Beispiel #1
0
    def __new__(mcs,
                cls,
                bases,
                class_dict,
                sep: AnyStr = None,
                converter: Callable[[AnyStr], AnyStr] = None):
        mixin_type, base_enum = mcs._get_mixins_(bases)
        if not issubclass(base_enum, BaseAnyStrEnum):
            raise TypeError(
                f'Unexpected Enum type \'{base_enum.__name__}\'. '
                f'Only {BaseAnyStrEnum.__name__} and its subclasses are allowed'
            )
        elif not issubclass(mixin_type, (str, bytes)):
            raise TypeError(
                f'Unexpected mixin type \'{mixin_type.__name__}\'. '
                f'Only str, bytes and their subclasses are allowed')

        # Resolving Item class for mixin_type
        item_type: Type[BaseStrEnumItem] = class_dict.get(
            ITEM_TYPE_ATTR, base_enum.__item_type__)
        if item_type is None:
            raise NotImplementedError(f'{cls} must implement {ITEM_TYPE_ATTR}')
        elif not issubclass(item_type, BaseStrEnumItem):
            raise TypeError(
                f'{item_type.__name__} must be type of {BaseStrEnumItem.__name__}'
            )

        # Trying to get sep and converter from class dict and base enum class
        if sep is None:
            sep = class_dict.get(SEP_ATTR) or base_enum.__sep__
        if converter is None:
            converter = class_dict.get(
                CONVERTER_ATTR) or base_enum.__converter__

        item: BaseStrEnumItem = item_type(sep=sep, converter=converter)

        new_class_dict = _EnumDict()
        for name, type_hint in class_dict.get('__annotations__', {}).items():
            if name.startswith('_') or name in class_dict:
                continue
            mcs.check_type_equals(type_hint, mixin_type)
            value = item.generate_value(name)
            new_class_dict[name] = value
            mcs.check_type_equals(type(value), mixin_type)

        for name, value in class_dict.items():
            if isinstance(value, BaseStrEnumItem):
                value = value.generate_value(name)
            elif isinstance(value, auto):
                value = item.generate_value(name)
            if not name.startswith('_'):
                mcs.check_type_equals(type(value), mixin_type)

            new_class_dict[name] = value

        new_class_dict[SEP_ATTR] = sep
        new_class_dict[CONVERTER_ATTR] = converter
        new_class_dict[ITEM_TYPE_ATTR] = item_type

        return super().__new__(mcs, cls, bases, new_class_dict)
Beispiel #2
0
 def __new__(metacls, name, bases, oldclassdict):
     # Scan through the declared enum members and convert any value that is a plain
     # empty tuple into a `str` of the name instead.
     newclassdict = enum._EnumDict()
     for key, val in oldclassdict.items():
         if val == ():
             val = key
         newclassdict[key] = val
     return super(StrEnumMeta, metacls).__new__(metacls, name, bases, newclassdict)
Beispiel #3
0
 def __new__(metacls, cls, bases, classdict):
     if type(classdict) is dict:
         original_dict = classdict
         classdict = _EnumDict()
         for k, v in original_dict.items():
             classdict[k] = v
     temp = _EnumDict()
     for k, v in classdict.items():
         if k in classdict._member_names:
             if v == ():
                 v = metacls._i
             else:
                 metacls._i = v
             metacls._i += 1
             temp[k] = v
         else:
             temp[k] = classdict[k]
     return EnumMeta.__new__(metacls, cls, bases, temp)
Beispiel #4
0
 def __new__(metacls, cls, bases, oldclassdict):
     """
     Override class dict to replace enum `autostr` value with lowercase key.
     """
     newclassdict = _EnumDict()
     for k, v in oldclassdict.items():
         if isinstance(v, autostr):
             v = k.lower()
         newclassdict[k] = v
     return super().__new__(metacls, cls, bases, newclassdict)
