コード例 #1
0
ファイル: server.py プロジェクト: netsafe/DeepVesnin
 def batch_decorator(cls: ModelMetaclass) -> ModelMetaclass:
     cls.__annotations__ = {arg_name: list for arg_name in model_args_names}
     cls.__fields__ = {
         arg_name: ModelField(name=arg_name,
                              type_=list,
                              class_validators=None,
                              model_config=BaseConfig,
                              required=False,
                              field_info=Field(None))
         for arg_name in model_args_names
     }
     return cls
コード例 #2
0
    def build_resp_model(cls):
        ns = {
            'code': Field(cls.CODE, const=True, example=cls.CODE),
            'message': Field(cls.MESSAGE, const=True, example=cls.MESSAGE),
            '__annotations__': {
                'code': int,
                'message': str,
            }
        }

        data_model = cls.get_data_model()
        if data_model is not None:
            if not cls.data_required:
                data_model = Optional[data_model]
            # noinspection PyTypeChecker
            ns['__annotations__']['data'] = data_model

        name = cls._component_name or cls.__name__

        _JsonRpcErrorModel = ModelMetaclass.__new__(ModelMetaclass, '_JsonRpcErrorModel', (BaseModel,), ns)
        _JsonRpcErrorModel = component_name(name, cls.__module__)(_JsonRpcErrorModel)

        @component_name(f'_ErrorResponse[{name}]', cls.__module__)
        class _ErrorResponseModel(BaseModel):
            jsonrpc: StrictStr = Field('2.0', const=True, example='2.0')
            id: Union[StrictStr, int] = Field(None, example=0)
            error: _JsonRpcErrorModel

            class Config:
                extra = 'forbid'

        return _ErrorResponseModel
コード例 #3
0
ファイル: document.py プロジェクト: mgwilliams/pyrodantic
    def __new__(cls, name, bases, namespace, **kwargs):
        firestore = FirestoreConfig
        for base in reversed(bases):
            if (
                _DOCUMENT_CLASS_DEFINED
                and issubclass(base, Document)
                and base != Document
            ):
                firestore = inherit_config(base.__firestore__, firestore)
        firestore = inherit_config(namespace.get("Firestore"), firestore)
        annotations = namespace.get("__annotations__", {})

        ids = {k: v for k, v in annotations.items() if issubclass(v, FirestoreID)}

        if (
            _DOCUMENT_CLASS_DEFINED
            and len(ids) != 1
            and not hasattr(firestore, "id_attr")
        ):
            raise TypeError(
                f'"{name}" must have exactly one attribute of type FirestoreID.'
            )
        elif len(ids) == 1:
            id_attr = list(ids.keys())[0]
            setattr(firestore, "id_attr", id_attr)
        namespace["__firestore__"] = firestore
        return ModelMetaclass.__new__(cls, name, bases, namespace, **kwargs)
コード例 #4
0
ファイル: decorators.py プロジェクト: alcrene/smttask
def _make_output_class(f, json_encoders=None):
    return_annot = typing.get_type_hints(f).get('return', inspect._empty)
    if return_annot is inspect._empty:
        raise TypeError(
            f"Unable to construct a Task from function '{f.__qualname__}': "
            "the annotation for the return value is missing. "
            "This may be a type, or a subclass of TaskOutput.")
    json_encoders_arg = json_encoders if json_encoders else {}

    class Config:  # NB: MIGHT NOT be used if `f` includes a 'return' annotation
        json_encoders = {
            **json_encoders_arg,
            **smttask_json_encoders,
            **base.TaskOutput.Config.json_encoders
        }

    if lenient_issubclass(return_annot, base.TaskOutput):
        # Nothing to do
        Outputs = return_annot
        # Add the json_encoders to the Output type, but only if they were not
        # given explicitely in the Output type.
        if json_encoders:
            if hasattr(Outputs, 'Config') and not hasattr(
                    Outputs.Config, 'json_encoders'):
                Outputs.Config.json_encoders = Config.json_encoders
            elif not hasattr(Outputs, 'Config'):
                Outputs.Config = Config

    else:
        assert isinstance(return_annot, (type, typing._GenericAlias))
        # A bare annotation does not define a variable name; we set it to the
        # empty string (i.e., the variable is only identified by the task name)
        Outputs = ModelMetaclass(f"{f.__qualname__}.Outputs",
                                 (base.TaskOutput, ), {
                                     '__annotations__': {
                                         "": return_annot
                                     },
                                     'Config': Config
                                 })
    # Set correct module; workaround for https://bugs.python.org/issue28869
    Outputs.__module__ = f.__module__
    # update_forward_refs required for 3.9+ style annotations
    Outputs.update_forward_refs()
    return Outputs
