summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/websockets/imports.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/websockets/imports.py')
-rw-r--r--venv/lib/python3.11/site-packages/websockets/imports.py99
1 files changed, 99 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/websockets/imports.py b/venv/lib/python3.11/site-packages/websockets/imports.py
new file mode 100644
index 0000000..a6a59d4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/websockets/imports.py
@@ -0,0 +1,99 @@
+from __future__ import annotations
+
+import warnings
+from typing import Any, Dict, Iterable, Optional
+
+
+__all__ = ["lazy_import"]
+
+
+def import_name(name: str, source: str, namespace: Dict[str, Any]) -> Any:
+ """
+ Import ``name`` from ``source`` in ``namespace``.
+
+ There are two use cases:
+
+ - ``name`` is an object defined in ``source``;
+ - ``name`` is a submodule of ``source``.
+
+ Neither :func:`__import__` nor :func:`~importlib.import_module` does
+ exactly this. :func:`__import__` is closer to the intended behavior.
+
+ """
+ level = 0
+ while source[level] == ".":
+ level += 1
+ assert level < len(source), "importing from parent isn't supported"
+ module = __import__(source[level:], namespace, None, [name], level)
+ return getattr(module, name)
+
+
+def lazy_import(
+ namespace: Dict[str, Any],
+ aliases: Optional[Dict[str, str]] = None,
+ deprecated_aliases: Optional[Dict[str, str]] = None,
+) -> None:
+ """
+ Provide lazy, module-level imports.
+
+ Typical use::
+
+ __getattr__, __dir__ = lazy_import(
+ globals(),
+ aliases={
+ "<name>": "<source module>",
+ ...
+ },
+ deprecated_aliases={
+ ...,
+ }
+ )
+
+ This function defines ``__getattr__`` and ``__dir__`` per :pep:`562`.
+
+ """
+ if aliases is None:
+ aliases = {}
+ if deprecated_aliases is None:
+ deprecated_aliases = {}
+
+ namespace_set = set(namespace)
+ aliases_set = set(aliases)
+ deprecated_aliases_set = set(deprecated_aliases)
+
+ assert not namespace_set & aliases_set, "namespace conflict"
+ assert not namespace_set & deprecated_aliases_set, "namespace conflict"
+ assert not aliases_set & deprecated_aliases_set, "namespace conflict"
+
+ package = namespace["__name__"]
+
+ def __getattr__(name: str) -> Any:
+ assert aliases is not None # mypy cannot figure this out
+ try:
+ source = aliases[name]
+ except KeyError:
+ pass
+ else:
+ return import_name(name, source, namespace)
+
+ assert deprecated_aliases is not None # mypy cannot figure this out
+ try:
+ source = deprecated_aliases[name]
+ except KeyError:
+ pass
+ else:
+ warnings.warn(
+ f"{package}.{name} is deprecated",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return import_name(name, source, namespace)
+
+ raise AttributeError(f"module {package!r} has no attribute {name!r}")
+
+ namespace["__getattr__"] = __getattr__
+
+ def __dir__() -> Iterable[str]:
+ return sorted(namespace_set | aliases_set | deprecated_aliases_set)
+
+ namespace["__dir__"] = __dir__