From a9959550af6b16b5da4972ef41848940d8f6e4fb Mon Sep 17 00:00:00 2001 From: Sergei Trofimov Date: Wed, 9 Aug 2017 15:24:57 +0100 Subject: [PATCH] utils/types: better enum class member setting - What used to be enum.values is now enum.levels. - Add enum.names and enum.values that are lists of enum's levels' names and values respectively. - Add a check on creation to make sure that provided level names do not conflict with the atomatically created members. --- tests/test_utils.py | 14 +++++++++++--- wa/framework/configuration/core.py | 2 +- wa/framework/instrumentation.py | 2 +- wa/utils/types.py | 14 +++++++++++--- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 60dec0dc..c3469f9e 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -107,6 +107,14 @@ class TestEnumLevel(TestCase): e = enum(['one', 'two', 'three'], start=-10, step=10) assert_list_equal(e.values, [-10, 0, 10]) + def test_enum_name_conflicts(self): + assert_raises(ValueError, enum, ['names', 'one', 'two']) + + e = enum(['NAMES', 'one', 'two']) + assert_in('names', e.levels) + assert_list_equal(e.names, ['names', 'one', 'two']) + assert_equal(e.NAMES, 'names') + def test_enum_behavior(self): e = enum(['one', 'two', 'three']) @@ -118,9 +126,9 @@ class TestEnumLevel(TestCase): assert_not_equal(e.one, '0') # ditto for enum membership tests - assert_in('one', e.values) - assert_in(2, e.values) - assert_not_in('five', e.values) + assert_in('one', e.levels) + assert_in(2, e.levels) + assert_not_in('five', e.levels) # The same level object returned, only when # passing in a valid level name/value. diff --git a/wa/framework/configuration/core.py b/wa/framework/configuration/core.py index 3665436e..0e0bbf73 100644 --- a/wa/framework/configuration/core.py +++ b/wa/framework/configuration/core.py @@ -741,7 +741,7 @@ class RunConfiguration(Configuration): 'retry_on_status', kind=list_of(Status), default=['FAILED', 'PARTIAL'], - allowed_values=Status.values[Status.RUNNING.value:], + allowed_values=Status.levels[Status.RUNNING.value:], description=''' This is list of statuses on which a job will be considered to have failed and will be automatically retried up to ``max_retries`` diff --git a/wa/framework/instrumentation.py b/wa/framework/instrumentation.py index 3fe67de3..009a2446 100644 --- a/wa/framework/instrumentation.py +++ b/wa/framework/instrumentation.py @@ -186,7 +186,7 @@ def priority(priority): def wrapper(*args, **kwargs): return func(*args, **kwargs) wrapper.func_name = func.func_name - if priority in Priority.values: + if priority in Priority.levels: wrapper.priority = Priority(priority) else: if not isinstance(priority, int): diff --git a/wa/utils/types.py b/wa/utils/types.py index 98e2b079..2db72597 100644 --- a/wa/utils/types.py +++ b/wa/utils/types.py @@ -557,7 +557,7 @@ def enum(args, start=0, step=1): @classmethod def from_pod(cls, pod): lv = level.from_pod(pod) - for enum_level in cls.values: + for enum_level in cls.levels: if enum_level == lv: return enum_level msg = 'Unexpected value "{}" for enum.' @@ -574,16 +574,24 @@ def enum(args, start=0, step=1): raise ValueError('Invalid enum value: {}'.format(repr(name))) + reserved = ['values', 'levels', 'names'] + levels = [] n = start for v in args: - name = caseless_string(identifier(v)) + id_v = identifier(v) + if id_v in reserved: + message = 'Invalid enum level name "{}"; must not be in {}' + raise ValueError(message.format(v, reserved)) + name = caseless_string(id_v) lv = level(v, n) setattr(Enum, name, lv) levels.append(lv) n += step - setattr(Enum, 'values', levels) + setattr(Enum, 'levels', levels) + setattr(Enum, 'values', [lv.value for lv in levels]) + setattr(Enum, 'names', [lv.name for lv in levels]) return Enum