コード例 #5
0
ファイル: decorators.py プロジェクト: alcrene/smttask
def _make_input_class(f, json_encoders=None):
    defaults = {}
    annotations = {}
    json_encoders_arg = json_encoders if json_encoders else {}

    class Config:
        # Override the lenience of the base TaskInput class and only allow expected arguments
        extra = 'forbid'
        json_encoders = {
            **json_encoders_arg,
            **smttask_json_encoders,
            **base.TaskInput.Config.json_encoders
        }

    for nm, param in inspect.signature(f).parameters.items():
        if param.annotation is inspect._empty:
            raise TypeError(
                "Constructing a Task requires that all function arguments "
                f"be annotated. Offender: argument '{nm}' of '{f.__qualname__}'."
            )
        annotation = param.annotation
        if isinstance(annotation, str):
            # HACK to resolve forward refs
            globalns = sys.modules[f.__module__].__dict__.copy()
            annotation = evaluate_forwardref(ForwardRef(annotation),
                                             globalns=globalns,
                                             localns=None)
        annotations[nm] = Union[base.Task, annotation]
        if param.default is not inspect._empty:
            defaults[nm] = param.default
    Inputs = ModelMetaclass(f"{f.__qualname__}.Inputs", (base.TaskInput, ), {
        **defaults, 'Config': Config,
        '__annotations__': annotations
    })
    # Set correct module; workaround for https://bugs.python.org/issue28869
    Inputs.__module__ = f.__module__
    # update_forward_refs required for 3.9+ style annotations
    # DEVNOTE: When one inspects Inputs.__fields__, some types may still contain 'ForwardRef'
    #          I don't know why that is, but checking Inputs.__fields__[field name].__args__[ForwardRef index].__forward_evaluated__ should still be True
    #          and [...].__forward_value__ should be the expected type
    Inputs.update_forward_refs()
    return Inputs
コード例 #6
0
def make_request_model(name, module, body_params: List[ModelField]):
    whole_params_list = [
        p for p in body_params if isinstance(p.field_info, Params)
    ]
    if len(whole_params_list):
        if len(whole_params_list) > 1:
            raise RuntimeError(f"Only one 'Params' allowed: "
                               f"params={whole_params_list}")
        body_params_list = [
            p for p in body_params if not isinstance(p.field_info, Params)
        ]
        if body_params_list:
            raise RuntimeError(
                f"No other params allowed when 'Params' used: "
                f"params={whole_params_list}, other={body_params_list}")

    if whole_params_list:
        assert whole_params_list[0].alias == 'params'
        params_field = whole_params_list[0]
    else:
        _JsonRpcRequestParams = ModelMetaclass.__new__(
            ModelMetaclass, '_JsonRpcRequestParams', (BaseModel, ), {})

        for f in body_params:
            _JsonRpcRequestParams.__fields__[f.name] = f

        _JsonRpcRequestParams = component_name(f'_Params[{name}]',
                                               module)(_JsonRpcRequestParams)

        params_field = ModelField(
            name='params',
            type_=_JsonRpcRequestParams,
            class_validators={},
            default=None,
            required=True,
            model_config=BaseConfig,
            field_info=Field(...),
        )

    class _Request(BaseModel):
        jsonrpc: StrictStr = Field('2.0', const=True, example='2.0')
        id: Union[StrictStr, int] = Field(None, example=0)
        method: StrictStr = Field(name, const=True, example=name)

        class Config:
            extra = 'forbid'

    _Request.__fields__[params_field.name] = params_field

    _Request = component_name(f'_Request[{name}]', module)(_Request)

    return _Request
コード例 #7
0
    def __new__(mcs, name, bases, namespace):

        slots = set(namespace.pop("__slots__", tuple()))

        for base in bases:
            if hasattr(base, "__slots__"):
                slots.update(base.__slots__)

        if "__dict__" in slots:
            slots.remove("__dict__")

        namespace["__slots__"] = tuple(slots)

        return ModelMetaclass.__new__(mcs, name, bases, namespace)
コード例 #8
0
ファイル: schema.py プロジェクト: 2021-msa-study/fastmsa
        def _get_model(
                DataClass: Type[D],
                excludes=[]) -> Type[Union[BaseModel, Type[D], Type[T]]]:
            from dataclasses import is_dataclass

            annotations = (dict(
                (name, SCHEMAS.get(type, type))
                for name, type in DataClass.__annotations__.items()
                if not excludes or name not in excludes) if hasattr(
                    DataClass, "__annotations__") else {})

            for field_name, field_type in annotations.items():
                if type(field_type) == GenericAlias and field_type.__mro__[
                        0] in [  # type: ignore
                            list,
                            set,
                        ]:
                    gen_type = field_type.__mro__[0]
                    arg_type = field_type.__args__[0]
                    arg_type = SCHEMAS.get(arg_type, arg_type)
                    field_type.__args__[0]
                    annotations[field_name] = GenericAlias(
                        gen_type, (arg_type, ))  # type: ignore
                if is_dataclass(field_type):
                    field = _get_model(field_type)
                    annotations[field_name] = field

            namespace = {
                "__annotations__": annotations,
                "__module__": TargetClass.__module__,
                "__qualname__": TargetClass.__qualname__,
            }

            model = cast(
                AnyType,
                ModelMetaclass(TargetClass.__name__, (ModelSchema, ),
                               namespace),
            )

            for field_name, field_type in annotations.items():
                member = members.get(field_name)
                field = model.__dict__["__fields__"].get(field_name)
                if not field:
                    continue
                if isinstance(member, (DataClassField, )):
                    setattr(field, "field_info", Field(..., **member.metadata))
                elif isinstance(member, (FieldInfo, )):
                    setattr(field, "field_info", member)
            return model
