ramifice 0.3.27__py3-none-any.whl → 0.3.29__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. ramifice/__init__.py +2 -1
  2. ramifice/commons/__init__.py +1 -3
  3. ramifice/commons/general.py +9 -9
  4. ramifice/commons/indexes.py +7 -7
  5. ramifice/commons/many.py +19 -15
  6. ramifice/commons/one.py +23 -13
  7. ramifice/commons/tools.py +62 -57
  8. ramifice/commons/{units.py → unit_manager.py} +5 -7
  9. ramifice/fields/bool_field.py +3 -3
  10. ramifice/fields/choice_float_dyn_field.py +3 -3
  11. ramifice/fields/choice_float_field.py +3 -3
  12. ramifice/fields/choice_float_mult_dyn_field.py +3 -3
  13. ramifice/fields/choice_float_mult_field.py +3 -3
  14. ramifice/fields/choice_int_dyn_field.py +3 -3
  15. ramifice/fields/choice_int_field.py +3 -3
  16. ramifice/fields/choice_int_mult_dyn_field.py +3 -3
  17. ramifice/fields/choice_int_mult_field.py +3 -3
  18. ramifice/fields/choice_text_dyn_field.py +3 -3
  19. ramifice/fields/choice_text_field.py +3 -3
  20. ramifice/fields/choice_text_mult_dyn_field.py +3 -3
  21. ramifice/fields/choice_text_mult_field.py +3 -3
  22. ramifice/fields/color_field.py +4 -4
  23. ramifice/fields/date_field.py +2 -2
  24. ramifice/fields/date_time_field.py +2 -2
  25. ramifice/fields/email_field.py +3 -3
  26. ramifice/fields/file_field.py +4 -4
  27. ramifice/fields/float_field.py +3 -3
  28. ramifice/fields/id_field.py +2 -2
  29. ramifice/fields/image_field.py +4 -4
  30. ramifice/fields/integer_field.py +3 -3
  31. ramifice/fields/ip_field.py +3 -3
  32. ramifice/fields/password_field.py +2 -2
  33. ramifice/fields/phone_field.py +3 -3
  34. ramifice/fields/slug_field.py +3 -3
  35. ramifice/fields/text_field.py +3 -3
  36. ramifice/fields/url_field.py +3 -3
  37. ramifice/models/__init__.py +1 -0
  38. ramifice/{decorators.py → models/decorator.py} +11 -13
  39. ramifice/{model.py → models/model.py} +4 -4
  40. ramifice/{pseudo_model.py → models/pseudo.py} +4 -4
  41. ramifice/paladins/check.py +11 -11
  42. ramifice/paladins/delete.py +10 -10
  43. ramifice/paladins/groups/choice_group.py +1 -1
  44. ramifice/paladins/groups/date_group.py +1 -1
  45. ramifice/paladins/groups/file_group.py +2 -2
  46. ramifice/paladins/groups/id_group.py +1 -1
  47. ramifice/paladins/groups/img_group.py +2 -2
  48. ramifice/paladins/groups/num_group.py +1 -1
  49. ramifice/paladins/groups/pass_group.py +2 -2
  50. ramifice/paladins/groups/slug_group.py +1 -1
  51. ramifice/paladins/groups/text_group.py +3 -3
  52. ramifice/paladins/password.py +10 -10
  53. ramifice/paladins/refrash.py +7 -7
  54. ramifice/paladins/save.py +16 -16
  55. ramifice/paladins/tools.py +1 -1
  56. ramifice/paladins/validation.py +4 -4
  57. ramifice/utils/__init__.py +1 -0
  58. ramifice/{store.py → utils/globals.py} +2 -4
  59. ramifice/{migration.py → utils/migration.py} +17 -17
  60. ramifice/utils/mixins/__init__.py +6 -0
  61. ramifice/{add_valid.py → utils/mixins/add_valid.py} +2 -2
  62. ramifice/{hooks.py → utils/mixins/hooks.py} +2 -2
  63. ramifice/utils/mixins/indexing.py +11 -0
  64. ramifice/{mixins.py → utils/mixins/json_converter.py} +2 -5
  65. ramifice/{tools.py → utils/tools.py} +1 -1
  66. ramifice/{types.py → utils/unit.py} +2 -9
  67. {ramifice-0.3.27.dist-info → ramifice-0.3.29.dist-info}/METADATA +5 -6
  68. ramifice-0.3.29.dist-info/RECORD +85 -0
  69. ramifice/indexing.py +0 -11
  70. ramifice-0.3.27.dist-info/RECORD +0 -82
  71. /ramifice/{errors.py → utils/errors.py} +0 -0
  72. /ramifice/{fixtures.py → utils/fixtures.py} +0 -0
  73. /ramifice/{translations.py → utils/translations.py} +0 -0
  74. {ramifice-0.3.27.dist-info → ramifice-0.3.29.dist-info}/WHEEL +0 -0
  75. {ramifice-0.3.27.dist-info → ramifice-0.3.29.dist-info}/licenses/LICENSE +0 -0
