0

Running the command pip2.7 show enum34 outputs the version and where is installed correctly:

Name: enum34
Version: 1.1.2
Summary: Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4
Home-page: https://pypi.python.org/pypi/enum34
Author: Ethan Furman
Author-email: ethan@stoneleaf.us
License: BSD License
Location: /usr/lib/python2.7/dist-packages
Requires: 
Required-by: 

Nevertheless I am having the following error with enum:

AttributeError: 'enum' object has no attribute 'IntFlag'

This error happens when you dont have enum34 installed in python 2.7, but it is already installed.

I can import enum and running enum.__file__ outputs the path:

/usr/lib/python2.7/dist-packages/enum/__init__.pyc
  • Why is IntFlag missing in enum if enum34 is installed?
Michael Szer
  • 77
  • 2
  • 9
  • That doesn't sound like a problem with your `enum34` install. That sounds like you're looking at some object that isn't the `enum` module. Your code is probably broken. – user2357112 Jul 18 '18 at 22:43
  • Similar: https://stackoverflow.com/questions/43124775/why-python-3-6-1-throws-attributeerror-module-enum-has-no-attribute-intflag – Bailey Parker Jul 18 '18 at 22:44
  • `IntFlag` is indeed missing from `enum43`. Check the source yourself: https://bitbucket.org/stoneleaf/enum34/src/default/enum/__init__.py – Bailey Parker Jul 18 '18 at 22:44
  • 1
    Oh, and yeah, `enum34` doesn't have `IntFlag`, so there's that too. Even with `enum34` installed, though, you would have gotten a different error message if you really were accessing an attribute on the `enum` module. – user2357112 Jul 18 '18 at 22:47

1 Answers1

1

If you look at the docs for 3.4 enum, you'll see that IntFlag is not there. That is because it was added in 3.6.

So the error you are seeing is indeed correct and not a problem with your enum34 installation.

It also looks like the enum package in pypi also doesn't have IntFlag.

You can monkey patch this pretty easily though by copying the source for IntFlag into a module in your project:

from enum import Enum

class Flag(Enum):
    """Support for flags"""

    def _generate_next_value_(name, start, count, last_values):
        """
        Generate the next value when not given.
        name: the name of the member
        start: the initital start value or None
        count: the number of existing members
        last_value: the last value assigned or None
        """
        if not count:
            return start if start is not None else 1
        for last_value in reversed(last_values):
            try:
                high_bit = _high_bit(last_value)
                break
            except Exception:
                raise TypeError('Invalid Flag value: %r' % last_value) from None
        return 2 ** (high_bit+1)

    @classmethod
    def _missing_(cls, value):
        original_value = value
        if value < 0:
            value = ~value
        possible_member = cls._create_pseudo_member_(value)
        if original_value < 0:
            possible_member = ~possible_member
        return possible_member

    @classmethod
    def _create_pseudo_member_(cls, value):
        """
        Create a composite member iff value contains only members.
        """
        pseudo_member = cls._value2member_map_.get(value, None)
        if pseudo_member is None:
            # verify all bits are accounted for
            _, extra_flags = _decompose(cls, value)
            if extra_flags:
                raise ValueError("%r is not a valid %s" % (value, cls.__name__))
            # construct a singleton enum pseudo-member
            pseudo_member = object.__new__(cls)
            pseudo_member._name_ = None
            pseudo_member._value_ = value
            # use setdefault in case another thread already created a composite
            # with this value
            pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
        return pseudo_member

    def __contains__(self, other):
        if not isinstance(other, self.__class__):
            import warnings
            warnings.warn(
                    "using non-Flags in containment checks will raise "
                    "TypeError in Python 3.8",
                    DeprecationWarning, 2)
            return False
        return other._value_ & self._value_ == other._value_

    def __repr__(self):
        cls = self.__class__
        if self._name_ is not None:
            return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
        members, uncovered = _decompose(cls, self._value_)
        return '<%s.%s: %r>' % (
                cls.__name__,
                '|'.join([str(m._name_ or m._value_) for m in members]),
                self._value_,
                )

    def __str__(self):
        cls = self.__class__
        if self._name_ is not None:
            return '%s.%s' % (cls.__name__, self._name_)
        members, uncovered = _decompose(cls, self._value_)
        if len(members) == 1 and members[0]._name_ is None:
            return '%s.%r' % (cls.__name__, members[0]._value_)
        else:
            return '%s.%s' % (
                    cls.__name__,
                    '|'.join([str(m._name_ or m._value_) for m in members]),
                    )

    def __bool__(self):
        return bool(self._value_)

    def __or__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        return self.__class__(self._value_ | other._value_)

    def __and__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        return self.__class__(self._value_ & other._value_)

    def __xor__(self, other):
        if not isinstance(other, self.__class__):
            return NotImplemented
        return self.__class__(self._value_ ^ other._value_)

    def __invert__(self):
        members, uncovered = _decompose(self.__class__, self._value_)
        inverted = self.__class__(0)
        for m in self.__class__:
            if m not in members and not (m._value_ & self._value_):
                inverted = inverted | m
        return self.__class__(inverted)


