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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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)
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
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)
def _enum_dict(mapping): enum_dict = _EnumDict() for key, value in mapping.items(): enum_dict[key] = value return enum_dict