@@ -6,8 +6,8 @@ from typing import Any
6
6
 
7
7
  from pymongo.asynchronous.collection import AsyncCollection
8
8
 
9
- from .. import store
10
- from ..errors import PanicError
9
+ from ..utils import globals
10
+ from ..utils.errors import PanicError
11
11
 
12
12
 
13
13
  class DeleteMixin:
@@ -27,26 +27,26 @@ class DeleteMixin:
27
27
  """Delete document from database."""
28
28
  cls_model = self.__class__
29
29
  # Raises a panic if the Model cannot be removed.
30
- if not cls_model.META["is_delete_doc"]: # type: ignore[attr-defined]
30
+ if not cls_model.META["is_delete_doc"]:
31
31
  msg = (
32
- f"Model: `{cls_model.META['full_model_name']}` > " # type: ignore[attr-defined]
32
+ f"Model: `{cls_model.META['full_model_name']}` > "
33
33
  + "META param: `is_delete_doc` (False) => "
34
34
  + "Documents of this Model cannot be removed from the database!"
35
35
  )
36
36
  raise PanicError(msg)
37
37
  # Get documet ID.
38
- doc_id = self._id.value # type: ignore[attr-defined]
38
+ doc_id = self._id.value
39
39
  if doc_id is None:
40
40
  msg = (
41
- f"Model: `{cls_model.META['full_model_name']}` > " # type: ignore[attr-defined]
41
+ f"Model: `{cls_model.META['full_model_name']}` > "
42
42
  + "Field: `_id` > "
43
43
  + "Param: `value` => ID is missing."
44
44
  )
45
45
  raise PanicError(msg)
46
46
  # Run hook.
47
- await self.pre_delete() # type: ignore[attr-defined]
47
+ await self.pre_delete()
48
48
  # Get collection for current Model.
49
- collection: AsyncCollection = store.MONGO_DATABASE[cls_model.META["collection_name"]] # type: ignore[index, attr-defined]
49
+ collection: AsyncCollection = globals.MONGO_DATABASE[cls_model.META["collection_name"]]
50
50
  # Delete document.
51
51
  mongo_doc: dict[str, Any] = {}
