def from_xgboost( model: Union.__getitem__(tuple(xgb_operator_list)), # noqa inputs: Sequence[IOShape], device: str = 'cpu', extra_config: Optional[dict] = None, ) -> torch.nn.Module: """Convert PyTorch module from XGBoost""" # inputs for XGBoost should contains only 1 argument with 2 dim if not (len(inputs) == 1 and len(inputs[0].shape) == 2): raise RuntimeError( 'XGboost does not support such input data for inference. The input data should contains only 1\n' 'argument with exactly 2 dimensions.' ) if extra_config is None: extra_config = dict() # assert batch size batch_size = inputs[0].shape[0] if batch_size == -1: batch_size = 1 test_input = np.random.rand(batch_size, inputs[0].shape[1]) extra_config_ = PyTorchConverter.hb_common_extra_config.copy() extra_config_.update(extra_config) return _convert_xgboost( model, 'torch', test_input=test_input, device=device, extra_config=extra_config_ )
def from_sklearn( model: Union.__getitem__(tuple(sklearn_operator_list)), # noqa device: str = 'cpu', extra_config: Optional[dict] = None, ): if extra_config is None: extra_config = dict() extra_config_ = PyTorchConverter.hb_common_extra_config.copy() extra_config_.update(extra_config) return _convert_sklearn( model, 'torch', test_input=None, device=device, extra_config=extra_config_ )
def from_lightgbm( model: Union.__getitem__(tuple(lgbm_operator_list)), # noqa inputs: Optional[Sequence[IOShape]] = None, device: str = 'cpu', extra_config: Optional[dict] = None ): if extra_config is None: extra_config = dict() extra_config_ = PyTorchConverter.hb_common_extra_config.copy() extra_config_.update(extra_config) return _convert_lightgbm( model, 'torch', test_input=None, device=device, extra_config=extra_config_ )
def __make_pydantic(cls): """ Temporary wrapper function to convert an MSONable class into a PyDantic Model for the sake of building schemas """ if any(cls == T for T in built_in_primitives): return cls if cls in prim_to_type_hint: return prim_to_type_hint[cls] if cls == Any: return Any if type(cls) == TypeVar: return cls if hasattr(cls, "__origin__") and hasattr(cls, "__args__"): args = tuple(__make_pydantic(arg) for arg in cls.__args__) if cls.__origin__ == Union: return Union.__getitem__(args) if cls.__origin__ == Optional and len(args) == 1: return Optional.__getitem__(args) if cls._name == "List": return List.__getitem__(args) if cls._name == "Tuple": return Tuple.__getitem__(args) if cls._name == "Set": return Set.__getitem__(args) if cls._name == "Sequence": return Sequence.__getitem__(args) if issubclass(cls, MSONable): if cls.__name__ not in STUBS: STUBS[cls] = MSONable_to_pydantic(cls) return STUBS[cls] if cls == ndarray: return List[Any] return cls
def get(cls, type_or_hint, *, is_argument: bool = False) -> "TypeChecker": # This ensures the validity of the type passed (see typing documentation for info) type_or_hint = is_valid_type(type_or_hint, "Invalid type.", is_argument) if type_or_hint is Any: return AnyTypeChecker() if is_type(type_or_hint): return TypeTypeChecker.make(type_or_hint, is_argument) if is_literal_type(type_or_hint): return LiteralTypeChecker.make(type_or_hint, is_argument) if is_generic_type(type_or_hint): origin = get_origin(type_or_hint) if issubclass(origin, MappingCol): return MappingTypeChecker.make(type_or_hint, is_argument) if issubclass(origin, Collection): return CollectionTypeChecker.make(type_or_hint, is_argument) # CONSIDER: how to cater for exhaustible generators? if issubclass(origin, Iterable): raise NotImplementedError( "No type-checker is setup for iterables that exhaust.") return GenericTypeChecker.make(type_or_hint, is_argument) if is_tuple_type(type_or_hint): return TupleTypeChecker.make(type_or_hint, is_argument) if is_callable_type(type_or_hint): return CallableTypeChecker.make(type_or_hint, is_argument) if isclass(type_or_hint): if is_typed_dict(type_or_hint): return TypedDictChecker.make(type_or_hint, is_argument) return ConcreteTypeChecker.make(type_or_hint, is_argument) if is_union_type(type_or_hint): return UnionTypeChecker.make(type_or_hint, is_argument) if is_typevar(type_or_hint): bound_type = get_bound(type_or_hint) if bound_type: return cls.get(bound_type) constraints = get_constraints(type_or_hint) if constraints: union_type_checkers = tuple( cls.get(type_) for type_ in constraints) return UnionTypeChecker(Union.__getitem__(constraints), union_type_checkers) else: return AnyTypeChecker() if is_new_type(type_or_hint): super_type = getattr(type_or_hint, "__supertype__", None) if super_type is None: raise TypeError( f"No supertype for NewType: {type_or_hint}. This is not allowed." ) return cls.get(super_type) if is_forward_ref(type_or_hint): return ForwardTypeChecker.make(type_or_hint, is_argument=is_argument) if is_classvar(type_or_hint): var_type = get_args(type_or_hint, evaluate=True)[0] return cls.get(var_type) raise NotImplementedError( f"No {TypeChecker.__qualname__} is available for type or hint: '{type_or_hint}'" )
def coerce_hint_pep( func: Callable, pith_name: str, hint: object, hint_label: str, ) -> object: ''' Coerce the passed type hint annotating the parameter or return with the passed name of the passed callable into the corresponding PEP-compliant type hint if needed. Specifically, this function: * If this hint is a **PEP-noncompliant tuple union** (i.e., tuple of one or more standard classes and forward references to standard classes): * Coerces this tuple union into the equivalent `PEP 484`_-compliant union. * Replaces this tuple union in the ``__annotations__`` dunder tuple of this callable with this `PEP 484`_-compliant union. * Returns this `PEP 484`_-compliant union. * Else if this hint is already PEP-compliant, preserves and returns this hint unmodified as is. * Else (i.e., if this hint is neither PEP-compliant nor -noncompliant and thus invalid as a type hint), raise an exception. This getter is *not* memoized, due to being only called once per decorated callable parameter or return value and being efficient in any case. Parameters ---------- func : Callable Callable pith_name : str Either: * If this hint annotates a parameter, the name of that parameter. * If this hint annotates the return, ``"return"``. hint : object Type hint to be rendered PEP-compliant. hint_label : str Human-readable label describing this hint. Returns ---------- object Either: * If this hint is PEP-noncompliant, PEP-compliant type hint converted from this hint. * If this hint is PEP-compliant, hint unmodified as is. Raises ---------- BeartypeDecorHintNonPepException If this object is neither: * A PEP-noncompliant type hint. * A supported PEP-compliant type hint. .. _PEP 484: https://www.python.org/dev/peps/pep-0484 ''' # If this hint is a PEP-noncompliant tuple union, coerce this union into # the equivalent PEP-compliant union subscripted by the same child hints. # By definition, PEP-compliant unions are a strict superset of # PEP-noncompliant tuple unions and thus accept all child hints accepted by # the latter. if isinstance(hint, tuple): assert callable(func), f'{repr(func)} not callable.' assert isinstance(pith_name, str), f'{pith_name} not string.' hint = func.__annotations__[pith_name] = Union.__getitem__(hint) # Else, this hint is *NOT* a PEP-noncompliant tuple union. # If this object is neither a PEP-noncompliant type hint *NOR* supported # PEP-compliant type hint, raise an exception. die_unless_hint(hint=hint, hint_label=hint_label) # Else, this object is either a PEP-noncompliant type hint *OR* supported # PEP-compliant type hint. # Return this hint. return hint
def apparent_type(self): return Union.__getitem__(self.types)
def cache_hint_nonpep563( func: Callable, pith_name: str, hint: Any, hint_label: str, ) -> Any: ''' Coerce and cache the passed (possibly non-self-cached and/or PEP-noncompliant) type hint annotating the parameter or return value with the passed name of the passed callable into the equivalent :mod:`beartype`-cached PEP-compliant type hint if needed *or* silently reduce to a noop otherwise (i.e., if this hint is already both self-cached and PEP-compliant). Specifically, this function (in order): #. If the passed type hint is already self-cached, this hint is already PEP-compliant by definition. In this case, this function preserves and returns this hint as is. #. Else if a semantically equivalent type hint (i.e., having the same machine-readable representation) as this hint was already cached by a prior call to this function, the current call to this function: * Replaces this hint in the ``__annotations__`` dunder tuple of this callable with this previously cached hint, minimizing memory space consumption across the lifetime of the active Python process. * Returns this previously cached hint. #. Else if this hint is a **PEP-noncompliant tuple union** (i.e., tuple of one or more standard classes and forward references to standard classes), this function: * Coerces this tuple union into the equivalent `PEP 484`_-compliant union. * Replaces this tuple union in the ``__annotations__`` dunder tuple of this callable with this `PEP 484`_-compliant union. #. Else (i.e., if this hint is neither PEP-compliant nor -noncompliant and thus unsupported by :mod:`beartype`), this function raises an exception. #. Internally caches this hint with the :data:`_HINT_REPR_TO_HINT` dictionary. #. Returns this hint. This function *cannot* be meaningfully memoized, since the passed type hint is *not* guaranteed to be cached somewhere. Only functions passed cached type hints can be meaningfully memoized. The ``_nonpep563`` substring suffixing the name of this function implies this function is intended to be called *after* all possibly `PEP 563`_-compliant **deferred type hints** (i.e., type hints persisted as evaluatable strings rather than actual type hints) annotating this callable if any have been evaluated into actual type hints. Design ------ This function does *not* bother caching **self-cached type hints** (i.e., type hints that externally cache themselves), as these hints are already cached elsewhere. Self-cached type hints include most `PEP 484`_-compliant type hints declared by the :mod:`typing` module, which means that subscripting type hints declared by the :mod:`typing` module with the same child type hints reuses the exact same internally cached objects rather than creating new uncached objects: e.g., .. code-block:: python >>> import typing >>> typing.List[int] is typing.List[int] True Equivalently, this function *only* caches **non-self-cached type hints** (i.e., type hints that do *not* externally cache themselves), as these hints are *not* already cached elsewhere. Non-self-cached type hints include *all* `PEP 585`_-compliant type hints produced by subscripting builtin container types, which means that subscripting builtin container types with the same child type hints creates new uncached objects rather than reusing the same internally cached objects: e.g., .. code-block:: python >>> list[int] is list[int] False Motivation ---------- This function enables callers to coerce non-self-cached type hints into :mod:`beartype`-cached type hints. :mod:`beartype` effectively requires *all* type hints to be cached somewhere! :mod:`beartype` does *not* care who, what, or how is caching those type hints -- only that they are cached before being passed to utility functions in the :mod:`beartype` codebase. Why? Because most such utility functions are memoized for efficiency by the :func:`beartype._util.cache.utilcachecall.callable_cached` decorator, which maps passed parameters (typically including the standard ``hint`` parameter accepting a type hint) based on object identity to previously cached return values. You see the problem, we trust. Non-self-cached type hints that are otherwise semantically equal are nonetheless distinct objects and will thus be treated as distinct parameters by memoization decorators. If this function did *not* exist, non-self-cached type hints could *not* be coerced into :mod:`beartype`-cached type hints and thus could *not* be memoized, reducing the efficiency of :mod:`beartype` for standard type hints. Parameters ---------- func : Callable Callable annotated by this hint. pith_name : str Either: * If this hint annotates a parameter, the name of that parameter. * If this hint annotates the return, ``"return"``. hint : object Possibly non-self-cached and/or PEP-noncompliant type hint to be coerced and cached into the equivalent :mod:`beartype`-cached PEP-compliant type hint. hint_label : str Human-readable label describing this hint. Returns ---------- object Either: * If this hint is either non-self-cached *or* PEP-noncompliant, the equivalent :mod:`beartype`-cached PEP-compliant type hint coerced and cached from this hint. * If this hint is self-cached *and* PEP-compliant, this hint as is. Raises ---------- BeartypeDecorHintNonPepException If this object is neither: * A PEP-noncompliant type hint. * A supported PEP-compliant type hint. .. _PEP 484: https://www.python.org/dev/peps/pep-0484 .. _PEP 563: https://www.python.org/dev/peps/pep-0563 .. _PEP 585: https://www.python.org/dev/peps/pep-0585 ''' #FIXME: Call the new is_hint_pep_uncached() tester here to decide whether #or not to cache this hint. # If this hint is a PEP-noncompliant tuple union, coerce this union into # the equivalent PEP-compliant union subscripted by the same child hints. # By definition, PEP-compliant unions are a strict superset of # PEP-noncompliant tuple unions and thus accept all child hints accepted by # the latter. if isinstance(hint, tuple): assert callable(func), f'{repr(func)} not callable.' assert isinstance(pith_name, str), f'{pith_name} not string.' hint = func.__annotations__[pith_name] = Union.__getitem__(hint) # Else, this hint is *NOT* a PEP-noncompliant tuple union. # If this object is neither a PEP-noncompliant type hint *NOR* supported # PEP-compliant type hint, raise an exception. die_unless_hint(hint=hint, hint_label=hint_label) # Else, this object is either a PEP-noncompliant type hint *OR* supported # PEP-compliant type hint. # Return this hint. return hint
def typeddict_to_dict(cls: Any) -> Any: return Dict[str, Union.__getitem__(tuple(cls.__annotations__.values()))]