Beispiel #5
0
 def __new__(mcs, cls, bases, oldclassdict):
     """
     Scan through ``oldclassdict`` and convert any value that is a plain
     tuple into a ``str`` of the name instead.
     """
     newclassdict = _EnumDict()
     for k, v in oldclassdict.items():
         if v == ():
             v = k
         newclassdict[k] = v
     return super().__new__(mcs, cls, bases, newclassdict)
Beispiel #6
0
    def __new__(metacls, cls, bases, classdict):
        if type(classdict) is dict:
            original_dict = classdict
            classdict = enum._EnumDict()
            for k, v in original_dict.items():
                classdict[k] = v

        if '__getitem__'  not in classdict:
            classdict['__getitem__'] = lambda self, idx: [self.value, self.display][idx]
        if '__len__' not in classdict:
            classdict['__len__'] = lambda self: 2

        return super(ChoicesEnumMeta, metacls).__new__(metacls, cls, bases, classdict)
Beispiel #7
0
 def __new__(mcs, cls, bases, oldclassdict):
     """
     Scan through ``oldclassdict`` and convert any value that is a plain
     tuple into a ``str`` of the name instead.
     """
     newclassdict = _EnumDict()
     for k, v in oldclassdict.items():
         if v == ():
             v = k.lower()
         if v in newclassdict.keys():
             raise ValueError(f"Duplicate value caused by key {k}")
         newclassdict[k] = v
     return super().__new__(mcs, cls, bases, newclassdict)
Beispiel #8
0
class Enum(EnumMeta('Enum', (BaseEnum, ), _EnumDict())):
    @classmethod
    def choices(cls):
        """
        Returns a list formatted for use as field choices.
        (See https://docs.djangoproject.com/en/dev/ref/models/fields/#choices)
        """
        return tuple((m.value, m.label) for m in cls)

    def __str__(self):
        """
        Show our label when Django uses the Enum for displaying in a view
        """
        return force_text(self.label)
Beispiel #9
0
    def __new__(mcs,
                cls,
                bases,
                class_dict,
                sep: AnyStr = None,
                converter: Callable[[str], str] = None):
        # In Python 3.8 the signature of 'EnumMeta._get_mixins_' was changed from (bases) to (class_name, bases)
        if sys.version_info >= (3, 8):  # (class_name, bases)
            mixin_type, base_enum = mcs._get_mixins_(cls, bases)
        else:  # Fallback to (bases) signature
            mixin_type, base_enum = mcs._get_mixins_(bases)
        if not issubclass(base_enum, BaseStrEnum):
            raise TypeError(
                f'Unexpected Enum type \'{base_enum.__name__}\'. '
                f'Only {BaseStrEnum.__name__} and its subclasses are allowed')
        if not issubclass(mixin_type, (str, bytes)):
            raise TypeError(
                f'Unexpected mixin type \'{mixin_type.__name__}\'. '
                f'Only str, bytes and their subclasses are allowed')

        # Trying to get sep and converter from class dict and base enum class
        if sep is None:
            sep = class_dict.get(SEP_ATTR) or base_enum.__sep__
        if converter is None:
            converter = class_dict.get(
                CONVERTER_ATTR) or base_enum.__converter__

        item = StrItem(sep=sep, converter=converter)
        new_class_dict = _EnumDict()
        for name, type_hint in class_dict.get('__annotations__', {}).items():
            if name.startswith('_') or name in class_dict:
                continue
            mcs.check_type_equals(type_hint, mixin_type)
            value = item.generate_value(name)
            new_class_dict[name] = value
            mcs.check_type_equals(type(value), mixin_type)

        for name, value in class_dict.items():
            if isinstance(value, StrItem):
                value = value.generate_value(name)
            if not (name.startswith('_') or isinstance(value, TYPE_BLACKLIST)):
                mcs.check_type_equals(type(value), mixin_type)

            new_class_dict[name] = value

        new_class_dict[SEP_ATTR] = sep
        new_class_dict[CONVERTER_ATTR] = converter

        return super().__new__(mcs, cls, bases, new_class_dict)