52
52
  mongo_doc = await collection.find_one_and_delete(
@@ -62,7 +62,7 @@ class DeleteMixin:
62
62
  # If the document failed to delete.
63
63
  if not bool(mongo_doc):
64
64
  msg = (
65
- f"Model: `{cls_model.META['full_model_name']}` > " # type: ignore[attr-defined]
65
+ f"Model: `{cls_model.META['full_model_name']}` > "
66
66
  + "Method: `delete` => "
67
67
  + "The document was not deleted, the document is absent in the database."
68
68
  )
@@ -86,6 +86,6 @@ class DeleteMixin:
86
86
  file_data = None
87
87
  field_data.value = None
88
88
  # Run hook.
89
- await self.post_delete() # type: ignore[attr-defined]
89
+ await self.post_delete()
90
90
  #
91
91
  return mongo_doc
@@ -9,7 +9,7 @@ Supported fields:
9
9
 
10
10
  from typing import Any
11
11
 
12
- from ... import translations
12
+ from ...utils import translations
13
13
  from ..tools import accumulate_error
14
14
 
15
15
 
@@ -9,7 +9,7 @@ from typing import Any
9
9
 
10
10
  from babel.dates import format_date, format_datetime
11
11
 
12
- from ... import translations
12
+ from ...utils import translations
13
13
  from ..tools import accumulate_error, panic_type_error
14
14
 
15
15
 
@@ -5,8 +5,8 @@ Supported fields: FileField
5
5
 
6
6
  from typing import Any
7
7
 
8
- from ... import translations
9
- from ...tools import to_human_size
8
+ from ...utils import translations
9
+ from ...utils.tools import to_human_size
10
10
  from ..tools import accumulate_error, panic_type_error
11
11
 
12
12
 
@@ -8,7 +8,7 @@ from typing import Any
8
8
 
9
9
  from bson.objectid import ObjectId
10
10
 
11
- from ... import translations
11
+ from ...utils import translations
12
12
  from ..tools import accumulate_error, panic_type_error
13
13
 
14
14
 
@@ -7,8 +7,8 @@ from typing import Any
7
7
 
8
8
  from PIL import Image
9
9
 
10
- from ... import translations
11
- from ...tools import to_human_size
10
+ from ...utils import translations
11
+ from ...utils.tools import to_human_size
12
12
  from ..tools import accumulate_error, panic_type_error
13
13
 
14
14
 
@@ -6,7 +6,7 @@ Supported fields:
6
6
 
7
7
  from typing import Any
8
8
 
9
- from ... import translations
9
+ from ...utils import translations
10
10
  from ..tools import accumulate_error, check_uniqueness, panic_type_error
11
11
 
12
12
 
@@ -7,8 +7,8 @@ from typing import Any
7
7
 
8
8
  from argon2 import PasswordHasher
9
9
 
10
- from ... import translations
11
- from ...tools import is_password
10
+ from ...utils import translations
11
+ from ...utils.tools import is_password
12
12
  from ..tools import accumulate_error, panic_type_error
13
13
 
14
14
 
@@ -8,7 +8,7 @@ from typing import Any
8
8
 
9
9
  from slugify import slugify
10
10
 
11
- from ...errors import PanicError
11
+ from ...utils.errors import PanicError
12
12
  from ..tools import check_uniqueness
13
13
 
14
14
 
@@ -9,8 +9,8 @@ from typing import Any
9
9
 
10
10
  from email_validator import EmailNotValidError, validate_email
11
11
 
12
- from ... import translations
13
- from ...tools import is_color, is_ip, is_phone, is_url
12
+ from ...utils import translations
13
+ from ...utils.tools import is_color, is_ip, is_phone, is_url
14
14
  from ..tools import accumulate_error, check_uniqueness, panic_type_error
15
15
 
16
16
 
@@ -53,7 +53,7 @@ class TextGroupMixin:
53
53
  try:
54
54
  emailinfo = validate_email(
55
55
  str(value),
56
- check_deliverability=self.__class__.META["is_migrate_model"], # type: ignore[attr-defined]
56
+ check_deliverability=self.__class__.META["is_migrate_model"],
57
57
  )
58
58
  value = emailinfo.normalized
59
59
  params["field_data"].value = value
@@ -5,8 +5,8 @@ from typing import Any
5
5
  from argon2 import PasswordHasher
6
6
  from pymongo.asynchronous.collection import AsyncCollection
7
7
 
8
- from .. import store
9
- from ..errors import OldPassNotMatchError, PanicError
8
+ from ..utils import globals
9
+ from ..utils.errors import OldPassNotMatchError, PanicError
10
10
 
11
11
 
12
12
  class PasswordMixin:
@@ -20,30 +20,30 @@ class PasswordMixin:
20
20
  """For password verification."""
21
21
  cls_model = self.__class__
22
22
  # Get documet ID.
23
- doc_id = self._id.value # type: ignore[attr-defined]
23
+ doc_id = self._id.value
24
24
  if doc_id is None:
25
25
  msg = (
26
- f"Model: `{cls_model.META['full_model_name']}` > " # type: ignore[attr-defined]
26
+ f"Model: `{cls_model.META['full_model_name']}` > "
27
27
  + "Method: `verify_password` => "
28
28
  + "Cannot get document ID - ID field is empty."
29
29
  )
30
30
  raise PanicError(msg)
31
31
  # Get collection for current Model.
32
- collection: AsyncCollection = store.MONGO_DATABASE[cls_model.META["collection_name"]] # type: ignore[index, attr-defined]
32
+ collection: AsyncCollection = globals.MONGO_DATABASE[cls_model.META["collection_name"]]
33
33
  # Get document.
34
34
  mongo_doc: dict[str, Any] | None = await collection.find_one({"_id": doc_id})
35
35
  if mongo_doc is None:
36
36
  msg = (
37
- f"Model: `{cls_model.META['full_model_name']}` > " # type: ignore[attr-defined]
37
+ f"Model: `{cls_model.META['full_model_name']}` > "
38
38
  + "Method: `verify_password` => "
39
- + f"There is no document with ID `{self._id.value}` in the database." # type: ignore[attr-defined]
39
+ + f"There is no document with ID `{self._id.value}` in the database."
40
40
  )
41
41
  raise PanicError(msg)
42
42
  # Get password hash.
43
43
  hash: str | None = mongo_doc.get(field_name)
44
44
  if hash is None:
45
45
  msg = (
46
- f"Model: `{cls_model.META['full_model_name']}` > " # type: ignore[attr-defined]
46
+ f"Model: `{cls_model.META['full_model_name']}` > "
47
47
  + "Method: `verify_password` => "
48
48
  + f"The model does not have a field `{field_name}`."
49
49
  )
@@ -73,9 +73,9 @@ class PasswordMixin:
73
73
  if not await self.verify_password(old_password, field_name):
74
74
  raise OldPassNotMatchError()
75
75
  # Get documet ID.
76
- doc_id = self._id.value # type: ignore[attr-defined]
76
+ doc_id = self._id.value
77
77
  # Get collection for current Model.
78
- collection: AsyncCollection = store.MONGO_DATABASE[cls_model.META["collection_name"]] # type: ignore[index, attr-defined]
78
+ collection: AsyncCollection = globals.MONGO_DATABASE[cls_model.META["collection_name"]]
79
79
  # Create hash of new passwor.
80
80
  ph = PasswordHasher()
81
81
  hash: str = ph.hash(new_password)
@@ -4,8 +4,8 @@ from typing import Any
4
4
 
5
5
  from pymongo.asynchronous.collection import AsyncCollection
6
6
 
7
- from .. import store
8
- from ..errors import PanicError
7
+ from ..utils import globals
8
+ from ..utils.errors import PanicError
9
9
  from .tools import refresh_from_mongo_doc
10
10
 
11
11
 
@@ -16,14 +16,14 @@ class RefrashMixin:
16
16
  """Update Model instance from database."""
17
17
  cls_model = self.__class__
18
18
  # Get collection.
19
- collection: AsyncCollection = store.MONGO_DATABASE[cls_model.META["collection_name"]] # type: ignore[index, attr-defined]
20
- mongo_doc: dict[str, Any] | None = await collection.find_one(filter={"_id": self._id.value}) # type: ignore[attr-defined]
19
+ collection: AsyncCollection = globals.MONGO_DATABASE[cls_model.META["collection_name"]]
20
+ mongo_doc: dict[str, Any] | None = await collection.find_one(filter={"_id": self._id.value})
21
21
  if mongo_doc is None:
22
22
  msg = (
23
- f"Model: `{self.full_model_name()}` > " # type: ignore[attr-defined]
23
+ f"Model: `{self.full_model_name()}` > "
24
24
  + "Method: `refrash_from_db` => "
25
- + f"A document with an identifier `{self._id.value}` is not exists in the database!" # type: ignore[attr-defined]
25
+ + f"A document with an identifier `{self._id.value}` is not exists in the database!"
26
26
  )
27
27
  raise PanicError(msg)
28
- self.inject() # type: ignore[attr-defined]
28
+ self.inject()
29
29
  refresh_from_mongo_doc(self, mongo_doc)
ramifice/paladins/save.py CHANGED
@@ -5,8 +5,8 @@ from typing import Any
5
5
 
6
6
  from pymongo.asynchronous.collection import AsyncCollection
7
7
 
8
- from .. import store
9
- from ..errors import PanicError
8
+ from ..utils import globals
9
+ from ..utils.errors import PanicError
10
10
  from .tools import ignored_fields_to_none, refresh_from_mongo_doc
11
11
 
12
12
 
@@ -20,17 +20,17 @@ class SaveMixin:
20
20
  """
21
21
  cls_model = self.__class__
22
22
  # Get collection.
23
- collection: AsyncCollection = store.MONGO_DATABASE[cls_model.META["collection_name"]] # type: ignore[index, attr-defined]
23
+ collection: AsyncCollection = globals.MONGO_DATABASE[cls_model.META["collection_name"]]
24
24
  # Check Model.
25
- result_check: dict[str, Any] = await self.check(is_save=True, collection=collection) # type: ignore[attr-defined]
25
+ result_check: dict[str, Any] = await self.check(is_save=True, collection=collection)
26
26
  # Reset the alerts to exclude duplicates.
27
- self._id.alerts = [] # type: ignore[attr-defined]
27
+ self._id.alerts = []
28
28
  # Check the conditions and, if necessary, define a message for the web form.
29
- if not result_check["is_update"] and not cls_model.META["is_create_doc"]: # type: ignore[attr-defined]
30
- self._id.alerts.append("It is forbidden to create new documents !") # type: ignore[attr-defined]
29
+ if not result_check["is_update"] and not cls_model.META["is_create_doc"]:
30
+ self._id.alerts.append("It is forbidden to create new documents !")
31
31
  result_check["is_valid"] = False
32
- if result_check["is_update"] and not cls_model.META["is_update_doc"]: # type: ignore[attr-defined]
33
- self._id.alerts.append("It is forbidden to update documents !") # type: ignore[attr-defined]
32
+ if result_check["is_update"] and not cls_model.META["is_update_doc"]:
33
+ self._id.alerts.append("It is forbidden to update documents !")
34
34
  result_check["is_valid"] = False
35
35
  # Leave the method if the check fails.
36
36
  if not result_check["is_valid"]:
@@ -43,18 +43,18 @@ class SaveMixin:
43
43
  # Update date and time.
44
44
  checked_data["updated_at"] = datetime.now()
45
45
  # Run hook.
46
- await self.pre_update() # type: ignore[attr-defined]
46
+ await self.pre_update()
47
47
  # Update doc.
48
48
  await collection.update_one({"_id": checked_data["_id"]}, {"$set": checked_data})
49
49
  # Run hook.
50
- await self.post_update() # type: ignore[attr-defined]
50
+ await self.post_update()
51
51
  # Refresh Model.
52
52
  mongo_doc: dict[str, Any] | None = await collection.find_one(
53
53
  {"_id": checked_data["_id"]}
54
54
  )
55
55
  if mongo_doc is None:
56
56
  msg = (
57
- f"Model: `{self.full_model_name()}` > " # type: ignore[attr-defined]
57
+ f"Model: `{self.full_model_name()}` > "
58
58
  + "Method: `save` => "
59
59
  + "Geted value is None - it is impossible to refresh the current Model."
60
60
  )
@@ -66,16 +66,16 @@ class SaveMixin:
66
66
  checked_data["created_at"] = today
67
67
  checked_data["updated_at"] = today
68
68
  # Run hook.
69
- await self.pre_create() # type: ignore[attr-defined]
69
+ await self.pre_create()
70
70
  # Insert doc.
71
71
  await collection.insert_one(checked_data)
72
72
  # Run hook.
73
- await self.post_create() # type: ignore[attr-defined]
73
+ await self.post_create()
74
74
  # Refresh Model.
75
75
  mongo_doc = await collection.find_one({"_id": checked_data["_id"]})
76
76
  if mongo_doc is None:
77
77
  msg = (
78
- f"Model: `{self.full_model_name()}` > " # type: ignore[attr-defined]
78
+ f"Model: `{self.full_model_name()}` > "
79
79
  + "Method: `save` => "
80
80
  + "Geted value is None - it is impossible to refresh the current Model."
81
81
  )
@@ -84,7 +84,7 @@ class SaveMixin:
84
84
  refresh_from_mongo_doc(self, mongo_doc)
85
85
  else:
86
86
  msg = (
87
- f"Model: `{self.full_model_name()}` > " # type: ignore[attr-defined]
87
+ f"Model: `{self.full_model_name()}` > "
88
88
  + "Method: `save` => "
89
89
  + "The document was not created."
90
90
  )
@@ -2,7 +2,7 @@
2
2
 
3
3
  from typing import Any
4
4
 
5
- from ..errors import PanicError
5
+ from ..utils.errors import PanicError
6
6
 
7
7
 
8
8
  def ignored_fields_to_none(inst_model: Any) -> None:
@@ -14,7 +14,7 @@ class ValidationMixin:
14
14
  The main use is to check data from web forms.
15
15
  It is also used to verify Models that do not migrate to the database.
16
16
  """
17
- result_check: dict[str, Any] = await self.check() # type: ignore[attr-defined]
17
+ result_check: dict[str, Any] = await self.check()
18
18
  return result_check["is_valid"]
19
19
 
20
20
  def print_err(self) -> None:
@@ -31,17 +31,17 @@ class ValidationMixin:
31
31
  if not is_err:
32
32
  print(colored("\nERRORS:", "red", attrs=["bold"]))
33
33
  print(colored("Model: ", "blue", attrs=["bold"]), end="")
34
- print(colored(f"`{self.full_model_name()}`", "blue")) # type: ignore[attr-defined]
34
+ print(colored(f"`{self.full_model_name()}`", "blue"))
35
35
  is_err = True
36
36
  # field name
37
37
  print(colored("Field: ", "green", attrs=["bold"]), end="")
38
38
  print(colored(f"`{field_name}`:", "green"))
39
39
  # error messages
40
40
  print(colored("\n".join(field_data.errors), "red"))
41
- if len(self._id.alerts) > 0: # type: ignore[attr-defined]
41
+ if len(self._id.alerts) > 0:
42
42
  # title
43
43
  print(colored("AlERTS:", "yellow", attrs=["bold"]))
44
44
  # messages
45
- print(colored("\n".join(self._id.alerts), "yellow"), end="\n\n") # type: ignore[attr-defined]
45
+ print(colored("\n".join(self._id.alerts), "yellow"), end="\n\n")
46
46
  else:
47
47
  print(end="\n\n")
@@ -0,0 +1 @@
1
+ """A set of Ramifice useful utilities."""
@@ -1,8 +1,6 @@
1
- """Global storage for caching auxiliary variables.
1
+ """Global variables.
2
2
 
3
- The purpose of caching is production optimization.
4
-
5
- The module contains the following elements:
3
+ List of variables:
6
4
 
7
5
  - `DEBUG` - Caching a condition for the verification code.
8
6
  - `MONGO_CLIENT` - Caching a Mongo client.
@@ -11,25 +11,25 @@ from pymongo import AsyncMongoClient
11
11
  from pymongo.asynchronous.collection import AsyncCollection
12
12
  from termcolor import colored
13
13
 
14
- from . import store
14
+ from ..models.model import Model
15
+ from . import globals
15
16
  from .errors import DoesNotMatchRegexError, NoModelsForMigrationError, PanicError
16
17
  from .fixtures import apply_fixture
17
- from .model import Model
18
18
 
19
19
 
20
20
  class Monitor:
21
21
  """Monitoring and updating database state for application."""
22
22
 
23
23
  def __init__(self, database_name: str, mongo_client: AsyncMongoClient): # noqa: D107
24
- store.DEBUG = False
24
+ globals.DEBUG = False
25
25
  #
26
- db_name_regex = store.REGEX["database_name"]
26
+ db_name_regex = globals.REGEX["database_name"]
27
27
  if db_name_regex.match(database_name) is None:
28
28
  raise DoesNotMatchRegexError("^[a-zA-Z][-_a-zA-Z0-9]{0,59}$")
29
29
  #
30
- store.DATABASE_NAME = database_name
31
- store.MONGO_CLIENT = mongo_client
32
- store.MONGO_DATABASE = store.MONGO_CLIENT[store.DATABASE_NAME]
30
+ globals.DATABASE_NAME = database_name
31
+ globals.MONGO_CLIENT = mongo_client
32
+ globals.MONGO_DATABASE = globals.MONGO_CLIENT[globals.DATABASE_NAME]
33
33
  # Get Model list.
34
34
  self.model_list: list[Any] = [
35
35
  cls_model for cls_model in Model.__subclasses__() if cls_model.META["is_migrate_model"]
@@ -45,7 +45,7 @@ class Monitor:
45
45
  """
46
46
  # Get access to super collection.
47
47
  # (Contains Model state and dynamic field data.)
48
- super_collection: AsyncCollection = store.MONGO_DATABASE[store.SUPER_COLLECTION_NAME] # type: ignore[index]
48
+ super_collection: AsyncCollection = globals.MONGO_DATABASE[globals.SUPER_COLLECTION_NAME]
49
49
  # Switch the `is_model_exist` parameter in `False`.
50
50
  async for model_state in super_collection.find():
51
51
  q_filter = {"collection_name": model_state["collection_name"]}
@@ -56,7 +56,7 @@ class Monitor:
56
56
  """Get the state of the current model from a super collection."""
57
57
  # Get access to super collection.
58
58
  # (Contains Model state and dynamic field data.)
59
- super_collection: AsyncCollection = store.MONGO_DATABASE[store.SUPER_COLLECTION_NAME] # type: ignore[index]
59
+ super_collection: AsyncCollection = globals.MONGO_DATABASE[globals.SUPER_COLLECTION_NAME]
60
60
  # Get state of current Model.
61
61
  model_state: dict[str, Any] | None = await super_collection.find_one(
62
62
  {"collection_name": metadata["collection_name"]}
@@ -88,10 +88,10 @@ class Monitor:
88
88
  delete collections associated with those Models.
89
89
  """ # noqa: D205
90
90
  # Get access to database.
91
- database = store.MONGO_DATABASE
91
+ database = globals.MONGO_DATABASE
92
92
  # Get access to super collection.
93
93
  # (Contains Model state and dynamic field data.)
94
- super_collection: AsyncCollection = store.MONGO_DATABASE[store.SUPER_COLLECTION_NAME] # type: ignore[index]
94
+ super_collection: AsyncCollection = globals.MONGO_DATABASE[globals.SUPER_COLLECTION_NAME]
95
95
  # Delete data for non-existent Models.
96
96
  async for model_state in super_collection.find():
97
97
  if model_state["is_model_exist"] is False:
@@ -113,9 +113,9 @@ class Monitor:
113
113
  # Switch the `is_model_exist` parameter in the condition `False`.
114
114
  await self.reset()
115
115
  # Get access to database.
116
- database = store.MONGO_DATABASE
116
+ database = globals.MONGO_DATABASE
117
117
  # Get access to super collection.
118
- super_collection: AsyncCollection = database[store.SUPER_COLLECTION_NAME] # type: ignore[index]
118
+ super_collection: AsyncCollection = database[globals.SUPER_COLLECTION_NAME]
119
119
  #
120
120
  for cls_model in self.model_list:
121
121
  # Get metadata of current Model.
@@ -128,7 +128,7 @@ class Monitor:
128
128
  # Get a list of new fields.
129
129
  new_fields: list[str] = self.new_fields(metadata, model_state)
130
130
  # Get collection for current Model.
131
- model_collection: AsyncCollection = database[model_state["collection_name"]] # type: ignore[index]
131
+ model_collection: AsyncCollection = database[model_state["collection_name"]]
132
132
  # Add new fields with default value or
133
133
  # update existing fields whose field type has changed.
134
134
  async for mongo_doc in model_collection.find():
@@ -194,7 +194,7 @@ class Monitor:
194
194
  )
195
195
  #
196
196
  # Block the verification code.
197
- store.DEBUG = False
197
+ globals.DEBUG = False
198
198
  #
199
199
  # Delete data for non-existent Models from a
200
200
  # super collection and delete collections associated with those Models.
@@ -206,8 +206,8 @@ class Monitor:
206
206
  # Apply fixture to current Model.
207
207
  fixture_name: str | None = cls_model.META["fixture_name"]
208
208
  if fixture_name is not None:
209
- collection: AsyncCollection = store.MONGO_DATABASE[
210
- cls_model.META["collection_name"] # type: ignore[index]
209
+ collection: AsyncCollection = globals.MONGO_DATABASE[
210
+ cls_model.META["collection_name"]
211
211
  ]
212
212
  if await collection.estimated_document_count() == 0:
213
213
  await apply_fixture(
@@ -0,0 +1,6 @@
1
+ """A set of mixins for Ramifice."""
2
+
3
+ from .add_valid import AddValidMixin
4
+ from .hooks import HooksMixin
5
+ from .indexing import IndexMixin
6
+ from .json_converter import JsonMixin
@@ -1,10 +1,10 @@
1
- """Additional validation of fields."""
1
+ """AddValidMixin - Contains an abstract method for additional validation of fields."""
2
2
 
3
3
  from abc import ABCMeta
4
4
 
5
5
 
6
6
  class AddValidMixin(metaclass=ABCMeta):
7
- """Additional validation of fields."""
7
+ """Contains an abstract method for additional validation of fields."""
8
8
 
9
9
  async def add_validation(self) -> dict[str, str]:
10
10
  """Additional validation of fields."""
@@ -1,10 +1,10 @@
1
- """Hook methods."""
1
+ """HooksMixin - Contains abstract methods for creating hooks."""
2
2
 
3
3
  from abc import ABCMeta
4
4
 
5
5
 
6
6
  class HooksMixin(metaclass=ABCMeta):
7
- """Hook methods and additional validation of fields."""
7
+ """A set of abstract methods for creating hooks."""
8
8
 
9
9
  async def pre_create(self) -> None:
10
10
  """Called before a new document is created in the database."""
@@ -0,0 +1,11 @@
1
+ """IndexMixin - Contains abstract method for indexing the model in the database."""
2
+
3
+ from abc import ABCMeta
4
+
5
+
6
+ class IndexMixin(metaclass=ABCMeta):
7
+ """Contains the method for indexing the model in the database."""
8
+
9
+ @classmethod
10
+ async def indexing(cls) -> None:
11
+ """For set up and start indexing."""
@@ -1,14 +1,11 @@
1
- """Complect of mixins."""
1
+ """JsonMixin - Contains the methods for converting Fields to JSON and back."""
2
2
 
3
3
  import json
4
4
  from typing import Any
5
5
 
6
6
 
7
7
  class JsonMixin:
8
- """Complect of methods for converting Fields to JSON and back.
9
-
10
- For fields FileField and ImageField is used FileJsonMixin.
11
- """
8
+ """Contains the methods for converting Fields to JSON and back."""
12
9
 
13
10
  def to_dict(self) -> dict[str, Any]:
14
11
  """Convert object instance to a dictionary."""
@@ -10,7 +10,7 @@ import phonenumbers
10
10
  from bson.objectid import ObjectId
11
11
  from email_validator import EmailNotValidError, validate_email
12
12
 
13
- from .store import REGEX
13
+ from .globals import REGEX
14
14
 
15
15
 
16
16
  def is_password(password: str | None) -> bool:
@@ -1,14 +1,7 @@
1
- """Auxiliary types collection.
2
-
3
- These types are used to transfer information.
4
-
5
- The module contains the following types:
6
-
7
- - `Unit` - Used for data management in dynamic fields.
8
- """
1
+ """Unit - Data management in dynamic fields."""
9
2
 
10
3
  from .errors import PanicError
11
- from .mixins import JsonMixin
4
+ from .mixins.json_converter import JsonMixin
12
5
 
13
6
 
14
7
  class Unit(JsonMixin):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ramifice
3
- Version: 0.3.27
3
+ Version: 0.3.29
4
4
  Summary: ORM-like API MongoDB for Python language.
5
5
  Project-URL: Homepage, https://github.com/kebasyaty/ramifice
6
6
  Project-URL: Documentation, https://kebasyaty.github.io/ramifice/
@@ -134,9 +134,8 @@ import pprint
134
134
  from datetime import datetime
135
135
 
136
136
  from pymongo import AsyncMongoClient
137
- from ramifice import model, translations
137
+ from ramifice import model, translations, migration
138
138
  from ramifice.fields import DateField, EmailField, ImageField, PasswordField, TextField
139
- from ramifice.migration import Monitor
140
139
 
141
140
 
142
141
  @model(service_name="Accounts")
@@ -192,7 +191,7 @@ class User:
192
191
  async def main():
193
192
  client = AsyncMongoClient()
194
193
 
195
- await Monitor(
194
+ await migration.Monitor(
196
195
  database_name="test_db",
197
196
  mongo_client=client,
198
197
  ).migrat()
@@ -474,7 +473,7 @@ async for index in await User.list_indexes():
474
473
  # Units Management.
475
474
  # Management for `choices` parameter in dynamic field types.
476
475
  # Units are stored in a separate collection.
477
- from ramifice.types import Unit
476
+ from ramifice.utils.unit import Unit
478
477
  unit = Unit(
479
478
  field="field_name", # The name of the dynamic field.
480
479
  title="Title", # The name of the choice item.
@@ -522,7 +521,7 @@ await user.update_password( # + verify_password
522
521
  ## General auxiliary methods
523
522
 
524
523
  ```python
525
- from ramifice.tools import (
524
+ from ramifice.utils.tools import (
526
525
  get_file_size,
527
526
  hash_to_obj_id,
528
527
  is_color,