class IntFlag(int, Flag):
    """Support for integer-based Flags"""

    @classmethod
    def _missing_(cls, value):
        if not isinstance(value, int):
            raise ValueError("%r is not a valid %s" % (value, cls.__name__))
        new_member = cls._create_pseudo_member_(value)
        return new_member

    @classmethod
    def _create_pseudo_member_(cls, value):
        pseudo_member = cls._value2member_map_.get(value, None)
        if pseudo_member is None:
            need_to_create = [value]
            # get unaccounted for bits
            _, extra_flags = _decompose(cls, value)
            # timer = 10
            while extra_flags:
                # timer -= 1
                bit = _high_bit(extra_flags)
                flag_value = 2 ** bit
                if (flag_value not in cls._value2member_map_ and
                        flag_value not in need_to_create
                        ):
                    need_to_create.append(flag_value)
                if extra_flags == -flag_value:
                    extra_flags = 0
                else:
                    extra_flags ^= flag_value
            for value in reversed(need_to_create):
                # construct singleton pseudo-members
                pseudo_member = int.__new__(cls, value)
                pseudo_member._name_ = None
                pseudo_member._value_ = value
                # use setdefault in case another thread already created a composite
                # with this value
                pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
        return pseudo_member

    def __or__(self, other):
        if not isinstance(other, (self.__class__, int)):
            return NotImplemented
        result = self.__class__(self._value_ | self.__class__(other)._value_)
        return result

    def __and__(self, other):
        if not isinstance(other, (self.__class__, int)):
            return NotImplemented
        return self.__class__(self._value_ & self.__class__(other)._value_)

    def __xor__(self, other):
        if not isinstance(other, (self.__class__, int)):
            return NotImplemented
        return self.__class__(self._value_ ^ self.__class__(other)._value_)

    __ror__ = __or__
    __rand__ = __and__
    __rxor__ = __xor__

    def __invert__(self):
        result = self.__class__(~self._value_)
        return result


def _high_bit(value):
    """returns index of highest bit, or -1 if value is zero or negative"""
    return value.bit_length() - 1

def unique(enumeration):
    """Class decorator for enumerations ensuring unique member values."""
    duplicates = []
    for name, member in enumeration.__members__.items():
        if name != member.name:
            duplicates.append((name, member.name))
    if duplicates:
        alias_details = ', '.join(
                ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
        raise ValueError('duplicate values found in %r: %s' %
                (enumeration, alias_details))
    return enumeration

def _decompose(flag, value):
    """Extract all members from the value."""
    # _decompose is only called if the value is not named
    not_covered = value
    negative = value < 0
    # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
    #             conditions between iterating over it and having more pseudo-
    #             members added to it
    if negative:
        # only check for named flags
        flags_to_check = [
                (m, v)
                for v, m in list(flag._value2member_map_.items())
                if m.name is not None
                ]
    else:
        # check for named flags and powers-of-two flags
        flags_to_check = [
                (m, v)
                for v, m in list(flag._value2member_map_.items())
                if m.name is not None or _power_of_two(v)
                ]
    members = []
    for member, member_value in flags_to_check:
        if member_value and member_value & value == member_value:
            members.append(member)
            not_covered &= ~member_value
    if not members and value in flag._value2member_map_:
        members.append(flag._value2member_map_[value])
    members.sort(key=lambda m: m._value_, reverse=True)
    if len(members) > 1 and members[0].value == value:
        # we have the breakdown, don't need the value member itself
        members.pop(0)
    return members, not_covered

def _power_of_two(value):
    if value < 1:
        return False
return value == 2 ** _high_bit(value)

Although, you're probably just better off copying the whole module into your own module (so that you aren't depending on undocumented under methods).

Further as @user2357112 mentioned, the error you're seeing indicates that you've probably overwritten the enum module in your code accidentally. Just to be clear, something like this will break, because you've assigned the name sys some other value than the module you imported:

import sys

sys = 1 # doesn't have to be 1, can be anything that's not sys

# sys is no longer the module you imported, this will fail
sys.stdout.write('hello world!\n')

I suspect in your code you're probably doing something like this:

import enum

class Foo(enum.Enum):
    BAR = 1

enum = Foo.Bar # or something like this

class Baz(enum.Enum):  # failure happens here, enum is now Foo.Bar
    pass
Bailey Parker
  • 15,599
  • 5
  • 53
  • 91
  • Do you know how I can upgrade enum? I know this sounds stupid but I have been searching and can't find anything useful. – Michael Szer Jul 19 '18 at 16:22
  • 1
    As I recommend at the bottom of my answer just make your own enum module in your package using its source and use that instead. – Bailey Parker Jul 19 '18 at 16:27