about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/marshmallow/class_registry.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/marshmallow/class_registry.py')
-rw-r--r--.venv/lib/python3.12/site-packages/marshmallow/class_registry.py103
1 files changed, 103 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/marshmallow/class_registry.py b/.venv/lib/python3.12/site-packages/marshmallow/class_registry.py
new file mode 100644
index 00000000..6c02f9cd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/marshmallow/class_registry.py
@@ -0,0 +1,103 @@
+"""A registry of :class:`Schema <marshmallow.Schema>` classes. This allows for string
+lookup of schemas, which may be used with
+class:`fields.Nested <marshmallow.fields.Nested>`.
+
+.. warning::
+
+    This module is treated as private API.
+    Users should not need to use this module directly.
+"""
+# ruff: noqa: ERA001
+
+from __future__ import annotations
+
+import typing
+
+from marshmallow.exceptions import RegistryError
+
+if typing.TYPE_CHECKING:
+    from marshmallow import Schema
+
+    SchemaType = type[Schema]
+
+# {
+#   <class_name>: <list of class objects>
+#   <module_path_to_class>: <list of class objects>
+# }
+_registry = {}  # type: dict[str, list[SchemaType]]
+
+
+def register(classname: str, cls: SchemaType) -> None:
+    """Add a class to the registry of serializer classes. When a class is
+    registered, an entry for both its classname and its full, module-qualified
+    path are added to the registry.
+
+    Example: ::
+
+        class MyClass:
+            pass
+
+
+        register("MyClass", MyClass)
+        # Registry:
+        # {
+        #   'MyClass': [path.to.MyClass],
+        #   'path.to.MyClass': [path.to.MyClass],
+        # }
+
+    """
+    # Module where the class is located
+    module = cls.__module__
+    # Full module path to the class
+    # e.g. user.schemas.UserSchema
+    fullpath = f"{module}.{classname}"
+    # If the class is already registered; need to check if the entries are
+    # in the same module as cls to avoid having multiple instances of the same
+    # class in the registry
+    if classname in _registry and not any(
+        each.__module__ == module for each in _registry[classname]
+    ):
+        _registry[classname].append(cls)
+    elif classname not in _registry:
+        _registry[classname] = [cls]
+
+    # Also register the full path
+    if fullpath not in _registry:
+        _registry.setdefault(fullpath, []).append(cls)
+    else:
+        # If fullpath does exist, replace existing entry
+        _registry[fullpath] = [cls]
+
+
+@typing.overload
+def get_class(classname: str, *, all: typing.Literal[False] = ...) -> SchemaType: ...
+
+
+@typing.overload
+def get_class(
+    classname: str, *, all: typing.Literal[True] = ...
+) -> list[SchemaType]: ...
+
+
+def get_class(classname: str, *, all: bool = False) -> list[SchemaType] | SchemaType:  # noqa: A002
+    """Retrieve a class from the registry.
+
+    :raises: `marshmallow.exceptions.RegistryError` if the class cannot be found
+        or if there are multiple entries for the given class name.
+    """
+    try:
+        classes = _registry[classname]
+    except KeyError as error:
+        raise RegistryError(
+            f"Class with name {classname!r} was not found. You may need "
+            "to import the class."
+        ) from error
+    if len(classes) > 1:
+        if all:
+            return _registry[classname]
+        raise RegistryError(
+            f"Multiple classes with name {classname!r} "
+            "were found. Please use the full, "
+            "module-qualified path."
+        )
+    return _registry[classname][0]