Skip to content

Commit

Permalink
Cleaning of internals (#58)
Browse files Browse the repository at this point in the history
* Remove old version
* Add handle annotations to the metaclass
  • Loading branch information
tarsil committed Aug 19, 2024
1 parent b426a56 commit 8074424
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
2 changes: 2 additions & 0 deletions mongoz/core/db/documents/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from mongoz import Document
from mongoz.core.signals import Broadcaster

mongoz_setattr = object.__setattr__


class BaseMongoz(BaseModel, metaclass=BaseModelMeta):
"""
Expand Down
40 changes: 37 additions & 3 deletions mongoz/core/db/documents/metaclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class MetaInfo:
"database",
"manager",
"autogenerate_index",
"from_collection"
"from_collection",
)

def __init__(self, meta: Any = None, **kwargs: Any) -> None:
Expand All @@ -67,7 +67,9 @@ def __init__(self, meta: Any = None, **kwargs: Any) -> None:
self.signals: Optional[Broadcaster] = {} # type: ignore
self.manager: "Manager" = getattr(meta, "manager", Manager())
self.autogenerate_index: bool = getattr(meta, "autogenerate_index", False)
self.from_collection: Union[AsyncIOMotorCollection, None] = getattr(meta, "from_collection", None)
self.from_collection: Union[AsyncIOMotorCollection, None] = getattr(
meta, "from_collection", None
)

def model_dump(self) -> Dict[Any, Any]:
return {k: getattr(self, k, None) for k in self.__slots__}
Expand Down Expand Up @@ -188,6 +190,28 @@ def _register_document_signals(model_class: Type["Document"]) -> None:
model_class.meta.signals = signals


def handle_annotations(
bases: Tuple[Type, ...], base_annotations: Dict[str, Any], attrs: Any
) -> Dict[str, Any]:
"""
Handles and copies some of the annotations for
initialiasation.
"""
for base in bases:
if hasattr(base, "__init_annotations__") and base.__init_annotations__:
base_annotations.update(base.__init_annotations__)
elif hasattr(base, "__annotations__") and base.__annotations__:
base_annotations.update(base.__annotations__)

annotations: Dict[str, Any] = (
copy.copy(attrs["__init_annotations__"])
if "__init_annotations__" in attrs
else copy.copy(attrs["__annotations__"])
)
annotations.update(base_annotations)
return annotations


class BaseModelMeta(ModelMetaclass):
__mongoz_fields__: ClassVar[Mapping[str, Type["MongozField"]]] = {}

Expand All @@ -198,11 +222,11 @@ def __new__(cls, name: str, bases: Tuple[Type, ...], attrs: Any) -> Any:
id_attribute: str = "id"
id_attribute_alias: str = "_id"
registry: Any = None
base_annotations: Dict[str, Any] = {}

# Extract the custom Mongoz Fields in a pydantic format.
attrs, model_fields = extract_field_annotations_and_defaults(attrs)
cls.__mongoz_fields__ = model_fields
super().__new__(cls, name, bases, attrs)

# Searching for fields "Field" in the class hierarchy.
def __search_for_fields(base: Type, attrs: Any) -> None:
Expand Down Expand Up @@ -256,6 +280,12 @@ def __search_for_fields(base: Type, attrs: Any) -> None:

model_class = super().__new__

# Handle annotations
annotations: Dict[str, Any] = handle_annotations(bases, base_annotations, attrs)

# Ensure the initialization is only performed for subclasses of Model
attrs["__init_annotations__"] = annotations

# Ensure the initialization is only performed for subclasses of Document
parents = [parent for parent in bases if isinstance(parent, BaseModelMeta)]
if not parents:
Expand Down Expand Up @@ -402,6 +432,10 @@ def __search_for_fields(base: Type, attrs: Any) -> None:
if not meta.abstract and meta.indexes and meta.autogenerate_index:
if not new_class.is_proxy_document:
run_sync(new_class.create_indexes())

# Protect the model namespaces to avoid UserWarnings on overriding the fields.
document_namespace = f"{new_class.__name__.lower()}_model_"
new_class.model_config["protected_namespaces"] = (document_namespace,)
return new_class

@property
Expand Down
2 changes: 1 addition & 1 deletion tests/models/manager/test_using.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Optional, AsyncGenerator
from typing import AsyncGenerator, List, Optional

import pydantic
import pytest
Expand Down

0 comments on commit 8074424

Please sign in to comment.