summaryrefslogtreecommitdiff
path: root/astroid
diff options
context:
space:
mode:
authorPhilip Lorenz <philip@bithub.de>2015-05-01 10:44:12 +0200
committerPhilip Lorenz <philip@bithub.de>2015-05-01 10:44:12 +0200
commitb7b303d5b590c11ba8d861dcd8fa440122567d6d (patch)
tree66b2b540adf3546a5a6603a9536a9f44f9487e03 /astroid
parent738a5cef5d0b08a373bf67b2c40d8f8adb070a7a (diff)
downloadastroid-enum-fixes.tar.gz
Ensure that generated enum values have the correct base classesenum-fixes
Enum values should share the same base classes as their defining class. If this is not the case it may lead to wrong inference results when an enum member is used - e.g. for the following snippet: class X(enum.IntEnum): one = 1 print([1, 2][X.one]) pylint will detect a "invalid-sequence-index" error as the __index__ method of X.one is not detected.
Diffstat (limited to 'astroid')
-rw-r--r--astroid/brain/py2stdlib.py4
-rw-r--r--astroid/tests/unittest_brain.py33
2 files changed, 35 insertions, 2 deletions
diff --git a/astroid/brain/py2stdlib.py b/astroid/brain/py2stdlib.py
index e63ea86..4231fe7 100644
--- a/astroid/brain/py2stdlib.py
+++ b/astroid/brain/py2stdlib.py
@@ -304,7 +304,7 @@ def infer_enum_class(node):
for target in targets:
# Replace all the assignments with our mocked class.
classdef = dedent('''
- class %(name)s(object):
+ class %(name)s(%(types)s):
@property
def value(self):
# Not the best return.
@@ -312,7 +312,7 @@ def infer_enum_class(node):
@property
def name(self):
return %(name)r
- ''' % {'name': target.name})
+ ''' % {'name': target.name, 'types': ', '.join(node.basenames)})
fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name]
fake.parent = target.parent
for method in node.mymethods():
diff --git a/astroid/tests/unittest_brain.py b/astroid/tests/unittest_brain.py
index 91a9a79..b0e0608 100644
--- a/astroid/tests/unittest_brain.py
+++ b/astroid/tests/unittest_brain.py
@@ -252,5 +252,38 @@ class EnumBrainTest(unittest.TestCase):
meth = one.getattr('mymethod')[0]
self.assertIsInstance(meth, astroid.Function)
+ def test_enum_multiple_base_classes(self):
+ module = AstroidBuilder().string_build(dedent("""
+ import enum
+
+ class Mixin:
+ pass
+
+ class MyEnum(Mixin, enum.Enum):
+ one = 1
+ """))
+ enum = next(module['MyEnum'].infer())
+ one = enum['one']
+
+ clazz = one.getattr('__class__')[0]
+ self.assertTrue(clazz.is_subtype_of('.Mixin'),
+ 'Enum instance should share base classes with generating class')
+
+ def test_int_enum(self):
+ module = AstroidBuilder().string_build(dedent("""
+ import enum
+
+ class MyEnum(enum.IntEnum):
+ one = 1
+ """))
+
+ enum = next(module['MyEnum'].infer())
+ one = enum['one']
+
+ clazz = one.getattr('__class__')[0]
+ int_type = '{}.{}'.format(bases.BUILTINS, 'int')
+ self.assertTrue(clazz.is_subtype_of(int_type),
+ 'IntEnum based enums should be a subtype of int')
+
if __name__ == '__main__':
unittest.main()