Repository URL to install this package:
|
Version:
0.18.5 ▾
|
beartype
/
__init__.py
|
|---|
#!/usr/bin/env python3
# --------------------( LICENSE )--------------------
# Copyright (c) 2014-2024 Beartype authors.
# See "LICENSE" for further details.
'''
**Beartype.**
For :pep:`8` compliance, this namespace exposes a subset of the metadata
constants published by the :mod:`beartype.meta` submodule. These metadata
constants are commonly inspected (and thus expected) by external automation.
'''
# ....................{ TODO }....................
#FIXME: Consider significantly expanding the above module docstring, assuming
#Sphinx presents this module in its generated frontmatter.
# ....................{ IMPORTS }....................
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# CAUTION: Explicitly list *ALL* public attributes imported below in the
# "__all__" list global declared below to avoid linter complaints.
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# CAUTION: To avoid race conditions during setuptools-based installation, this
# module may import *ONLY* from modules guaranteed to exist at the start of
# installation. This includes all standard Python and package submodules but
# *NOT* third-party dependencies, which if currently uninstalled will only be
# installed at some later time in the installation. Likewise, to avoid circular
# import dependencies, the top-level of this module should avoid importing
# package submodules where feasible.
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# CAUTION: To avoid polluting the public module namespace, external attributes
# should be locally imported at module scope *ONLY* under alternate private
# names (e.g., "from argparse import ArgumentParser as _ArgumentParser" rather
# than merely "from argparse import ArgumentParser").
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# ....................{ IMPORTS ~ meta }....................
# For PEP 8 compliance, versions constants expected by external automation are
# imported under their PEP 8-mandated names.
from beartype.meta import VERSION as __version__
from beartype.meta import VERSION_PARTS as __version_info__
# ....................{ IMPORTS ~ non-meta }....................
from sys import modules as _modules
# If this submodule is being imported at install time from our top-level
# "setup.py" script, avoid implicitly importing from *ANY* "beartype" submodule
# other than the "beartype.meta" submodule. By sheer force of will,
# "beartype.meta" is the *ONLY* "beartype" submodule guaranteed to be safely
# importable at install time. All other "beartype" submodules should be assumed
# to be unsafe due to potentially importing one or more optional runtime
# dependencies yet to be installed (e.g., "typing_extensions").
#
# See "setup.py" for gruesome details you do *NOT* want to know about.
if 'beartype.__is_installing__' not in _modules:
# Publicize the private @beartype._decor.beartype decorator as
# @beartype.beartype, preserving all implementation details as private.
from beartype._decor.decormain import (
beartype as beartype)
# Publicize all top-level configuration attributes required to configure the
# @beartype.beartype decorator.
from beartype._conf.confcls import (
BeartypeConf as BeartypeConf)
from beartype._conf.confenum import (
BeartypeStrategy as BeartypeStrategy,
BeartypeViolationVerbosity as BeartypeViolationVerbosity,
)
from beartype._conf.confoverrides import (
BeartypeHintOverrides as BeartypeHintOverrides)
# Else, this submodule is *NOT* being imported at install time.
# Delete the temporarily imported "sys.modules" global for ultimate safety.
del _modules
# ....................{ GLOBALS }....................
# Document all global variables imported into this namespace above.
__version__ = __version__
'''
Human-readable package version as a ``.``-delimited string.
For PEP 8 compliance, this specifier has the canonical name ``__version__``
rather than that of a typical global (e.g., ``VERSION_STR``).
'''
__version_info__ = __version_info__
'''
Machine-readable package version as a tuple of integers.
For PEP 8 compliance, this specifier has the canonical name
``__version_info__`` rather than that of a typical global (e.g.,
``VERSION_PARTS``).
'''
__all__ = [
'BeartypeConf',
'BeartypeHintOverrides',
'BeartypeStrategy',
'BeartypeViolationVerbosity',
'beartype',
'__version__',
'__version_info__',
]
'''
Special list global of the unqualified names of all public package attributes
explicitly exported by and thus safely importable from this package.
Caveats
-------
**This global is defined only for conformance with static type checkers,** a
necessary prerequisite for :pep:`561`-compliance. This global is *not* intended
to enable star imports of the form ``from beartype import *`` (now largely
considered a harmful anti-pattern by the Python community), although it
technically does the latter as well.
This global would ideally instead reference *only* a single package attribute
guaranteed *not* to exist (e.g., ``'STAR_IMPORTS_CONSIDERED_HARMFUL'``),
effectively disabling star imports. Since doing so induces spurious static
type-checking failures, we reluctantly embrace the standard approach. For
example, :mod:`mypy` emits an error resembling:
error: Module 'beartype' does not explicitly export attribute 'beartype';
implicit reexport disabled.
'''
# ....................{ DEPRECATIONS }....................
def __getattr__(attr_deprecated_name: str) -> object:
'''
Dynamically retrieve a deprecated attribute with the passed unqualified
name from this submodule and emit a non-fatal deprecation warning on each
such retrieval if this submodule defines this attribute *or* raise an
exception otherwise.
The Python interpreter implicitly calls this :pep:`562`-compliant module
dunder function under Python >= 3.7 *after* failing to directly retrieve an
explicit attribute with this name from this submodule. Since this dunder
function is only called in the event of an error, neither space nor time
efficiency are a concern here.
Parameters
----------
attr_deprecated_name : str
Unqualified name of the deprecated attribute to be retrieved.
Returns
----------
object
Value of this deprecated attribute.
Warns
----------
DeprecationWarning
If this attribute is deprecated.
Raises
----------
AttributeError
If this attribute is unrecognized and thus erroneous.
'''
# Isolate imports to avoid polluting the module namespace.
from beartype._util.module.utilmoddeprecate import deprecate_module_attr
# Package scope (i.e., dictionary mapping from the names to values of all
# non-deprecated attributes defined by this package).
attr_nondeprecated_name_to_value = globals()
# If this deprecated attribute is the deprecated "beartype.abby" submodule,
# forcibly import the non-deprecated "beartype.door" submodule aliased to
# "beartype.abby" into this package scope. For efficiency, this package does
# *NOT* unconditionally import and expose the "beartype.door" submodule
# above. That submodule does *NOT* exist in the globals() dictionary
# defaulted to above and *MUST* now be forcibly injected there.
if attr_deprecated_name == 'abby':
from beartype import door
attr_nondeprecated_name_to_value = {'door': door}
attr_nondeprecated_name_to_value.update(globals())
#FIXME: To support attribute-based deferred importation ala "lazy loading"
#of heavyweight subpackages like "beartype.door" and "beartype.vale", it
#looks like we'll need to manually add support here for that: e.g.,
# elif attr_deprecated_name in {'cave', 'claw', 'door', 'vale',}:
# #FIXME: Dynamically import this attribute here... somehow. Certainly, if
# #such functionality does *NOT* exist, add it to the existing
# #"utilmodimport" submodule: e.g.,
# attr_value = import_module_attr(f'beartype.{attr_deprecated_name}')
# attr_nondeprecated_name_to_value = {attr_deprecated_name: attr_value}
#FIXME: Rename "attr_deprecated_name" to merely "attr_name", please.
#FIXME: Revise docstring accordingly, please.
#FIXME: Exhaustively test this, please. Because we'll never manage to keep
#this in sync, we *ABSOLUTELY* should author a unit test that:
#* Decides the set of all public subpackages of "beartype".
#* Validates that each subpackage in this set is accessible as a
# "beartype.{subpackage_name}" attribute.
# Else, this deprecated attribute is any other attribute.
# Return the value of this deprecated attribute and emit a warning.
return deprecate_module_attr(
attr_deprecated_name=attr_deprecated_name,
attr_deprecated_name_to_nondeprecated_name={
'abby': 'door',
},
attr_nondeprecated_name_to_value=attr_nondeprecated_name_to_value,
)