Esempio n. 1
0
    def evaluate_forward_ref(self, globalns: Any, localns: Any) -> None:
        """
        Evaluates the ForwardRef to actual Field based on global and local namespaces

        :param globalns: global namespace
        :type globalns: Any
        :param localns: local namespace
        :type localns: Any
        :return: None
        :rtype: None
        """
        if self.to.__class__ == ForwardRef:
            self.to = evaluate_forwardref(
                self.to,  # type: ignore
                globalns,
                localns or None,
            )

            (self.__type__, self.column_type,) = populate_m2m_params_based_on_to_model(
                to=self.to, nullable=self.nullable,
            )

        if self.through.__class__ == ForwardRef:
            self.through = evaluate_forwardref(
                self.through,  # type: ignore
                globalns,
                localns or None,
            )
            forbid_through_relations(self.through)
Esempio n. 2
0
def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str,
                                                                  Any]) -> Any:
    annotation = param.annotation
    if isinstance(annotation, str):
        annotation = ForwardRef(annotation)
        annotation = evaluate_forwardref(annotation, globalns, globalns)
    return annotation
Esempio n. 3
0
    def evaluate_forward_ref(cls, globalns: Any, localns: Any) -> None:
        """
        Evaluates the ForwardRef to actual Field based on global and local namespaces

        :param globalns: global namespace
        :type globalns: Any
        :param localns: local namespace
        :type localns: Any
        :return: None
        :rtype: None
        """
        if cls.to.__class__ == ForwardRef:
            cls.to = evaluate_forwardref(
                cls.to,  # type: ignore
                globalns,
                localns or None,
            )
            (
                cls.__type__,
                cls.constraints,
                cls.column_type,
            ) = populate_fk_params_based_on_to_model(
                to=cls.to,
                nullable=cls.nullable,
                ondelete=cls.ondelete,
                onupdate=cls.onupdate,
            )
Esempio n. 4
0
def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any:
    annotation = param.annotation
    if isinstance(annotation, str):
        # Temporary ignore type
        # Ref: https://github.com/samuelcolvin/pydantic/issues/1738
        annotation = ForwardRef(annotation)  # type: ignore
        annotation = evaluate_forwardref(annotation, globalns, globalns)
    return annotation
Esempio n. 5
0
def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any:
    annotation = param.annotation
    if isinstance(annotation, str):
        try:
            annotation = ForwardRef(annotation)  # type: ignore
            annotation = evaluate_forwardref(annotation, globalns, globalns)
        except (TypeError, NameError):
            annotation = param.annotation
    return annotation
Esempio n. 6
0
def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str,
                                                                  Any]) -> Any:
    annotation = param.annotation
    if isinstance(annotation, str):
        annotation = ForwardRef(annotation)
        try:
            annotation = evaluate_forwardref(annotation, globalns, globalns)
        except Exception as e:
            logger.opt(colors=True, exception=e).warning(
                f'Unknown ForwardRef["{param.annotation}"] for parameter {param.name}'
            )
            return inspect.Parameter.empty
    return annotation
Esempio n. 7
0
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
Esempio n. 8
0
def get_typed_annotation(
    dependency_param: inspect.Parameter,
    global_namespace: Dict[str, Any],
) -> Any:
    """Solve forward reference annotation for instance of `inspect.Parameter`.

    Arguments:
        dependency_param: instance of `inspect.Parameter` for which possible forward
            annotation will be evaluated.
        global_namespace: dictionary of entities that can be used for evaluating
            forward references.

    Returns:
        Parameter annotation.
    """
    annotation = dependency_param.annotation
    if isinstance(annotation, str):
        annotation = ForwardRef(annotation)
        annotation = evaluate_forwardref(annotation, global_namespace, global_namespace)
    return annotation
Esempio n. 9
0
def make_forwardref(annotation: str, globalns: Dict[str, Any]):
    annotation = ForwardRef(annotation)
    annotation = evaluate_forwardref(annotation, globalns, globalns)
    return annotation
def find_graphene_type(
    type_: T.Type,
    field: ModelField,
    registry: Registry,
    parent_type: T.Type = None,
    model: T.Type[BaseModel] = None,
) -> BaseType:  # noqa: C901
    """
    Map a native Python type to a Graphene-supported Field type, where possible,
    throwing an error if we don't know what to map it to.
    """
    if type_ == uuid.UUID:
        return UUID
    elif type_ in (str, bytes):
        return String
    elif type_ == datetime.datetime:
        return DateTime
    elif type_ == datetime.date:
        return Date
    elif type_ == datetime.time:
        return Time
    elif type_ == bool:
        return Boolean
    elif type_ == float:
        return Float
    elif type_ == decimal.Decimal:
        return GrapheneDecimal if DECIMAL_SUPPORTED else Float
    elif type_ == int:
        return Int
    elif type_ in (tuple, list, set):
        # TODO: do Sets really belong here?
        return List
    elif registry and registry.get_type_for_model(type_):
        return registry.get_type_for_model(type_)
    elif registry and (isinstance(type_, BaseModel) or
                       (inspect.isclass(type_)
                        and issubclass(type_, BaseModel))):
        # If it's a Pydantic model that hasn't yet been wrapped with a ObjectType,
        # we can put a placeholder in and request that `resolve_placeholders()`
        # be called to update it.
        registry.add_placeholder_for_model(type_)
        return registry.get_type_for_model(type_)
    # NOTE: this has to come before any `issubclass()` checks, because annotated
    # generic types aren't valid arguments to `issubclass`
    elif hasattr(type_, "__origin__"):
        return convert_generic_python_type(type_,
                                           field,
                                           registry,
                                           parent_type=parent_type,
                                           model=model)
    elif isinstance(type_, T.ForwardRef):
        # A special case! We have to do a little hackery to try and resolve
        # the type that this points to, by trying to reference a "sibling" type
        # to where this was defined so we can get access to that namespace...
        sibling = model or parent_type
        if not sibling:
            raise ConversionError(
                "Don't know how to convert the Pydantic field "
                f"{field!r} ({field.type_}), could not resolve "
                "the forward reference. Did you call `resolve_placeholders()`? "
                "See the README for more on forward references.")
        module_ns = sys.modules[sibling.__module__].__dict__
        resolved = evaluate_forwardref(type_, module_ns, None)
        # TODO: make this behavior optional. maybe this is a place for the TypeOptions to play a role?
        if registry:
            registry.add_placeholder_for_model(resolved)
        return find_graphene_type(resolved,
                                  field,
                                  registry,
                                  parent_type=parent_type,
                                  model=model)
    elif issubclass(type_, enum.Enum):
        return Enum.from_enum(type_)
    elif issubclass(type_, str):
        return String
    else:
        raise ConversionError(
            f"Don't know how to convert the Pydantic field {field!r} ({field.type_})"
        )
Esempio n. 11
0
def make_forwardref(annotation: str, globalns: DictStrAny) -> Any:
    forward_ref = ForwardRef(annotation)
    return evaluate_forwardref(forward_ref, globalns, globalns)