Coverage for pyodmongo/models/metaclasses.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-16 15:08 +0000

1from typing import Any 

2from ..services.model_init import ( 

3 resolve_indexes, 

4 resolve_class_fields_db_info, 

5) 

6from pydantic import BaseModel 

7from pydantic._internal._model_construction import ModelMetaclass 

8from typing_extensions import dataclass_transform 

9 

10 

11@dataclass_transform(kw_only_default=True) 

12class PyOdmongoMeta(ModelMetaclass): 

13 """ 

14 Metaclass for creating and configuring PyODMongo models. This metaclass extends 

15 the functionality of Pydantic's ModelMetaclass to include database-specific 

16 configurations and transformations. 

17 

18 The primary responsibilities of this metaclass are: 

19 - Setting and tracking the `__pyodmongo_complete__` attribute to ensure proper 

20 initialization of database-related features. 

21 - Applying necessary transformations to class fields for database compatibility. 

22 - Providing custom attribute access behavior for dynamically generated attributes. 

23 

24 Attributes: 

25 __pyodmongo_complete__ (bool): Indicator of whether the meta-level 

26 configuration is complete. 

27 

28 Methods: 

29 __new__(cls, name, bases, namespace, **kwargs): Constructs a new class instance, 

30 applying database-specific initializations. 

31 __getattr__(cls, name): Custom attribute access method supporting dynamic 

32 attribute retrieval based on model fields. 

33 """ 

34 

35 def __new__( 

36 cls, name: str, bases: tuple[Any], namespace: dict, **kwargs: Any 

37 ) -> type: 

38 setattr(cls, "__pyodmongo_complete__", False) 

39 for base in bases: 

40 setattr(base, "__pyodmongo_complete__", False) 

41 

42 cls: BaseModel = ModelMetaclass.__new__(cls, name, bases, namespace, **kwargs) 

43 

44 setattr(cls, "__pyodmongo_complete__", True) 

45 for base in bases: 

46 setattr(base, "__pyodmongo_complete__", True) 

47 

48 resolve_class_fields_db_info(cls=cls) 

49 return cls 

50 

51 def __getattr__(cls, name: str): 

52 if cls.__dict__.get("__pyodmongo_complete__") and cls.__dict__.get( 

53 name + "__pyodmongo" 

54 ): 

55 return cls.__dict__.get(name + "__pyodmongo") 

56 ModelMetaclass.__getattr__(cls, name) 

57 

58 

59@dataclass_transform(kw_only_default=True) 

60class DbMeta(PyOdmongoMeta): 

61 """ 

62 Metaclass for database model entities in a PyODMongo environment. It extends 

63 the functionality of the PyOdmongoMeta by applying specific behaviors and 

64 transformations related to database operations such as indexing, reference 

65 resolution, and initialization of database fields. 

66 

67 The primary responsibilities of this metaclass are: 

68 - Constructing new class instances with additional database-specific adjustments 

69 and initializations. 

70 - Setting up pipelines for resolving references within the database context. 

71 - Configuring indexes for efficient database operations. 

72 

73 Attributes: 

74 __pyodmongo_complete__ (bool): Attribute used to track the completion of 

75 the meta-level configuration. 

76 

77 Methods: 

78 __new__(cls, name, bases, namespace, **kwargs): Constructs a new class instance, 

79 ensuring database-specific adjustments and initializations are applied. 

80 """ 

81 

82 def __new__( 

83 cls, name: str, bases: tuple[Any], namespace: dict, **kwargs: Any 

84 ) -> type: 

85 cls: BaseModel = PyOdmongoMeta.__new__(cls, name, bases, namespace, **kwargs) 

86 

87 indexes = resolve_indexes(cls=cls) 

88 setattr(cls, "_init_indexes", indexes) 

89 return cls