Beispiel #10
0
    def __new__(metacls, cls, bases, classdict):
        if type(classdict) is dict:
            original_dict = classdict
            classdict = enum._EnumDict()
            for k, v in original_dict.items():
                classdict[k] = v

        if '__getitem__' not in classdict:
            classdict['__getitem__'] = lambda self, idx: [
                self.value, self.display
            ][idx]
        if '__len__' not in classdict:
            classdict['__len__'] = lambda self: 2

        return super(ChoicesEnumMeta, metacls).__new__(metacls, cls, bases,
                                                       classdict)
Beispiel #11
0
    def __init__(self,
                 choices,
                 name="",
                 description="",
                 default=None,
                 id=None):
        if isinstance(choices, list):
            _choices = enum._EnumDict()
            for i in range(len(choices)):
                _choices[choices[i]] = i
            choices = enum.EnumMeta(
                "_local_enum_from_list_",
                (EnumParameter.EnumFromList, ),
                _choices,
            )
        elif not isinstance(choices, type) or not issubclass(
                choices, enum.Enum):
            # If choices is not a class and not an enum
            raise TypeError(
                "Enum's choices can only be a list or an enum.Enum")

        self.choices = choices
        if len(list(self.choices)) == 0:
            raise TypeError("Enum's choices cannot be an empty")

        if isinstance(default, enum.Enum):
            default = self.choices(default)
        elif default is not None:
            default = self.choices[default]
        else:
            default = list(self.choices)[0]

        ParameterType.__init__(self, name, description, default, id)

        def normalizer(x):
            if isinstance(x, enum.Enum):
                return self.choices(x)
            else:
                return self.choices[x]

        self._normalizer = normalizer
Beispiel #12
0
 def __new__(metacls, cls, bases, classdict):
     original_dict = classdict
     classdict = enum._EnumDict()
     for k, v in original_dict.items():
         classdict[k] = v
     temp = type(classdict)()
     names = set(classdict._member_names)
     i = 0
     for k in classdict._member_names:
         v = classdict[k]
         if v == ():
             v = i
         else:
             i = v
         i += 1
         temp[k] = v
     for k, v in classdict.items():
         if k not in names:
             temp[k] = v
     return super(auto_enum, metacls).__new__(
             metacls, cls, bases, temp)
Beispiel #13
0
 def __new__(metacls, cls, bases, classdict):
     original_dict = classdict
     classdict = enum._EnumDict()
     for k, v in original_dict.items():
         classdict[k] = v
     temp = type(classdict)()
     names = set(classdict._member_names)
     i = 0
     for k in classdict._member_names:
         v = classdict[k]
         if v == ():
             v = i
         else:
             i = v
         i += 1
         temp[k] = v
     for k, v in classdict.items():
         if k not in names:
             temp[k] = v
     return super(auto_enum,
                  metacls).__new__(metacls, cls, bases, temp)
