Best Python code snippet using hypothesis
enum.py
Source:enum.py  
1import sys2from types import MappingProxyType, DynamicClassAttribute3# try _collections first to reduce startup cost4try:5    from _collections import OrderedDict6except ImportError:7    from collections import OrderedDict8__all__ = [9        'EnumMeta',10        'Enum', 'IntEnum', 'Flag', 'IntFlag',11        'auto', 'unique',12        ]13def _is_descriptor(obj):14    """Returns True if obj is a descriptor, False otherwise."""15    return (16            hasattr(obj, '__get__') or17            hasattr(obj, '__set__') or18            hasattr(obj, '__delete__'))19def _is_dunder(name):20    """Returns True if a __dunder__ name, False otherwise."""21    return (len(name) > 4 and22            name[:2] == name[-2:] == '__' and23            name[2] != '_' and24            name[-3] != '_')25def _is_sunder(name):26    """Returns True if a _sunder_ name, False otherwise."""27    return (len(name) > 2 and28            name[0] == name[-1] == '_' and29            name[1:2] != '_' and30            name[-2:-1] != '_')31def _make_class_unpicklable(cls):32    """Make the given class un-picklable."""33    def _break_on_call_reduce(self, proto):34        raise TypeError('%r cannot be pickled' % self)35    cls.__reduce_ex__ = _break_on_call_reduce36    cls.__module__ = '<unknown>'37_auto_null = object()38class auto:39    """40    Instances are replaced with an appropriate value in Enum class suites.41    """42    value = _auto_null43class _EnumDict(dict):44    """Track enum member order and ensure member names are not reused.45    EnumMeta will use the names found in self._member_names as the46    enumeration member names.47    """48    def __init__(self):49        super().__init__()50        self._member_names = []51        self._last_values = []52        self._ignore = []53    def __setitem__(self, key, value):54        """Changes anything not dundered or not a descriptor.55        If an enum member name is used twice, an error is raised; duplicate56        values are not checked for.57        Single underscore (sunder) names are reserved.58        """59        if _is_sunder(key):60            if key not in (61                    '_order_', '_create_pseudo_member_',62                    '_generate_next_value_', '_missing_', '_ignore_',63                    ):64                raise ValueError('_names_ are reserved for future Enum use')65            if key == '_generate_next_value_':66                setattr(self, '_generate_next_value', value)67            elif key == '_ignore_':68                if isinstance(value, str):69                    value = value.replace(',',' ').split()70                else:71                    value = list(value)72                self._ignore = value73                already = set(value) & set(self._member_names)74                if already:75                    raise ValueError('_ignore_ cannot specify already set names: %r' % (already, ))76        elif _is_dunder(key):77            if key == '__order__':78                key = '_order_'79        elif key in self._member_names:80            # descriptor overwriting an enum?81            raise TypeError('Attempted to reuse key: %r' % key)82        elif key in self._ignore:83            pass84        elif not _is_descriptor(value):85            if key in self:86                # enum overwriting a descriptor?87                raise TypeError('%r already defined as: %r' % (key, self[key]))88            if isinstance(value, auto):89                if value.value == _auto_null:90                    value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])91                value = value.value92            self._member_names.append(key)93            self._last_values.append(value)94        super().__setitem__(key, value)95# Dummy value for Enum as EnumMeta explicitly checks for it, but of course96# until EnumMeta finishes running the first time the Enum class doesn't exist.97# This is also why there are checks in EnumMeta like `if Enum is not None`98Enum = None99class EnumMeta(type):100    """Metaclass for Enum"""101    @classmethod102    def __prepare__(metacls, cls, bases):103        # create the namespace dict104        enum_dict = _EnumDict()105        # inherit previous flags and _generate_next_value_ function106        member_type, first_enum = metacls._get_mixins_(bases)107        if first_enum is not None:108            enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None)109        return enum_dict110    def __new__(metacls, cls, bases, classdict):111        # an Enum class is final once enumeration items have been defined; it112        # cannot be mixed with other types (int, float, etc.) if it has an113        # inherited __new__ unless a new __new__ is defined (or the resulting114        # class will fail).115        #116        # remove any keys listed in _ignore_117        classdict.setdefault('_ignore_', []).append('_ignore_')118        ignore = classdict['_ignore_']119        for key in ignore:120            classdict.pop(key, None)121        member_type, first_enum = metacls._get_mixins_(bases)122        __new__, save_new, use_args = metacls._find_new_(classdict, member_type,123                                                        first_enum)124        # save enum items into separate mapping so they don't get baked into125        # the new class126        enum_members = {k: classdict[k] for k in classdict._member_names}127        for name in classdict._member_names:128            del classdict[name]129        # adjust the sunders130        _order_ = classdict.pop('_order_', None)131        # check for illegal enum names (any others?)132        invalid_names = set(enum_members) & {'mro', ''}133        if invalid_names:134            raise ValueError('Invalid enum member name: {0}'.format(135                ','.join(invalid_names)))136        # create a default docstring if one has not been provided137        if '__doc__' not in classdict:138            classdict['__doc__'] = 'An enumeration.'139        # create our new Enum type140        enum_class = super().__new__(metacls, cls, bases, classdict)141        enum_class._member_names_ = []               # names in definition order142        enum_class._member_map_ = OrderedDict()      # name->value map143        enum_class._member_type_ = member_type144        # save DynamicClassAttribute attributes from super classes so we know145        # if we can take the shortcut of storing members in the class dict146        dynamic_attributes = {k for c in enum_class.mro()147                              for k, v in c.__dict__.items()148                              if isinstance(v, DynamicClassAttribute)}149        # Reverse value->name map for hashable values.150        enum_class._value2member_map_ = {}151        # If a custom type is mixed into the Enum, and it does not know how152        # to pickle itself, pickle.dumps will succeed but pickle.loads will153        # fail.  Rather than have the error show up later and possibly far154        # from the source, sabotage the pickle protocol for this class so155        # that pickle.dumps also fails.156        #157        # However, if the new class implements its own __reduce_ex__, do not158        # sabotage -- it's on them to make sure it works correctly.  We use159        # __reduce_ex__ instead of any of the others as it is preferred by160        # pickle over __reduce__, and it handles all pickle protocols.161        if '__reduce_ex__' not in classdict:162            if member_type is not object:163                methods = ('__getnewargs_ex__', '__getnewargs__',164                        '__reduce_ex__', '__reduce__')165                if not any(m in member_type.__dict__ for m in methods):166                    _make_class_unpicklable(enum_class)167        # instantiate them, checking for duplicates as we go168        # we instantiate first instead of checking for duplicates first in case169        # a custom __new__ is doing something funky with the values -- such as170        # auto-numbering ;)171        for member_name in classdict._member_names:172            value = enum_members[member_name]173            if not isinstance(value, tuple):174                args = (value, )175            else:176                args = value177            if member_type is tuple:   # special case for tuple enums178                args = (args, )     # wrap it one more time179            if not use_args:180                enum_member = __new__(enum_class)181                if not hasattr(enum_member, '_value_'):182                    enum_member._value_ = value183            else:184                enum_member = __new__(enum_class, *args)185                if not hasattr(enum_member, '_value_'):186                    if member_type is object:187                        enum_member._value_ = value188                    else:189                        enum_member._value_ = member_type(*args)190            value = enum_member._value_191            enum_member._name_ = member_name192            enum_member.__objclass__ = enum_class193            enum_member.__init__(*args)194            # If another member with the same value was already defined, the195            # new member becomes an alias to the existing one.196            for name, canonical_member in enum_class._member_map_.items():197                if canonical_member._value_ == enum_member._value_:198                    enum_member = canonical_member199                    break200            else:201                # Aliases don't appear in member names (only in __members__).202                enum_class._member_names_.append(member_name)203            # performance boost for any member that would not shadow204            # a DynamicClassAttribute205            if member_name not in dynamic_attributes:206                setattr(enum_class, member_name, enum_member)207            # now add to _member_map_208            enum_class._member_map_[member_name] = enum_member209            try:210                # This may fail if value is not hashable. We can't add the value211                # to the map, and by-value lookups for this value will be212                # linear.213                enum_class._value2member_map_[value] = enum_member214            except TypeError:215                pass216        # double check that repr and friends are not the mixin's or various217        # things break (such as pickle)218        for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):219            class_method = getattr(enum_class, name)220            obj_method = getattr(member_type, name, None)221            enum_method = getattr(first_enum, name, None)222            if obj_method is not None and obj_method is class_method:223                setattr(enum_class, name, enum_method)224        # replace any other __new__ with our own (as long as Enum is not None,225        # anyway) -- again, this is to support pickle226        if Enum is not None:227            # if the user defined their own __new__, save it before it gets228            # clobbered in case they subclass later229            if save_new:230                enum_class.__new_member__ = __new__231            enum_class.__new__ = Enum.__new__232        # py3 support for definition order (helps keep py2/py3 code in sync)233        if _order_ is not None:234            if isinstance(_order_, str):235                _order_ = _order_.replace(',', ' ').split()236            if _order_ != enum_class._member_names_:237                raise TypeError('member order does not match _order_')238        return enum_class239    def __bool__(self):240        """241        classes/types should always be True.242        """243        return True244    def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):245        """Either returns an existing member, or creates a new enum class.246        This method is used both when an enum class is given a value to match247        to an enumeration member (i.e. Color(3)) and for the functional API248        (i.e. Color = Enum('Color', names='RED GREEN BLUE')).249        When used for the functional API:250        `value` will be the name of the new class.251        `names` should be either a string of white-space/comma delimited names252        (values will start at `start`), or an iterator/mapping of name, value pairs.253        `module` should be set to the module this class is being created in;254        if it is not set, an attempt to find that module will be made, but if255        it fails the class will not be picklable.256        `qualname` should be set to the actual location this class can be found257        at in its module; by default it is set to the global scope.  If this is258        not correct, unpickling will fail in some circumstances.259        `type`, if set, will be mixed in as the first base class.260        """261        if names is None:  # simple value lookup262            return cls.__new__(cls, value)263        # otherwise, functional API: we're creating a new Enum type264        return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)265    def __contains__(cls, member):266        if not isinstance(member, Enum):267            import warnings268            warnings.warn(269                    "using non-Enums in containment checks will raise "270                    "TypeError in Python 3.8",271                    DeprecationWarning, 2)272        return isinstance(member, cls) and member._name_ in cls._member_map_273    def __delattr__(cls, attr):274        # nicer error message when someone tries to delete an attribute275        # (see issue19025).276        if attr in cls._member_map_:277            raise AttributeError(278                    "%s: cannot delete Enum member." % cls.__name__)279        super().__delattr__(attr)280    def __dir__(self):281        return (['__class__', '__doc__', '__members__', '__module__'] +282                self._member_names_)283    def __getattr__(cls, name):284        """Return the enum member matching `name`285        We use __getattr__ instead of descriptors or inserting into the enum286        class' __dict__ in order to support `name` and `value` being both287        properties for enum members (which live in the class' __dict__) and288        enum members themselves.289        """290        if _is_dunder(name):291            raise AttributeError(name)292        try:293            return cls._member_map_[name]294        except KeyError:295            raise AttributeError(name) from None296    def __getitem__(cls, name):297        return cls._member_map_[name]298    def __iter__(cls):299        return (cls._member_map_[name] for name in cls._member_names_)300    def __len__(cls):301        return len(cls._member_names_)302    @property303    def __members__(cls):304        """Returns a mapping of member name->value.305        This mapping lists all enum members, including aliases. Note that this306        is a read-only view of the internal mapping.307        """308        return MappingProxyType(cls._member_map_)309    def __repr__(cls):310        return "<enum %r>" % cls.__name__311    def __reversed__(cls):312        return (cls._member_map_[name] for name in reversed(cls._member_names_))313    def __setattr__(cls, name, value):314        """Block attempts to reassign Enum members.315        A simple assignment to the class namespace only changes one of the316        several possible ways to get an Enum member from the Enum class,317        resulting in an inconsistent Enumeration.318        """319        member_map = cls.__dict__.get('_member_map_', {})320        if name in member_map:321            raise AttributeError('Cannot reassign members.')322        super().__setattr__(name, value)323    def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):324        """Convenience method to create a new Enum class.325        `names` can be:326        * A string containing member names, separated either with spaces or327          commas.  Values are incremented by 1 from `start`.328        * An iterable of member names.  Values are incremented by 1 from `start`.329        * An iterable of (member name, value) pairs.330        * A mapping of member name -> value pairs.331        """332        metacls = cls.__class__333        bases = (cls, ) if type is None else (type, cls)334        _, first_enum = cls._get_mixins_(bases)335        classdict = metacls.__prepare__(class_name, bases)336        # special processing needed for names?337        if isinstance(names, str):338            names = names.replace(',', ' ').split()339        if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):340            original_names, names = names, []341            last_values = []342            for count, name in enumerate(original_names):343                value = first_enum._generate_next_value_(name, start, count, last_values[:])344                last_values.append(value)345                names.append((name, value))346        # Here, names is either an iterable of (name, value) or a mapping.347        for item in names:348            if isinstance(item, str):349                member_name, member_value = item, names[item]350            else:351                member_name, member_value = item352            classdict[member_name] = member_value353        enum_class = metacls.__new__(metacls, class_name, bases, classdict)354        # TODO: replace the frame hack if a blessed way to know the calling355        # module is ever developed356        if module is None:357            try:358                module = sys._getframe(2).f_globals['__name__']359            except (AttributeError, ValueError, KeyError) as exc:360                pass361        if module is None:362            _make_class_unpicklable(enum_class)363        else:364            enum_class.__module__ = module365        if qualname is not None:366            enum_class.__qualname__ = qualname367        return enum_class368    @staticmethod369    def _get_mixins_(bases):370        """Returns the type for creating enum members, and the first inherited371        enum class.372        bases: the tuple of bases that was given to __new__373        """374        if not bases:375            return object, Enum376        def _find_data_type(bases):377            for chain in bases:378                for base in chain.__mro__:379                    if base is object:380                        continue381                    elif '__new__' in base.__dict__:382                        if issubclass(base, Enum):383                            continue384                        return base385        # ensure final parent class is an Enum derivative, find any concrete386        # data type, and check that Enum has no members387        first_enum = bases[-1]388        if not issubclass(first_enum, Enum):389            raise TypeError("new enumerations should be created as "390                    "`EnumName([mixin_type, ...] [data_type,] enum_type)`")391        member_type = _find_data_type(bases) or object392        if first_enum._member_names_:393            raise TypeError("Cannot extend enumerations")394        return member_type, first_enum395    @staticmethod396    def _find_new_(classdict, member_type, first_enum):397        """Returns the __new__ to be used for creating the enum members.398        classdict: the class dictionary given to __new__399        member_type: the data type whose __new__ will be used by default400        first_enum: enumeration to check for an overriding __new__401        """402        # now find the correct __new__, checking to see of one was defined403        # by the user; also check earlier enum classes in case a __new__ was404        # saved as __new_member__405        __new__ = classdict.get('__new__', None)406        # should __new__ be saved as __new_member__ later?407        save_new = __new__ is not None408        if __new__ is None:409            # check all possibles for __new_member__ before falling back to410            # __new__411            for method in ('__new_member__', '__new__'):412                for possible in (member_type, first_enum):413                    target = getattr(possible, method, None)414                    if target not in {415                            None,416                            None.__new__,417                            object.__new__,418                            Enum.__new__,419                            }:420                        __new__ = target421                        break422                if __new__ is not None:423                    break424            else:425                __new__ = object.__new__426        # if a non-object.__new__ is used then whatever value/tuple was427        # assigned to the enum member name will be passed to __new__ and to the428        # new enum member's __init__429        if __new__ is object.__new__:430            use_args = False431        else:432            use_args = True433        return __new__, save_new, use_args434class Enum(metaclass=EnumMeta):435    """Generic enumeration.436    Derive from this class to define new enumerations.437    """438    def __new__(cls, value):439        # all enum instances are actually created during class construction440        # without calling this method; this method is called by the metaclass'441        # __call__ (i.e. Color(3) ), and by pickle442        if type(value) is cls:443            # For lookups like Color(Color.RED)444            return value445        # by-value search for a matching enum member446        # see if it's in the reverse mapping (for hashable values)447        try:448            return cls._value2member_map_[value]449        except KeyError:450            # Not found, no need to do long O(n) search451            pass452        except TypeError:453            # not there, now do long search -- O(n) behavior454            for member in cls._member_map_.values():455                if member._value_ == value:456                    return member457        # still not found -- try _missing_ hook458        try:459            exc = None460            result = cls._missing_(value)461        except Exception as e:462            exc = e463            result = None464        if isinstance(result, cls):465            return result466        else:467            ve_exc = ValueError("%r is not a valid %s" % (value, cls.__name__))468            if result is None and exc is None:469                raise ve_exc470            elif exc is None:471                exc = TypeError(472                        'error in %s._missing_: returned %r instead of None or a valid member'473                        % (cls.__name__, result)474                        )475            exc.__context__ = ve_exc476            raise exc477    def _generate_next_value_(name, start, count, last_values):478        for last_value in reversed(last_values):479            try:480                return last_value + 1481            except TypeError:482                pass483        else:484            return start485    @classmethod486    def _missing_(cls, value):487        raise ValueError("%r is not a valid %s" % (value, cls.__name__))488    def __repr__(self):489        return "<%s.%s: %r>" % (490                self.__class__.__name__, self._name_, self._value_)491    def __str__(self):492        return "%s.%s" % (self.__class__.__name__, self._name_)493    def __dir__(self):494        added_behavior = [495                m496                for cls in self.__class__.mro()497                for m in cls.__dict__498                if m[0] != '_' and m not in self._member_map_499                ]500        return (['__class__', '__doc__', '__module__'] + added_behavior)501    def __format__(self, format_spec):502        # mixed-in Enums should use the mixed-in type's __format__, otherwise503        # we can get strange results with the Enum name showing up instead of504        # the value505        # pure Enum branch506        if self._member_type_ is object:507            cls = str508            val = str(self)509        # mix-in branch510        else:511            cls = self._member_type_512            val = self._value_513        return cls.__format__(val, format_spec)514    def __hash__(self):515        return hash(self._name_)516    def __reduce_ex__(self, proto):517        return self.__class__, (self._value_, )518    # DynamicClassAttribute is used to provide access to the `name` and519    # `value` properties of enum members while keeping some measure of520    # protection from modification, while still allowing for an enumeration521    # to have members named `name` and `value`.  This works because enumeration522    # members are not set directly on the enum class -- __getattr__ is523    # used to look them up.524    @DynamicClassAttribute525    def name(self):526        """The name of the Enum member."""527        return self._name_528    @DynamicClassAttribute529    def value(self):530        """The value of the Enum member."""531        return self._value_532    @classmethod533    def _convert(cls, name, module, filter, source=None):534        """535        Create a new Enum subclass that replaces a collection of global constants536        """537        # convert all constants from source (or module) that pass filter() to538        # a new Enum called name, and export the enum and its members back to539        # module;540        # also, replace the __reduce_ex__ method so unpickling works in541        # previous Python versions542        module_globals = vars(sys.modules[module])543        if source:544            source = vars(source)545        else:546            source = module_globals547        # We use an OrderedDict of sorted source keys so that the548        # _value2member_map is populated in the same order every time549        # for a consistent reverse mapping of number to name when there550        # are multiple names for the same number rather than varying551        # between runs due to hash randomization of the module dictionary.552        members = [553                (name, source[name])554                for name in source.keys()555                if filter(name)]556        try:557            # sort by value558            members.sort(key=lambda t: (t[1], t[0]))559        except TypeError:560            # unless some values aren't comparable, in which case sort by name561            members.sort(key=lambda t: t[0])562        cls = cls(name, members, module=module)563        cls.__reduce_ex__ = _reduce_ex_by_name564        module_globals.update(cls.__members__)565        module_globals[name] = cls566        return cls567class IntEnum(int, Enum):568    """Enum where members are also (and must be) ints"""569def _reduce_ex_by_name(self, proto):570    return self.name571class Flag(Enum):572    """Support for flags"""573    def _generate_next_value_(name, start, count, last_values):574        """575        Generate the next value when not given.576        name: the name of the member577        start: the initital start value or None578        count: the number of existing members579        last_value: the last value assigned or None580        """581        if not count:582            return start if start is not None else 1583        for last_value in reversed(last_values):584            try:585                high_bit = _high_bit(last_value)586                break587            except Exception:588                raise TypeError('Invalid Flag value: %r' % last_value) from None589        return 2 ** (high_bit+1)590    @classmethod591    def _missing_(cls, value):592        original_value = value593        if value < 0:594            value = ~value595        possible_member = cls._create_pseudo_member_(value)596        if original_value < 0:597            possible_member = ~possible_member598        return possible_member599    @classmethod600    def _create_pseudo_member_(cls, value):601        """602        Create a composite member iff value contains only members.603        """604        pseudo_member = cls._value2member_map_.get(value, None)605        if pseudo_member is None:606            # verify all bits are accounted for607            _, extra_flags = _decompose(cls, value)608            if extra_flags:609                raise ValueError("%r is not a valid %s" % (value, cls.__name__))610            # construct a singleton enum pseudo-member611            pseudo_member = object.__new__(cls)612            pseudo_member._name_ = None613            pseudo_member._value_ = value614            # use setdefault in case another thread already created a composite615            # with this value616            pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)617        return pseudo_member618    def __contains__(self, other):619        if not isinstance(other, self.__class__):620            import warnings621            warnings.warn(622                    "using non-Flags in containment checks will raise "623                    "TypeError in Python 3.8",624                    DeprecationWarning, 2)625            return False626        return other._value_ & self._value_ == other._value_627    def __repr__(self):628        cls = self.__class__629        if self._name_ is not None:630            return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)631        members, uncovered = _decompose(cls, self._value_)632        return '<%s.%s: %r>' % (633                cls.__name__,634                '|'.join([str(m._name_ or m._value_) for m in members]),635                self._value_,636                )637    def __str__(self):638        cls = self.__class__639        if self._name_ is not None:640            return '%s.%s' % (cls.__name__, self._name_)641        members, uncovered = _decompose(cls, self._value_)642        if len(members) == 1 and members[0]._name_ is None:643            return '%s.%r' % (cls.__name__, members[0]._value_)644        else:645            return '%s.%s' % (646                    cls.__name__,647                    '|'.join([str(m._name_ or m._value_) for m in members]),648                    )649    def __bool__(self):650        return bool(self._value_)651    def __or__(self, other):652        if not isinstance(other, self.__class__):653            return NotImplemented654        return self.__class__(self._value_ | other._value_)655    def __and__(self, other):656        if not isinstance(other, self.__class__):657            return NotImplemented658        return self.__class__(self._value_ & other._value_)659    def __xor__(self, other):660        if not isinstance(other, self.__class__):661            return NotImplemented662        return self.__class__(self._value_ ^ other._value_)663    def __invert__(self):664        members, uncovered = _decompose(self.__class__, self._value_)665        inverted = self.__class__(0)666        for m in self.__class__:667            if m not in members and not (m._value_ & self._value_):668                inverted = inverted | m669        return self.__class__(inverted)670class IntFlag(int, Flag):671    """Support for integer-based Flags"""672    @classmethod673    def _missing_(cls, value):674        if not isinstance(value, int):675            raise ValueError("%r is not a valid %s" % (value, cls.__name__))676        new_member = cls._create_pseudo_member_(value)677        return new_member678    @classmethod679    def _create_pseudo_member_(cls, value):680        pseudo_member = cls._value2member_map_.get(value, None)681        if pseudo_member is None:682            need_to_create = [value]683            # get unaccounted for bits684            _, extra_flags = _decompose(cls, value)685            # timer = 10686            while extra_flags:687                # timer -= 1688                bit = _high_bit(extra_flags)689                flag_value = 2 ** bit690                if (flag_value not in cls._value2member_map_ and691                        flag_value not in need_to_create692                        ):693                    need_to_create.append(flag_value)694                if extra_flags == -flag_value:695                    extra_flags = 0696                else:697                    extra_flags ^= flag_value698            for value in reversed(need_to_create):699                # construct singleton pseudo-members700                pseudo_member = int.__new__(cls, value)701                pseudo_member._name_ = None702                pseudo_member._value_ = value703                # use setdefault in case another thread already created a composite704                # with this value705                pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)706        return pseudo_member707    def __or__(self, other):708        if not isinstance(other, (self.__class__, int)):709            return NotImplemented710        result = self.__class__(self._value_ | self.__class__(other)._value_)711        return result712    def __and__(self, other):713        if not isinstance(other, (self.__class__, int)):714            return NotImplemented715        return self.__class__(self._value_ & self.__class__(other)._value_)716    def __xor__(self, other):717        if not isinstance(other, (self.__class__, int)):718            return NotImplemented719        return self.__class__(self._value_ ^ self.__class__(other)._value_)720    __ror__ = __or__721    __rand__ = __and__722    __rxor__ = __xor__723    def __invert__(self):724        result = self.__class__(~self._value_)725        return result726def _high_bit(value):727    """returns index of highest bit, or -1 if value is zero or negative"""728    return value.bit_length() - 1729def unique(enumeration):730    """Class decorator for enumerations ensuring unique member values."""731    duplicates = []732    for name, member in enumeration.__members__.items():733        if name != member.name:734            duplicates.append((name, member.name))735    if duplicates:736        alias_details = ', '.join(737                ["%s -> %s" % (alias, name) for (alias, name) in duplicates])738        raise ValueError('duplicate values found in %r: %s' %739                (enumeration, alias_details))740    return enumeration741def _decompose(flag, value):742    """Extract all members from the value."""743    # _decompose is only called if the value is not named744    not_covered = value745    negative = value < 0746    # issue29167: wrap accesses to _value2member_map_ in a list to avoid race747    #             conditions between iterating over it and having more pseudo-748    #             members added to it749    if negative:750        # only check for named flags751        flags_to_check = [752                (m, v)753                for v, m in list(flag._value2member_map_.items())754                if m.name is not None755                ]756    else:757        # check for named flags and powers-of-two flags758        flags_to_check = [759                (m, v)760                for v, m in list(flag._value2member_map_.items())761                if m.name is not None or _power_of_two(v)762                ]763    members = []764    for member, member_value in flags_to_check:765        if member_value and member_value & value == member_value:766            members.append(member)767            not_covered &= ~member_value768    if not members and value in flag._value2member_map_:769        members.append(flag._value2member_map_[value])770    members.sort(key=lambda m: m._value_, reverse=True)771    if len(members) > 1 and members[0].value == value:772        # we have the breakdown, don't need the value member itself773        members.pop(0)774    return members, not_covered775def _power_of_two(value):776    if value < 1:777        return False...apache2_mod_proxy.py
Source:apache2_mod_proxy.py  
1#!/usr/bin/python2# -*- coding: utf-8 -*-3# (c) 2016, Olivier Boukili <boukili.olivier@gmail.com>4#5# This file is part of Ansible.6#7# Ansible is free software: you can redistribute it and/or modify8# it under the terms of the GNU General Public License as published by9# the Free Software Foundation, either version 3 of the License, or10# (at your option) any later version.11#12# Ansible is distributed in the hope that it will be useful,13# but WITHOUT ANY WARRANTY; without even the implied warranty of14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the15# GNU General Public License for more details.16#17# You should have received a copy of the GNU General Public License18# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.19ANSIBLE_METADATA = {'metadata_version': '1.0',20                    'status': ['preview'],21                    'supported_by': 'community'}22DOCUMENTATION = '''23---24module: apache2_mod_proxy25author: Olivier Boukili (@oboukili)"26version_added: "2.2"27short_description: Set and/or get members' attributes of an Apache httpd 2.4 mod_proxy balancer pool28description:29  - Set and/or get members' attributes of an Apache httpd 2.4 mod_proxy balancer30    pool, using HTTP POST and GET requests. The httpd mod_proxy balancer-member31    status page has to be enabled and accessible, as this module relies on parsing32    this page. This module supports ansible check_mode, and requires BeautifulSoup33    python module.34options:35  balancer_url_suffix:36    default: /balancer-manager/37    description:38      - Suffix of the balancer pool url required to access the balancer pool39        status page (e.g. balancer_vhost[:port]/balancer_url_suffix).40    required: false41  balancer_vhost:42    default: None43    description:44      - (ipv4|ipv6|fqdn):port of the Apache httpd 2.4 mod_proxy balancer pool.45    required: true46  member_host:47    default: None48    description:49      - (ipv4|ipv6|fqdn) of the balancer member to get or to set attributes to.50        Port number is autodetected and should not be specified here.51        If undefined, apache2_mod_proxy module will return a members list of52        dictionaries of all the current balancer pool members' attributes.53    required: false54  state:55    default: None56    description:57      - Desired state of the member host.58        (absent|disabled),drained,hot_standby,ignore_errors can be59        simultaneously invoked by separating them with a comma (e.g. state=drained,ignore_errors).60    required: false61    choices: ["present", "absent", "enabled", "disabled", "drained", "hot_standby", "ignore_errors"]62  tls:63    default: false64    description:65      - Use https to access balancer management page.66    choices: ["true", "false"]67  validate_certs:68    default: true69    description:70      - Validate ssl/tls certificates.71    choices: ["true", "false"]72'''73EXAMPLES = '''74# Get all current balancer pool members' attributes:75- apache2_mod_proxy:76    balancer_vhost: 10.0.0.277# Get a specific member's attributes:78- apache2_mod_proxy:79    balancer_vhost: myws.mydomain.org80    balancer_suffix: /lb/81    member_host: node1.myws.mydomain.org82# Enable all balancer pool members:83- apache2_mod_proxy:84    balancer_vhost: '{{ myloadbalancer_host }}'85  register: result86- apache2_mod_proxy:87    balancer_vhost: '{{ myloadbalancer_host }}'88    member_host: '{{ item.host }}'89    state: present90  with_items: '{{ result.members }}'91# Gracefully disable a member from a loadbalancer node:92- apache2_mod_proxy:93    balancer_vhost: '{{ vhost_host }}'94    member_host: '{{ member.host }}'95    state: drained96  delegate_to: myloadbalancernode97- wait_for:98    host: '{{ member.host }}'99    port: '{{ member.port }}'100    state: drained101  delegate_to: myloadbalancernode102- apache2_mod_proxy:103    balancer_vhost: '{{ vhost_host }}'104    member_host: '{{ member.host }}'105    state: absent106  delegate_to: myloadbalancernode107'''108RETURN = '''109member:110    description: specific balancer member information dictionary, returned when apache2_mod_proxy module is invoked with member_host parameter.111    type: dict112    returned: success113    sample:114      {"attributes":115            {"Busy": "0",116            "Elected": "42",117            "Factor": "1",118            "From": "136K",119            "Load": "0",120            "Route": null,121            "RouteRedir": null,122            "Set": "0",123            "Status": "Init Ok ",124            "To": " 47K",125            "Worker URL": null126        },127        "balancer_url": "http://10.10.0.2/balancer-manager/",128        "host": "10.10.0.20",129        "management_url": "http://10.10.0.2/lb/?b=mywsbalancer&w=http://10.10.0.20:8080/ws&nonce=8925436c-79c6-4841-8936-e7d13b79239b",130        "path": "/ws",131        "port": 8080,132        "protocol": "http",133        "status": {134            "disabled": false,135            "drained": false,136            "hot_standby": false,137            "ignore_errors": false138        }139      }140members:141    description: list of member (defined above) dictionaries, returned when apache2_mod_proxy is invoked with no member_host and state args.142    returned: success143    type: list144    sample:145      [{"attributes": {146            "Busy": "0",147            "Elected": "42",148            "Factor": "1",149            "From": "136K",150            "Load": "0",151            "Route": null,152            "RouteRedir": null,153            "Set": "0",154            "Status": "Init Ok ",155            "To": " 47K",156            "Worker URL": null157        },158        "balancer_url": "http://10.10.0.2/balancer-manager/",159        "host": "10.10.0.20",160        "management_url": "http://10.10.0.2/lb/?b=mywsbalancer&w=http://10.10.0.20:8080/ws&nonce=8925436c-79c6-4841-8936-e7d13b79239b",161        "path": "/ws",162        "port": 8080,163        "protocol": "http",164        "status": {165            "disabled": false,166            "drained": false,167            "hot_standby": false,168            "ignore_errors": false169        }170        },171        {"attributes": {172            "Busy": "0",173            "Elected": "42",174            "Factor": "1",175            "From": "136K",176            "Load": "0",177            "Route": null,178            "RouteRedir": null,179            "Set": "0",180            "Status": "Init Ok ",181            "To": " 47K",182            "Worker URL": null183        },184        "balancer_url": "http://10.10.0.2/balancer-manager/",185        "host": "10.10.0.21",186        "management_url": "http://10.10.0.2/lb/?b=mywsbalancer&w=http://10.10.0.21:8080/ws&nonce=8925436c-79c6-4841-8936-e7d13b79239b",187        "path": "/ws",188        "port": 8080,189        "protocol": "http",190        "status": {191            "disabled": false,192            "drained": false,193            "hot_standby": false,194            "ignore_errors": false}195        }196      ]197'''198import re199try:200    from BeautifulSoup import BeautifulSoup201except ImportError:202    HAS_BEAUTIFULSOUP = False203else:204    HAS_BEAUTIFULSOUP = True205# balancer member attributes extraction regexp:206EXPRESSION = r"(b=([\w\.\-]+)&w=(https?|ajp|wss?|ftp|[sf]cgi)://([\w\.\-]+):?(\d*)([/\w\.\-]*)&?[\w\-\=]*)"207# Apache2 server version extraction regexp:208APACHE_VERSION_EXPRESSION = r"Server Version: Apache/([\d.]+) \(([\w]+)\)"209def regexp_extraction(string, _regexp, groups=1):210    """ Returns the capture group (default=1) specified in the regexp, applied to the string """211    regexp_search = re.search(string=str(string), pattern=str(_regexp))212    if regexp_search:213        if regexp_search.group(groups) != '':214            return str(regexp_search.group(groups))215    return None216class BalancerMember(object):217    """ Apache 2.4 mod_proxy LB balancer member.218    attributes:219        read-only:220            host -> member host (string),221            management_url -> member management url (string),222            protocol -> member protocol (string)223            port -> member port (string),224            path -> member location (string),225            balancer_url -> url of this member's parent balancer (string),226            attributes -> whole member attributes (dictionary)227            module -> ansible module instance (AnsibleModule object).228        writable:229            status -> status of the member (dictionary)230    """231    def __init__(self, management_url, balancer_url, module):232        self.host = regexp_extraction(management_url, str(EXPRESSION), 4)233        self.management_url = str(management_url)234        self.protocol = regexp_extraction(management_url, EXPRESSION, 3)235        self.port = regexp_extraction(management_url, EXPRESSION, 5)236        self.path = regexp_extraction(management_url, EXPRESSION, 6)237        self.balancer_url = str(balancer_url)238        self.module = module239    def get_member_attributes(self):240        """ Returns a dictionary of a balancer member's attributes."""241        balancer_member_page = fetch_url(self.module, self.management_url)242        try:243            assert balancer_member_page[1]['status'] == 200244        except AssertionError:245            self.module.fail_json(msg="Could not get balancer_member_page, check for connectivity! " + balancer_member_page[1])246        else:247            try:248                soup = BeautifulSoup(balancer_member_page[0])249            except TypeError:250                self.module.fail_json(msg="Cannot parse balancer_member_page HTML! " + str(soup))251            else:252                subsoup = soup.findAll('table')[1].findAll('tr')253                keys = subsoup[0].findAll('th')254                for valuesset in subsoup[1::1]:255                    if re.search(pattern=self.host, string=str(valuesset)):256                        values = valuesset.findAll('td')257                        return dict((keys[x].string, values[x].string) for x in range(0, len(keys)))258    def get_member_status(self):259        """ Returns a dictionary of a balancer member's status attributes."""260        status_mapping = {'disabled':'Dis',261                          'drained':'Drn',262                          'hot_standby':'Stby',263                          'ignore_errors':'Ign'}264        status = {}265        actual_status = str(self.attributes['Status'])266        for mode in status_mapping.keys():267            if re.search(pattern=status_mapping[mode], string=actual_status):268                status[mode] = True269            else:270                status[mode] = False271        return status272    def set_member_status(self, values):273        """ Sets a balancer member's status attributes amongst pre-mapped values."""274        values_mapping = {'disabled':'&w_status_D',275                          'drained':'&w_status_N',276                          'hot_standby':'&w_status_H',277                          'ignore_errors':'&w_status_I'}278        request_body = regexp_extraction(self.management_url, EXPRESSION, 1)279        for k in values_mapping.keys():280            if values[str(k)]:281                request_body = request_body + str(values_mapping[k]) + '=1'282            else:283                request_body = request_body + str(values_mapping[k]) + '=0'284        response = fetch_url(self.module, self.management_url, data=str(request_body))285        try:286            assert response[1]['status'] == 200287        except AssertionError:288            self.module.fail_json(msg="Could not set the member status! " + self.host + " " + response[1]['status'])289    attributes = property(get_member_attributes)290    status = property(get_member_status, set_member_status)291class Balancer(object):292    """ Apache httpd 2.4 mod_proxy balancer object"""293    def __init__(self, host, suffix, module, members=None, tls=False):294        if tls:295            self.base_url = str(str('https://') + str(host))296            self.url = str(str('https://') + str(host) + str(suffix))297        else:298            self.base_url = str(str('http://') + str(host))299            self.url = str(str('http://') + str(host) + str(suffix))300        self.module = module301        self.page = self.fetch_balancer_page()302        if members is None:303            self._members = []304    def fetch_balancer_page(self):305        """ Returns the balancer management html page as a string for later parsing."""306        page = fetch_url(self.module, str(self.url))307        try:308            assert page[1]['status'] == 200309        except AssertionError:310            self.module.fail_json(msg="Could not get balancer page! HTTP status response: " + str(page[1]['status']))311        else:312            content = page[0].read()313            apache_version = regexp_extraction(content, APACHE_VERSION_EXPRESSION, 1)314            if not re.search(pattern=r"2\.4\.[\d]*", string=apache_version):315                self.module.fail_json(msg="This module only acts on an Apache2 2.4+ instance, current Apache2 version: " + str(apache_version))316            return content317    def get_balancer_members(self):318        """ Returns members of the balancer as a generator object for later iteration."""319        try:320            soup = BeautifulSoup(self.page)321        except TypeError:322            self.module.fail_json(msg="Cannot parse balancer page HTML! " + str(self.page))323        else:324            for element in soup.findAll('a')[1::1]:325                balancer_member_suffix = str(element.get('href'))326                try:327                    assert balancer_member_suffix is not ''328                except AssertionError:329                    self.module.fail_json(msg="Argument 'balancer_member_suffix' is empty!")330                else:331                    yield BalancerMember(str(self.base_url + balancer_member_suffix), str(self.url), self.module)332    members = property(get_balancer_members)333def main():334    """ Initiates module."""335    module = AnsibleModule(336        argument_spec=dict(337            balancer_vhost=dict(required=True, default=None, type='str'),338            balancer_url_suffix=dict(default="/balancer-manager/", type='str'),339            member_host=dict(type='str'),340            state=dict(type='str'),341            tls=dict(default=False, type='bool'),342            validate_certs=dict(default=True, type='bool')343        ),344        supports_check_mode=True345    )346    if HAS_BEAUTIFULSOUP is False:347        module.fail_json(msg="python module 'BeautifulSoup' is required!")348    if module.params['state'] is not None:349        states = module.params['state'].split(',')350        if (len(states) > 1) and (("present" in states) or ("enabled" in states)):351            module.fail_json(msg="state present/enabled is mutually exclusive with other states!")352        else:353            for _state in states:354                if _state not in ['present', 'absent', 'enabled', 'disabled', 'drained', 'hot_standby', 'ignore_errors']:355                    module.fail_json(msg="State can only take values amongst 'present', 'absent', 'enabled', 'disabled', 'drained', 'hot_standby', 'ignore_errors'.")356    else:357        states = ['None']358    mybalancer = Balancer(module.params['balancer_vhost'],359                          module.params['balancer_url_suffix'],360                          module=module,361                          tls=module.params['tls'])362    if module.params['member_host'] is None:363        json_output_list = []364        for member in mybalancer.members:365            json_output_list.append({366                "host": member.host,367                "status": member.status,368                "protocol": member.protocol,369                "port": member.port,370                "path": member.path,371                "attributes": member.attributes,372                "management_url": member.management_url,373                "balancer_url": member.balancer_url374            })375        module.exit_json(376            changed=False,377            members=json_output_list378        )379    else:380        changed = False381        member_exists = False382        member_status = {'disabled': False, 'drained': False, 'hot_standby': False, 'ignore_errors':False}383        for mode in member_status.keys():384            for state in states:385                if mode == state:386                    member_status[mode] = True387                elif mode == 'disabled' and state == 'absent':388                    member_status[mode] = True389        for member in mybalancer.members:390            if str(member.host) == str(module.params['member_host']):391                member_exists = True392                if module.params['state'] is not None:393                    member_status_before = member.status394                    if not module.check_mode:395                        member_status_after = member.status = member_status396                    else:397                        member_status_after = member_status398                    if member_status_before != member_status_after:399                        changed = True400                json_output = {401                    "host": member.host,402                    "status": member.status,403                    "protocol": member.protocol,404                    "port": member.port,405                    "path": member.path,406                    "attributes": member.attributes,407                    "management_url": member.management_url,408                    "balancer_url": member.balancer_url409                }410        if member_exists:411            module.exit_json(412                changed=changed,413                member=json_output414                )415        else:416            module.fail_json(msg=str(module.params['member_host']) + ' is not a member of the balancer ' + str(module.params['balancer_vhost']) + '!')417from ansible.module_utils.basic import AnsibleModule418from ansible.module_utils.urls import fetch_url419if __name__ == '__main__':...test_emr_responses.py
Source:test_emr_responses.py  
1# Copyright (c) 2010 Jeremy Thurgood <firxen+boto@gmail.com>2#3# Permission is hereby granted, free of charge, to any person obtaining a4# copy of this software and associated documentation files (the5# "Software"), to deal in the Software without restriction, including6# without limitation the rights to use, copy, modify, merge, publish, dis-7# tribute, sublicense, and/or sell copies of the Software, and to permit8# persons to whom the Software is furnished to do so, subject to the fol-9# lowing conditions:10#11# The above copyright notice and this permission notice shall be included12# in all copies or substantial portions of the Software.13#14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS15# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-16# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT17# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20# IN THE SOFTWARE.21# NOTE: These tests only cover the very simple cases I needed to test22# for the InstanceGroup fix.23import xml.sax24from boto import handler25from boto.emr import emrobject26from boto.resultset import ResultSet27from tests.compat import unittest28JOB_FLOW_EXAMPLE = b"""29<DescribeJobFlowsResponse30    xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-01-15">31  <DescribeJobFlowsResult>32    <JobFlows>33      <member>34        <ExecutionStatusDetail>35          <CreationDateTime>2009-01-28T21:49:16Z</CreationDateTime>36          <StartDateTime>2009-01-28T21:49:16Z</StartDateTime>37          <State>STARTING</State>38        </ExecutionStatusDetail>39        <BootstrapActions>40          <member>41            <BootstrapActionConfig>42              <ScriptBootstrapAction>43                <Args/>44                <Path>s3://elasticmapreduce/libs/hue/install-hue</Path>45              </ScriptBootstrapAction>46              <Name>Install Hue</Name>47            </BootstrapActionConfig>48          </member>49        </BootstrapActions>50        <VisibleToAllUsers>true</VisibleToAllUsers>51        <SupportedProducts>52          <member>Hue</member>53        </SupportedProducts>54        <Name>MyJobFlowName</Name>55        <LogUri>mybucket/subdir/</LogUri>56        <Steps>57          <member>58            <ExecutionStatusDetail>59              <CreationDateTime>2009-01-28T21:49:16Z</CreationDateTime>60              <State>PENDING</State>61            </ExecutionStatusDetail>62            <StepConfig>63              <HadoopJarStep>64                <Jar>MyJarFile</Jar>65                <MainClass>MyMailClass</MainClass>66                <Args>67                  <member>arg1</member>68                  <member>arg2</member>69                </Args>70                <Properties/>71              </HadoopJarStep>72              <Name>MyStepName</Name>73              <ActionOnFailure>CONTINUE</ActionOnFailure>74            </StepConfig>75          </member>76        </Steps>77        <JobFlowId>j-3UN6WX5RRO2AG</JobFlowId>78        <Instances>79          <Placement>80            <AvailabilityZone>us-east-1a</AvailabilityZone>81          </Placement>82          <SlaveInstanceType>m1.small</SlaveInstanceType>83          <MasterInstanceType>m1.small</MasterInstanceType>84          <Ec2KeyName>myec2keyname</Ec2KeyName>85          <InstanceCount>4</InstanceCount>86          <KeepJobFlowAliveWhenNoSteps>true</KeepJobFlowAliveWhenNoSteps>87        </Instances>88      </member>89    </JobFlows>90  </DescribeJobFlowsResult>91  <ResponseMetadata>92    <RequestId>9cea3229-ed85-11dd-9877-6fad448a8419</RequestId>93  </ResponseMetadata>94</DescribeJobFlowsResponse>95"""96JOB_FLOW_COMPLETED = b"""97<DescribeJobFlowsResponse xmlns="http://elasticmapreduce.amazonaws.com/doc/2009-03-31">98  <DescribeJobFlowsResult>99    <JobFlows>100      <member>101        <ExecutionStatusDetail>102          <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>103          <LastStateChangeReason>Steps completed</LastStateChangeReason>104          <StartDateTime>2010-10-21T01:03:59Z</StartDateTime>105          <ReadyDateTime>2010-10-21T01:03:59Z</ReadyDateTime>106          <State>COMPLETED</State>107          <EndDateTime>2010-10-21T01:44:18Z</EndDateTime>108        </ExecutionStatusDetail>109        <BootstrapActions/>110        <Name>RealJobFlowName</Name>111        <LogUri>s3n://example.emrtest.scripts/jobflow_logs/</LogUri>112        <Steps>113          <member>114            <StepConfig>115              <HadoopJarStep>116                <Jar>s3n://us-east-1.elasticmapreduce/libs/script-runner/script-runner.jar</Jar>117                <Args>118                  <member>s3n://us-east-1.elasticmapreduce/libs/state-pusher/0.1/fetch</member>119                </Args>120                <Properties/>121              </HadoopJarStep>122              <Name>Setup Hadoop Debugging</Name>123              <ActionOnFailure>TERMINATE_JOB_FLOW</ActionOnFailure>124            </StepConfig>125            <ExecutionStatusDetail>126              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>127              <StartDateTime>2010-10-21T01:03:59Z</StartDateTime>128              <State>COMPLETED</State>129              <EndDateTime>2010-10-21T01:04:22Z</EndDateTime>130            </ExecutionStatusDetail>131          </member>132          <member>133            <StepConfig>134              <HadoopJarStep>135                <Jar>/home/hadoop/contrib/streaming/hadoop-0.20-streaming.jar</Jar>136                <Args>137                  <member>-mapper</member>138                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-InitialMapper.py</member>139                  <member>-reducer</member>140                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-InitialReducer.py</member>141                  <member>-input</member>142                  <member>s3://example.emrtest.data/raw/2010/10/20/*</member>143                  <member>-input</member>144                  <member>s3://example.emrtest.data/raw/2010/10/19/*</member>145                  <member>-input</member>146                  <member>s3://example.emrtest.data/raw/2010/10/18/*</member>147                  <member>-input</member>148                  <member>s3://example.emrtest.data/raw/2010/10/17/*</member>149                  <member>-input</member>150                  <member>s3://example.emrtest.data/raw/2010/10/16/*</member>151                  <member>-input</member>152                  <member>s3://example.emrtest.data/raw/2010/10/15/*</member>153                  <member>-input</member>154                  <member>s3://example.emrtest.data/raw/2010/10/14/*</member>155                  <member>-output</member>156                  <member>s3://example.emrtest.crunched/</member>157                </Args>158                <Properties/>159              </HadoopJarStep>160              <Name>testjob_Initial</Name>161              <ActionOnFailure>TERMINATE_JOB_FLOW</ActionOnFailure>162            </StepConfig>163            <ExecutionStatusDetail>164              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>165              <StartDateTime>2010-10-21T01:04:22Z</StartDateTime>166              <State>COMPLETED</State>167              <EndDateTime>2010-10-21T01:36:18Z</EndDateTime>168            </ExecutionStatusDetail>169          </member>170          <member>171            <StepConfig>172              <HadoopJarStep>173                <Jar>/home/hadoop/contrib/streaming/hadoop-0.20-streaming.jar</Jar>174                <Args>175                  <member>-mapper</member>176                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step1Mapper.py</member>177                  <member>-reducer</member>178                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step1Reducer.py</member>179                  <member>-input</member>180                  <member>s3://example.emrtest.crunched/*</member>181                  <member>-output</member>182                  <member>s3://example.emrtest.step1/</member>183                </Args>184                <Properties/>185              </HadoopJarStep>186              <Name>testjob_step1</Name>187              <ActionOnFailure>TERMINATE_JOB_FLOW</ActionOnFailure>188            </StepConfig>189            <ExecutionStatusDetail>190              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>191              <StartDateTime>2010-10-21T01:36:18Z</StartDateTime>192              <State>COMPLETED</State>193              <EndDateTime>2010-10-21T01:37:51Z</EndDateTime>194            </ExecutionStatusDetail>195          </member>196          <member>197            <StepConfig>198              <HadoopJarStep>199                <Jar>/home/hadoop/contrib/streaming/hadoop-0.20-streaming.jar</Jar>200                <Args>201                  <member>-mapper</member>202                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step2Mapper.py</member>203                  <member>-reducer</member>204                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step2Reducer.py</member>205                  <member>-input</member>206                  <member>s3://example.emrtest.crunched/*</member>207                  <member>-output</member>208                  <member>s3://example.emrtest.step2/</member>209                </Args>210                <Properties/>211              </HadoopJarStep>212              <Name>testjob_step2</Name>213              <ActionOnFailure>TERMINATE_JOB_FLOW</ActionOnFailure>214            </StepConfig>215            <ExecutionStatusDetail>216              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>217              <StartDateTime>2010-10-21T01:37:51Z</StartDateTime>218              <State>COMPLETED</State>219              <EndDateTime>2010-10-21T01:39:32Z</EndDateTime>220            </ExecutionStatusDetail>221          </member>222          <member>223            <StepConfig>224              <HadoopJarStep>225                <Jar>/home/hadoop/contrib/streaming/hadoop-0.20-streaming.jar</Jar>226                <Args>227                  <member>-mapper</member>228                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step3Mapper.py</member>229                  <member>-reducer</member>230                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step3Reducer.py</member>231                  <member>-input</member>232                  <member>s3://example.emrtest.step1/*</member>233                  <member>-output</member>234                  <member>s3://example.emrtest.step3/</member>235                </Args>236                <Properties/>237              </HadoopJarStep>238              <Name>testjob_step3</Name>239              <ActionOnFailure>TERMINATE_JOB_FLOW</ActionOnFailure>240            </StepConfig>241            <ExecutionStatusDetail>242              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>243              <StartDateTime>2010-10-21T01:39:32Z</StartDateTime>244              <State>COMPLETED</State>245              <EndDateTime>2010-10-21T01:41:22Z</EndDateTime>246            </ExecutionStatusDetail>247          </member>248          <member>249            <StepConfig>250              <HadoopJarStep>251                <Jar>/home/hadoop/contrib/streaming/hadoop-0.20-streaming.jar</Jar>252                <Args>253                  <member>-mapper</member>254                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step4Mapper.py</member>255                  <member>-reducer</member>256                  <member>s3://example.emrtest.scripts/81d8-5a9d3df4a86c-step4Reducer.py</member>257                  <member>-input</member>258                  <member>s3://example.emrtest.step1/*</member>259                  <member>-output</member>260                  <member>s3://example.emrtest.step4/</member>261                </Args>262                <Properties/>263              </HadoopJarStep>264              <Name>testjob_step4</Name>265              <ActionOnFailure>TERMINATE_JOB_FLOW</ActionOnFailure>266            </StepConfig>267            <ExecutionStatusDetail>268              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>269              <StartDateTime>2010-10-21T01:41:22Z</StartDateTime>270              <State>COMPLETED</State>271              <EndDateTime>2010-10-21T01:43:03Z</EndDateTime>272            </ExecutionStatusDetail>273          </member>274        </Steps>275        <JobFlowId>j-3H3Q13JPFLU22</JobFlowId>276        <Instances>277          <SlaveInstanceType>m1.large</SlaveInstanceType>278          <MasterInstanceId>i-64c21609</MasterInstanceId>279          <Placement>280            <AvailabilityZone>us-east-1b</AvailabilityZone>281          </Placement>282          <InstanceGroups>283            <member>284              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>285              <InstanceRunningCount>0</InstanceRunningCount>286              <StartDateTime>2010-10-21T01:02:09Z</StartDateTime>287              <ReadyDateTime>2010-10-21T01:03:03Z</ReadyDateTime>288              <State>ENDED</State>289              <EndDateTime>2010-10-21T01:44:18Z</EndDateTime>290              <InstanceRequestCount>1</InstanceRequestCount>291              <InstanceType>m1.large</InstanceType>292              <Market>ON_DEMAND</Market>293              <LastStateChangeReason>Job flow terminated</LastStateChangeReason>294              <InstanceRole>MASTER</InstanceRole>295              <InstanceGroupId>ig-EVMHOZJ2SCO8</InstanceGroupId>296              <Name>master</Name>297            </member>298            <member>299              <CreationDateTime>2010-10-21T01:00:25Z</CreationDateTime>300              <InstanceRunningCount>0</InstanceRunningCount>301              <StartDateTime>2010-10-21T01:03:59Z</StartDateTime>302              <ReadyDateTime>2010-10-21T01:03:59Z</ReadyDateTime>303              <State>ENDED</State>304              <EndDateTime>2010-10-21T01:44:18Z</EndDateTime>305              <InstanceRequestCount>9</InstanceRequestCount>306              <InstanceType>m1.large</InstanceType>307              <Market>ON_DEMAND</Market>308              <LastStateChangeReason>Job flow terminated</LastStateChangeReason>309              <InstanceRole>CORE</InstanceRole>310              <InstanceGroupId>ig-YZHDYVITVHKB</InstanceGroupId>311              <Name>slave</Name>312            </member>313          </InstanceGroups>314          <NormalizedInstanceHours>40</NormalizedInstanceHours>315          <HadoopVersion>0.20</HadoopVersion>316          <MasterInstanceType>m1.large</MasterInstanceType>317          <MasterPublicDnsName>ec2-184-72-153-139.compute-1.amazonaws.com</MasterPublicDnsName>318          <Ec2KeyName>myubersecurekey</Ec2KeyName>319          <InstanceCount>10</InstanceCount>320          <KeepJobFlowAliveWhenNoSteps>false</KeepJobFlowAliveWhenNoSteps>321        </Instances>322      </member>323    </JobFlows>324  </DescribeJobFlowsResult>325  <ResponseMetadata>326    <RequestId>c31e701d-dcb4-11df-b5d9-337fc7fe4773</RequestId>327  </ResponseMetadata>328</DescribeJobFlowsResponse>329"""330class TestEMRResponses(unittest.TestCase):331    def _parse_xml(self, body, markers):332        rs = ResultSet(markers)333        h = handler.XmlHandler(rs, None)334        xml.sax.parseString(body, h)335        return rs336    def _assert_fields(self, response, **fields):337        for field, expected in fields.items():338            actual = getattr(response, field)339            self.assertEquals(expected, actual,340                              "Field %s: %r != %r" % (field, expected, actual))341    def test_JobFlows_example(self):342        [jobflow] = self._parse_xml(JOB_FLOW_EXAMPLE,343                                    [('member', emrobject.JobFlow)])344        self._assert_fields(jobflow,345                            creationdatetime='2009-01-28T21:49:16Z',346                            startdatetime='2009-01-28T21:49:16Z',347                            state='STARTING',348                            instancecount='4',349                            jobflowid='j-3UN6WX5RRO2AG',350                            loguri='mybucket/subdir/',351                            name='MyJobFlowName',352                            availabilityzone='us-east-1a',353                            slaveinstancetype='m1.small',354                            masterinstancetype='m1.small',355                            ec2keyname='myec2keyname',356                            keepjobflowalivewhennosteps='true')357    def test_JobFlows_completed(self):358        [jobflow] = self._parse_xml(JOB_FLOW_COMPLETED,359                                    [('member', emrobject.JobFlow)])360        self._assert_fields(jobflow,361                            creationdatetime='2010-10-21T01:00:25Z',362                            startdatetime='2010-10-21T01:03:59Z',363                            enddatetime='2010-10-21T01:44:18Z',364                            state='COMPLETED',365                            instancecount='10',366                            jobflowid='j-3H3Q13JPFLU22',367                            loguri='s3n://example.emrtest.scripts/jobflow_logs/',368                            name='RealJobFlowName',369                            availabilityzone='us-east-1b',370                            slaveinstancetype='m1.large',371                            masterinstancetype='m1.large',372                            ec2keyname='myubersecurekey',373                            keepjobflowalivewhennosteps='false')374        self.assertEquals(6, len(jobflow.steps))...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
