def infer_enum_class(node):
    """ Specific inference for enums. """
    for basename in node.basenames:
        # TODO: doesn't handle subclasses yet. This implementation
        # is a hack to support enums.
        if basename not in ENUM_BASE_NAMES:
            continue
        if node.root().name == "enum":
            # Skip if the class is directly from enum module.
            break
        for local, values in node.locals.items():
            if any(not isinstance(value, nodes.AssignName) for value in values):
                continue

            targets = []
            stmt = values[0].statement()
            if isinstance(stmt, nodes.Assign):
                if isinstance(stmt.targets[0], nodes.Tuple):
                    targets = stmt.targets[0].itered()
                else:
                    targets = stmt.targets
            elif isinstance(stmt, nodes.AnnAssign):
                targets = [stmt.target]

            inferred_return_value = None
            if isinstance(stmt, nodes.Assign):
                if isinstance(stmt.value, nodes.Const):
                    if isinstance(stmt.value.value, str):
                        inferred_return_value = repr(stmt.value.value)
                    else:
                        inferred_return_value = stmt.value.value
                else:
                    inferred_return_value = stmt.value.as_string()

            new_targets = []
            for target in targets:
                # Replace all the assignments with our mocked class.
                classdef = dedent(
                    """
                class {name}({types}):
                    @property
                    def value(self):
                        return {return_value}
                    @property
                    def name(self):
                        return "{name}"
                """.format(
                        name=target.name,
                        types=", ".join(node.basenames),
                        return_value=inferred_return_value,
                    )
                )
                if "IntFlag" in basename:
                    # Alright, we need to add some additional methods.
                    # Unfortunately we still can't infer the resulting objects as
                    # Enum members, but once we'll be able to do that, the following
                    # should result in some nice symbolic execution
                    classdef += INT_FLAG_ADDITION_METHODS.format(name=target.name)

                fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name]
                fake.parent = target.parent
                for method in node.mymethods():
                    fake.locals[method.name] = [method]
                new_targets.append(fake.instantiate_class())
            node.locals[local] = new_targets
        break
    return node
def infer_enum_class ( node ) : for basename in node . basenames : if basename not in ENUM_BASE_NAMES : continue if node . root ( ) . name == "enum" : break for local , values in node . locals . items ( ) : if any ( not isinstance ( value , nodes . AssignName ) for value in values ) : continue targets = [ ] stmt = values [ 0 ] . statement ( ) if isinstance ( stmt , nodes . Assign ) : if isinstance ( stmt . targets [ 0 ] , nodes . Tuple ) : targets = stmt . targets [ 0 ] . itered ( ) else : targets = stmt . targets elif isinstance ( stmt , nodes . AnnAssign ) : targets = [ stmt . target ] inferred_return_value = None if isinstance ( stmt , nodes . Assign ) : if isinstance ( stmt . value , nodes . Const ) : if isinstance ( stmt . value . value , str ) : inferred_return_value = repr ( stmt . value . value ) else : inferred_return_value = stmt . value . value else : inferred_return_value = stmt . value . as_string ( ) new_targets = [ ] for target in targets : classdef = dedent ( """
                class {name}({types}):
                    @property
                    def value(self):
                        return {return_value}
                    @property
                    def name(self):
                        return "{name}"
                """ . format ( name = target . name , types = ", " . join ( node . basenames ) , return_value = inferred_return_value , ) ) if "IntFlag" in basename : classdef += INT_FLAG_ADDITION_METHODS . format ( name = target . name ) fake = AstroidBuilder ( MANAGER ) . string_build ( classdef ) [ target . name ] fake . parent = target . parent for method in node . mymethods ( ) : fake . locals [ method . name ] = [ method ] new_targets . append ( fake . instantiate_class ( ) ) node . locals [ local ] = new_targets break return node
Specific inference for enums.