Beispiel #14
0
def create_register_flag(register_name: str,
                         names: Union[tuple, dict],
                         length: int) -> Type[IntFlag]:
    """Create a IntFlag subclass for a bit field.

    Parameters
    ----------
    register_name : str
        Name of the subclass to create.

    names : dict | list
        Mapping between the field names and their index or list of names.
        In the case of a list its length must match length.

    length : int
        Number of fields in the bit field.

    Returns
    -------
    register_flag : IntFlag
        IntFlag subclass whose fields match the register fields. If some of the
        names are not provided, the associated fields are named 'BIT_n' with n
        the bit number.

    """
    register_names = _EnumDict()
    register_names.update({'BIT_%d' % i: 2**i for i in range(length)})
    if isinstance(names, dict):
        for n, i in names.items():
            register_names[n] = 2**i

    elif names:
        if len(names) != length:
            raise ValueError('Register necessitates %d names' % length)

        for i, n in enumerate(names[:]):
            if n:
                register_names[n] = 2**i

    return type(register_name, (IntFlag,), register_names)
    def add_enum_class(self, class_name: str, class_values: list):
        """Construct a TerminusDB Enum class by provideing class name and member values then add into the schema.

        Parameters
        ----------
        class_name: str
            Name of the class object constructed.
        class_values : list
            A list of values in this Enum.

        Returns
        -------
        EnumMetaTemplate
            A Enum object with the sepcified name and members
        """
        attributedict = _EnumDict()
        attributedict._cls_name = class_name
        for value in class_values:
            attributedict[value.lower().replace(" ", "_")] = value
        new_class = type(class_name, (EnumTemplate, ), attributedict)
        self.add_obj(class_name, new_class)
        return new_class
    def _contruct_class(self, class_obj_dict):
        # if the class is already constructed properly
        if (class_obj_dict.get("@id") and class_obj_dict["@id"] in self.object
                and not isinstance(self.object[class_obj_dict["@id"]], str)):
            return self.object[class_obj_dict["@id"]]
        # if the class is Enum
        if class_obj_dict.get("@type") == "Enum":
            attributedict = _EnumDict()
            attributedict._cls_name = class_obj_dict.get("@id")
        else:
            attributedict = {}
        annotations = {}
        superclasses = []
        inherits = class_obj_dict.get("@inherits")
        if inherits:
            if isinstance(inherits, str):
                inherits = [inherits]
            for parent in inherits:
                if parent == "TaggedUnion":
                    superclasses.append(TaggedUnion)
                elif parent not in self._all_existing_classes:
                    raise RuntimeError(
                        f"{parent} not exist in database schema")
                else:
                    self._contruct_class(self._all_existing_classes[parent])
                    superclasses.append(self.object[parent])
        else:
            inherits = []
        if class_obj_dict.get("@type") == "Class":
            superclasses.append(DocumentTemplate)
        elif class_obj_dict.get("@type") == "Enum":
            superclasses.append(EnumTemplate)
            if class_obj_dict.get("@value"):
                for members in class_obj_dict.get("@value"):
                    attributedict[members.lower().replace(" ", "_")] = members
            else:
                raise RuntimeError(
                    f"{class_obj_dict} not exist in database schema")
        for key, value in class_obj_dict.items():
            if key[0] != "@":
                attributedict[key] = None
                if isinstance(value, str):
                    if value[:4] == "xsd:":
                        annotations[key] = wt.from_woql_type(value)
                    else:
                        if value not in self._all_existing_classes:
                            raise RuntimeError(
                                f"{value} not exist in database schema")
                        elif value not in self.object:
                            self.object[value] = value
                        annotations[key] = self.object[value]
                elif isinstance(value, dict):
                    if value.get("@type") and value.get("@type") == "Set":
                        annotations[key] = Set[wt.from_woql_type(
                            value.get("@class"), skip_convert_error=True)]
                    elif value.get("@type") and value.get("@type") == "List":
                        annotations[key] = List[wt.from_woql_type(
                            value.get("@class"), skip_convert_error=True)]
                    elif value.get("@type") and value.get(
                            "@type") == "Optional":
                        annotations[key] = Optional[wt.from_woql_type(
                            value.get("@class"), skip_convert_error=True)]
                    else:
                        raise RuntimeError(
                            f"{value} is not in the right format for TerminusDB type"
                        )
            # when key stars with @
            elif key == "@subdocument":
                attributedict["_subdocument"] = value
            elif key == "@abstract":
                attributedict["_abstract"] = value
            elif key == "@key":
                key_type = value.get("@type")
                if key_type and key_type == "Random":
                    attributedict["_key"] = RandomKey()
                elif key_type and key_type == "ValueHash":
                    attributedict["_key"] = ValueHashKey()
                elif key_type and key_type == "Lexical":
                    attributedict["_key"] = LexicalKey(value.get("@fields"))
                elif key_type and key_type == "Hash":
                    attributedict["_key"] = HashKey(value.get("@fields"))
                else:
                    raise RuntimeError(
                        f"{value} is not in the right format for TerminusDB key"
                    )
            elif key == "@documentation":
                docstring = f'{value["@comment"]}'
                if value.get("@properties"):
                    docstring += "\n\n    Attributes\n    ----------\n"
                    for prop, discription in value["@properties"].items():
                        docstring += f"    {prop} : {wt.from_woql_type(class_obj_dict[prop], skip_convert_error=True, as_str=True)}\n        {discription}\n"
                attributedict["__doc__"] = docstring

        attributedict["__annotations__"] = annotations
        new_class = type(class_obj_dict["@id"], tuple(superclasses),
                         attributedict)
        self.add_obj(class_obj_dict["@id"], new_class)
        return new_class