コード例 #9
0
    def build_data_model(cls):
        if cls.DataModel is not None:
            return rename_if_scope_child_component(cls, cls.DataModel, 'Data')

        error_model = cls.get_error_model()
        if error_model is None:
            return None

        errors_annotation = List[error_model]
        if not cls.errors_required:
            errors_annotation = Optional[errors_annotation]

        ns = {
            '__annotations__': {
                'errors': errors_annotation,
            }
        }

        _ErrorData = ModelMetaclass.__new__(ModelMetaclass, '_ErrorData', (BaseModel,), ns)
        _ErrorData = component_name(f'_ErrorData[{error_model.__name__}]', error_model.__module__)(_ErrorData)

        return _ErrorData
コード例 #10
0
ファイル: __init__.py プロジェクト: djpugh/fastapi_aad_auth
def expand_doc(klass: ModelMetaclass) -> ModelMetaclass:
    """Expand pydantic model documentation to enable autodoc."""
    docs = ['', '', 'Keyword Args:']
    for name, field in klass.__fields__.items():  # type: ignore
        default_str = ''
        #
        if field.default:
            default_str = ''
            if field.default:
                if SecretStr not in field.type_.__mro__:
                    default = field.default
                    if Path in field.type_.__mro__:
                        default = str(Path(default).relative_to(Path(default).parents[2]))
                    if field.name == 'user_klass':
                        default_str = f' [default: :class:`{default.replace("`", "").replace(":", ".")}`]'
                    else:
                        default_str = f' [default: ``{default}``]'
                else:
                    default_str = ' [default: ``uuid.uuid4()``]'
        module = field.outer_type_.__module__
        if module != 'builtins':
            if hasattr(field.outer_type_, '__origin__'):
                type_ = f' ({field.outer_type_.__origin__.__name__}) '
            elif not hasattr(field.outer_type_, '__name__'):
                type_ = ''
            else:
                type_ = f' ({module}.{field.outer_type_.__name__}) '
        else:
            type_ = f' ({field.outer_type_.__name__}) '
        env_var = ''
        if 'env' in field.field_info.extra:
            env_var = f' (Can be set by ``{field.field_info.extra["env"]}`` environment variable)'
        docs.append(f'    {name}{type_}: {field.field_info.description}{default_str}{env_var}')
    if klass.__doc__ is None:
        klass.__doc__ = ''
    klass.__doc__ += '\n'.join(docs)
    return klass
コード例 #11
0
ファイル: model.py プロジェクト: vanutp/fox_orm
    def __new__(mcs, name, bases, namespace, **kwargs):
        if bases[0] == BaseModel:
            return super().__new__(mcs, name, bases, namespace, **kwargs)

        inherited_columns = {}
        for base in bases[::-1]:
            if issubclass(base, OrmModel) and base is not OrmModel:
                inherited_columns.update(
                    {x.name: x.copy()
                     for x in base.__columns__.values()})

        mcs._ensure_proper_init(namespace)

        table_name = namespace.get('__tablename__',
                                   None) or camel_to_snake(name)
        metadata = namespace.get('__metadata__', None) or FoxOrm.metadata
        abstract = namespace.get('__abstract__', None) or False

        new_namespace = {}
        relation_namespace = {}
        for k, v in namespace.items():
            if k == '__tablename__':
                continue
            if isinstance(v, _GenericIterableRelation):
                relation_namespace[k] = v
            else:
                new_namespace[k] = v

        new_namespace['__annotations__'] = annotations = {}
        for k, v in namespace.get('__annotations__', {}).items():
            if k in relation_namespace:
                continue
            annotations[k] = v

        columns = {}
        for column_name, namespace_value in new_namespace.items():
            if not is_valid_column_name(
                    column_name) or not is_valid_column_value(namespace_value):
                continue
            if column_name not in annotations:
                raise OrmException(f'Unannotated field {column_name}')
            column, value = construct_column(column_name,
                                             annotations[column_name],
                                             namespace_value)
            columns[column.name] = column
            new_namespace[column_name] = value
        for column_name, annotation in annotations.items():
            if not is_valid_column_name(column_name):
                continue
            if column_name not in columns:
                column, _ = construct_column(column_name, annotation, tuple())
                columns[column.name] = column
        all_columns = inherited_columns.copy()
        all_columns.update(columns)

        # Hack for generating FastAPI models
        if (len(bases) == 1 and issubclass((base := bases[0]), OrmModel)
                and base is not OrmModel and base.__name__ == name):
            stack = traceback.extract_stack()
            if len(stack) >= 3:
                caller = stack[-3]
                if caller.name == 'create_cloned_field' and caller.filename.endswith(
                        f'{os.sep}fastapi{os.sep}utils.py'):
                    return ModelMetaclass(name, (BaseModel, ),
                                          base.get_namespace())