def get_union_fields(field_type: Union[Any]) -> List[Variant]: """ Unions have a __args__ that is all their variants (after typing's type-collapsing magic has run, so caveat emptor...) JsonSchemaMixin dataclasses have `Field`s, returned by the `_get_fields` method. This method returns list of 2-tuples: - the first value is always a type - the second value is None if there are no restrictions, or a list of restrictions if there are restrictions The list will be sorted so that unrestricted variants will always be at the end. """ fields: List[Variant] = [] for variant in field_type.__args__: restrictions: Optional[Restriction] = _get_restrictions(variant) if not restrictions: restrictions = None fields.append((variant, restrictions)) # put unrestricted variants last fields.sort(key=lambda f: f[1] is None) return fields
def __init_subclass__(cls): """Metaprogramming: modify the attributes of the subclass based on information in run(). The goal is to make it possible for users to simply write a single run() method and have as much functionality as possible occur automatically. Specifically, this function converts the annotations and defaults in run() into a `BranchHparams` property. """ fields = [] for arg_name, parameter in list( inspect.signature(cls.branch_function).parameters.items())[1:]: t = parameter.annotation if t == inspect._empty: raise ValueError( f'Argument {arg_name} needs a type annotation.') elif t in [str, float, int, bool] or (isinstance(t, type) and issubclass(t, Hparams)): if parameter.default != inspect._empty: fields.append( (arg_name, t, field(default=parameter.default))) else: fields.append((arg_name, t)) else: raise ValueError('Invalid branch type: {}'.format( parameter.annotation)) fields += [('_name', str, 'Branch Arguments'), ('_description', str, 'Arguments specific to the branch.')] setattr(cls, 'BranchHparams', make_dataclass('BranchHparams', fields, bases=(Hparams, ))) setattr(cls, 'BranchDesc', make_BranchDesc(cls.BranchHparams, cls.name()))
def delete_field(self, name): # Check `name` name = self.munge(name) if name in BaseValues.__dataclass_fields__: raise ValueError(f"cannot remove ixmp core configuration key {repr(name)}") # Create a new dataclass, removing `name` fields = [] for f in self.__dataclass_fields__.values(): if f.name == name or f in BaseValues.__dataclass_fields__: continue fields.append((f.name, f.type, f)) new_cls = make_dataclass("Values", fields, bases=(BaseValues,)) # Reuse current values, discarding the deleted field data = asdict(self) data.pop(name) return new_cls, new_cls(**data)
async def makeModel( cls, name: str, schema: str = "public", fields: list = [], db: BaseProvider = None, ): """ Make Model. Making a model from field tuples, a JSON schema or a Table. """ tablename = "{}.{}".format(schema, name) if not fields: # we need to look in to it. colinfo = await db.column_info(tablename) fields = [] for column in colinfo: tp = column["data_type"] col = Field( primary_key=column["is_primary"], notnull=column["notnull"], db_type=column["format_type"], ) # get dtype from database type: try: dtype = MODEL_TYPES[tp] except KeyError: dtype = str fields.append((column["column_name"], dtype, col)) cls = make_dataclass(name, fields, bases=(Model,)) m = Meta() m.name = name m.schema = schema m.app_label = schema if db: m.connection = db m.frozen = False cls.Meta = m return cls