Beispiel #17
0
 def __prepare__(metacls, cls):
     return enum._EnumDict()
    def __call__(cls, requests=None):
        """Given a dictionary of requests for neutrino interactions, returns an
        enumeration containing the requested interactions.           
            
           .. param :: cls : Interactions
              Called object. (Similar to 'self' keyword)
            
           .. param :: requests : dict, (list, tuple, ndarray of str), or str
              Dictionary of requested interactions
               - Keys with value True are initialized as enumeration members                
        """
        if isinstance(requests, str):
            # If string 'default' or 'all' requests, return default interactions Enum
            if requests.lower() in {'all', 'default'}:
                return Interactions
            else:
                raise RuntimeError("Unknown requests made: {0}".format(requests))

        # If requests input is list, tuple or ndarray of strings, assume all elements are requested interactions
        if isinstance(requests, (list, tuple, np.ndarray)):
            requests = {item: True for item in requests}

        # Declare Meta-class _InteractionsMeta for error-checking.
        metacls = cls.__class__

        # If no requests have been made, raise an error.
        if requests is None or all( not val for val in requests.values() ):
            raise RuntimeError('No Interactions Requested. ') 
        # If an unknown interaction is requested, raise an error.
        elif any( key not in metacls._InteractionDict for key in requests):
            raise AttributeError('Unknown interaction(s) "{0}" Requested'.format(
                                 '", "'.join(set(requests)-set(metacls._InteractionDict))))
        # If requests does not have all boolean values, throw an error  .
        elif not all(isinstance(val, bool) for val in requests.values()):
            errordict = {key: val for key, val in requests.items()
                         if not isinstance(requests[key], bool)}
            raise ValueError('Requests must be dictionary with bool values. ' +
                             'Given elements: {0}'.format(errordict))

        # Retrieve interactions (if any) that were missing from requests.
        missing = {key: False for key in metacls._InteractionDict if
                   key not in requests}
        requests.update(missing)

        # If both implementations of Inverse Beta Decay are requested, throw an error.
        if requests['InvBetaTab'] and requests['InvBetaPar']:
            raise RuntimeError('Requested InvBetaTab & InvBetaPar; ' +
                               'only one instance of IBD is allowed.')
        # Otherwise, create a new Enum object...

        # Sort requests according to metacls._InteractionDict
        requests = {key: requests[key] for key in metacls._InteractionDict }
        
        # Populate an _EnumDict with fields required for Enum creation.
        bases = (Enum, )
        classdict = _EnumDict()
        fields = {'__doc__'               : cls.__doc__,
                  '__init__'              : cls.__init__,
                  '__module__'            : cls.__module__,
                  '__qualname__'          : 'Interactions',
                  '_generate_next_value_' : cls._generate_next_value_,
                  'cross_section'         : cls.cross_section,
                  'mean_lepton_energy'    : cls.mean_lepton_energy,
                  'photon_scaling_factor' : cls.photon_scaling_factor,
                  'requests'              : requests }
        classdict.update({ key : val for key, val in fields.items()})
        
        # Create and return an Enum object using _InteractionsMeta.__new__      
        return metacls.__new__(metacls, 'Interactions', bases, classdict)
Beispiel #19
0
 def _enum_dict(mapping):
     enum_dict = _EnumDict()
     for key, value in mapping.items():
         enum_dict[key] = value
     return enum_dict