ramifice 0.8.26__py3-none-any.whl → 0.8.28__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.
- ramifice/commons/many.py +4 -8
- ramifice/commons/one.py +1 -3
- ramifice/commons/tools.py +1 -5
- ramifice/commons/unit_manager.py +2 -4
- ramifice/fields/choice_float_field.py +2 -5
- ramifice/fields/choice_float_mult_field.py +3 -8
- ramifice/fields/choice_int_field.py +2 -5
- ramifice/fields/choice_int_mult_field.py +3 -8
- ramifice/fields/choice_text_field.py +3 -8
- ramifice/fields/choice_text_mult_field.py +3 -8
- ramifice/fields/color_field.py +1 -3
- ramifice/fields/date_field.py +1 -3
- ramifice/fields/date_time_field.py +1 -3
- ramifice/fields/email_field.py +2 -4
- ramifice/fields/file_field.py +4 -6
- ramifice/fields/float_field.py +3 -5
- ramifice/fields/general/choice_group.py +1 -3
- ramifice/fields/general/date_group.py +1 -2
- ramifice/fields/general/field.py +2 -4
- ramifice/fields/general/file_group.py +1 -3
- ramifice/fields/general/number_group.py +1 -3
- ramifice/fields/general/text_group.py +1 -3
- ramifice/fields/image_field.py +6 -12
- ramifice/fields/integer_field.py +3 -5
- ramifice/fields/ip_field.py +2 -4
- ramifice/fields/phone_field.py +2 -4
- ramifice/fields/slug_field.py +1 -1
- ramifice/fields/url_field.py +1 -3
- ramifice/models/decorator.py +3 -5
- ramifice/models/model.py +5 -7
- ramifice/paladins/add_valid.py +3 -2
- ramifice/paladins/check.py +6 -8
- ramifice/paladins/groups/date_group.py +1 -3
- ramifice/paladins/groups/file_group.py +1 -3
- ramifice/paladins/groups/img_group.py +1 -3
- ramifice/paladins/groups/num_group.py +2 -6
- ramifice/paladins/groups/slug_group.py +1 -1
- ramifice/paladins/groups/text_group.py +2 -2
- ramifice/paladins/hooks.py +8 -2
- ramifice/paladins/indexing.py +3 -2
- ramifice/paladins/save.py +4 -10
- ramifice/paladins/validation.py +9 -9
- ramifice/utils/constants.py +1 -1
- ramifice/utils/fixtures.py +4 -4
- ramifice/utils/migration.py +10 -21
- ramifice/utils/tools.py +1 -1
- ramifice/utils/translations.py +1 -1
- ramifice/utils/unit.py +3 -6
- {ramifice-0.8.26.dist-info → ramifice-0.8.28.dist-info}/METADATA +2 -1
- ramifice-0.8.28.dist-info/RECORD +83 -0
- ramifice-0.8.26.dist-info/RECORD +0 -83
- {ramifice-0.8.26.dist-info → ramifice-0.8.28.dist-info}/WHEEL +0 -0
- {ramifice-0.8.26.dist-info → ramifice-0.8.28.dist-info}/licenses/LICENSE +0 -0
ramifice/models/model.py
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
__all__ = ("Model",)
|
4
4
|
|
5
|
-
from abc import
|
6
|
-
from typing import Any
|
5
|
+
from abc import abstractmethod
|
6
|
+
from typing import Any, ClassVar
|
7
7
|
|
8
8
|
import orjson
|
9
9
|
from babel.dates import format_date, format_datetime
|
@@ -15,10 +15,10 @@ from ramifice.fields import DateTimeField, IDField
|
|
15
15
|
from ramifice.utils import translations
|
16
16
|
|
17
17
|
|
18
|
-
class Model
|
18
|
+
class Model:
|
19
19
|
"""Converting Python Class into Ramifice Model."""
|
20
20
|
|
21
|
-
META: dict[str, Any] = {}
|
21
|
+
META: ClassVar[dict[str, Any]] = {}
|
22
22
|
|
23
23
|
def __init__(self) -> None: # noqa: D107
|
24
24
|
_ = translations._
|
@@ -81,9 +81,7 @@ class Model(metaclass=ABCMeta):
|
|
81
81
|
if "Dyn" in f_type.field_type:
|
82
82
|
dyn_data = data_dynamic_fields[f_name]
|
83
83
|
if dyn_data is not None:
|
84
|
-
f_type.choices = [
|
85
|
-
[item["value"], item["title"][lang]] for item in dyn_data
|
86
|
-
]
|
84
|
+
f_type.choices = [[item["value"], item["title"][lang]] for item in dyn_data]
|
87
85
|
else:
|
88
86
|
# This is necessary for
|
89
87
|
# `paladins > refrash > RefrashMixin > refrash_from_db`.
|
ramifice/paladins/add_valid.py
CHANGED
@@ -2,14 +2,15 @@
|
|
2
2
|
|
3
3
|
__all__ = ("AddValidMixin",)
|
4
4
|
|
5
|
-
from abc import
|
5
|
+
from abc import abstractmethod
|
6
6
|
|
7
7
|
from xloft import NamedTuple
|
8
8
|
|
9
9
|
|
10
|
-
class AddValidMixin
|
10
|
+
class AddValidMixin:
|
11
11
|
"""Contains an abstract method for additional validation of fields."""
|
12
12
|
|
13
|
+
@abstractmethod
|
13
14
|
async def add_validation(self) -> NamedTuple:
|
14
15
|
"""Additional validation of fields."""
|
15
16
|
return NamedTuple()
|
ramifice/paladins/check.py
CHANGED
@@ -80,9 +80,7 @@ class CheckMixin(
|
|
80
80
|
"field_data": None,
|
81
81
|
"full_model_name": cls_model.META["full_model_name"],
|
82
82
|
"is_migration_process": is_migration_process,
|
83
|
-
"curr_doc": (
|
84
|
-
await collection.find_one({"_id": doc_id}) if is_save and is_update else None
|
85
|
-
),
|
83
|
+
"curr_doc": (await collection.find_one({"_id": doc_id}) if is_save and is_update else None),
|
86
84
|
}
|
87
85
|
|
88
86
|
# Run checking fields.
|
@@ -168,8 +166,8 @@ class CheckMixin(
|
|
168
166
|
if img_data is not None:
|
169
167
|
img_data["is_new_img"] = False
|
170
168
|
#
|
171
|
-
return
|
172
|
-
data
|
173
|
-
is_valid
|
174
|
-
is_update
|
175
|
-
|
169
|
+
return {
|
170
|
+
"data": result_map,
|
171
|
+
"is_valid": not params["is_error_symptom"],
|
172
|
+
"is_update": is_update,
|
173
|
+
}
|
@@ -105,9 +105,7 @@ class DateGroupMixin:
|
|
105
105
|
locale=translations.CURRENT_LOCALE,
|
106
106
|
)
|
107
107
|
)
|
108
|
-
err_msg = translations._(
|
109
|
-
"The date %s must not be less than min=%s !" % value_str, min_date_str
|
110
|
-
)
|
108
|
+
err_msg = translations._("The date %s must not be less than min=%s !" % value_str, min_date_str)
|
111
109
|
accumulate_error(err_msg, params)
|
112
110
|
# Insert result.
|
113
111
|
if params["is_save"]:
|
@@ -66,9 +66,7 @@ class FileGroupMixin:
|
|
66
66
|
return
|
67
67
|
# Accumulate an error if the file size exceeds the maximum value.
|
68
68
|
if value["size"] > field.max_size:
|
69
|
-
err_msg = translations._(
|
70
|
-
"File size exceeds the maximum value %s !" % to_human_size(field.max_size)
|
71
|
-
)
|
69
|
+
err_msg = translations._("File size exceeds the maximum value %s !" % to_human_size(field.max_size))
|
72
70
|
accumulate_error(err_msg, params)
|
73
71
|
return
|
74
72
|
# Insert result.
|
@@ -66,9 +66,7 @@ class ImgGroupMixin:
|
|
66
66
|
return
|
67
67
|
# Accumulate an error if the file size exceeds the maximum value.
|
68
68
|
if value["size"] > field.max_size:
|
69
|
-
err_msg = translations._(
|
70
|
-
"Image size exceeds the maximum value %s !" % to_human_size(field.max_size)
|
71
|
-
)
|
69
|
+
err_msg = translations._("Image size exceeds the maximum value %s !" % to_human_size(field.max_size))
|
72
70
|
accumulate_error(err_msg, params)
|
73
71
|
return
|
74
72
|
# Create thumbnails.
|
@@ -49,16 +49,12 @@ class NumGroupMixin:
|
|
49
49
|
# Validation the `max_number` field attribute.
|
50
50
|
max_number = field.max_number
|
51
51
|
if max_number is not None and value > max_number:
|
52
|
-
err_msg = translations._(
|
53
|
-
"The value %d must not be greater than max=%d !" % value, max_number
|
54
|
-
)
|
52
|
+
err_msg = translations._("The value %d must not be greater than max=%d !" % value, max_number)
|
55
53
|
accumulate_error(err_msg, params)
|
56
54
|
# Validation the `min_number` field attribute.
|
57
55
|
min_number = field.min_number
|
58
56
|
if min_number is not None and value < min_number:
|
59
|
-
err_msg = translations._(
|
60
|
-
"The value %d must not be less than min=%d !" % value, min_number
|
61
|
-
)
|
57
|
+
err_msg = translations._("The value %d must not be less than min=%d !" % value, min_number)
|
62
58
|
accumulate_error(err_msg, params)
|
63
59
|
# Validation the `unique` field attribute.
|
64
60
|
if field.unique and not await check_uniqueness(value, params, field_name):
|
@@ -66,7 +66,7 @@ class SlugGroupMixin:
|
|
66
66
|
err_msg = (
|
67
67
|
f"Model: `{params['full_model_name']}` > "
|
68
68
|
+ f"Field: `{field_name}` > "
|
69
|
-
+
|
69
|
+
+ "Parameter: `slug_sources` => "
|
70
70
|
+ "At least one field should be unique!"
|
71
71
|
)
|
72
72
|
logger.critical(err_msg)
|
@@ -102,11 +102,11 @@ class TextGroupMixin:
|
|
102
102
|
# Insert result.
|
103
103
|
if params["is_save"]:
|
104
104
|
if is_multi_language:
|
105
|
-
mult_lang_text
|
105
|
+
mult_lang_text = (
|
106
106
|
params["curr_doc"][field_name]
|
107
107
|
if params["is_update"]
|
108
108
|
else (
|
109
|
-
|
109
|
+
dict.fromkeys(translations.LANGUAGES)
|
110
110
|
if isinstance(value, str)
|
111
111
|
else {lang: value.get(lang, "- -") for lang in translations.LANGUAGES}
|
112
112
|
)
|
ramifice/paladins/hooks.py
CHANGED
@@ -2,26 +2,32 @@
|
|
2
2
|
|
3
3
|
__all__ = ("HooksMixin",)
|
4
4
|
|
5
|
-
from abc import
|
5
|
+
from abc import abstractmethod
|
6
6
|
|
7
7
|
|
8
|
-
class HooksMixin
|
8
|
+
class HooksMixin:
|
9
9
|
"""A set of abstract methods for creating hooks."""
|
10
10
|
|
11
|
+
@abstractmethod
|
11
12
|
async def pre_create(self) -> None:
|
12
13
|
"""Called before a new document is created in the database."""
|
13
14
|
|
15
|
+
@abstractmethod
|
14
16
|
async def post_create(self) -> None:
|
15
17
|
"""Called after a new document has been created in the database."""
|
16
18
|
|
19
|
+
@abstractmethod
|
17
20
|
async def pre_update(self) -> None:
|
18
21
|
"""Called before updating an existing document in the database."""
|
19
22
|
|
23
|
+
@abstractmethod
|
20
24
|
async def post_update(self) -> None:
|
21
25
|
"""Called after an existing document in the database is updated."""
|
22
26
|
|
27
|
+
@abstractmethod
|
23
28
|
async def pre_delete(self) -> None:
|
24
29
|
"""Called before deleting an existing document in the database."""
|
25
30
|
|
31
|
+
@abstractmethod
|
26
32
|
async def post_delete(self) -> None:
|
27
33
|
"""Called after an existing document in the database has been deleted."""
|
ramifice/paladins/indexing.py
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
__all__ = ("IndexMixin",)
|
4
4
|
|
5
|
-
from abc import
|
5
|
+
from abc import abstractmethod
|
6
6
|
|
7
7
|
|
8
|
-
class IndexMixin
|
8
|
+
class IndexMixin:
|
9
9
|
"""Contains the method for indexing the model in the database."""
|
10
10
|
|
11
11
|
@classmethod
|
12
|
+
@abstractmethod
|
12
13
|
async def indexing(cls) -> None:
|
13
14
|
"""Set up and start indexing."""
|
ramifice/paladins/save.py
CHANGED
@@ -46,7 +46,7 @@ class SaveMixin:
|
|
46
46
|
# Create or update a document in database.
|
47
47
|
if result_check["is_update"]:
|
48
48
|
# Update date and time.
|
49
|
-
checked_data["updated_at"] = datetime.now()
|
49
|
+
checked_data["updated_at"] = datetime.now() # noqa: DTZ005
|
50
50
|
# Run hook.
|
51
51
|
await self.pre_update()
|
52
52
|
# Update doc.
|
@@ -54,9 +54,7 @@ class SaveMixin:
|
|
54
54
|
# Run hook.
|
55
55
|
await self.post_update()
|
56
56
|
# Refresh Model.
|
57
|
-
mongo_doc: dict[str, Any] | None = await collection.find_one(
|
58
|
-
{"_id": checked_data["_id"]}
|
59
|
-
)
|
57
|
+
mongo_doc: dict[str, Any] | None = await collection.find_one({"_id": checked_data["_id"]})
|
60
58
|
if mongo_doc is None:
|
61
59
|
msg = (
|
62
60
|
f"Model: `{self.full_model_name()}` > "
|
@@ -68,7 +66,7 @@ class SaveMixin:
|
|
68
66
|
refresh_from_mongo_doc(self, mongo_doc)
|
69
67
|
else:
|
70
68
|
# Add date and time.
|
71
|
-
today = datetime.now()
|
69
|
+
today = datetime.now() # noqa: DTZ005
|
72
70
|
checked_data["created_at"] = today
|
73
71
|
checked_data["updated_at"] = today
|
74
72
|
# Run hook.
|
@@ -80,11 +78,7 @@ class SaveMixin:
|
|
80
78
|
# Refresh Model.
|
81
79
|
mongo_doc = await collection.find_one({"_id": checked_data["_id"]})
|
82
80
|
if mongo_doc is None:
|
83
|
-
msg = (
|
84
|
-
f"Model: `{self.full_model_name()}` > "
|
85
|
-
+ "Method: `save` => "
|
86
|
-
+ "The document was not created."
|
87
|
-
)
|
81
|
+
msg = f"Model: `{self.full_model_name()}` > " + "Method: `save` => " + "The document was not created."
|
88
82
|
logger.critical(msg)
|
89
83
|
raise PanicError(msg)
|
90
84
|
refresh_from_mongo_doc(self, mongo_doc)
|
ramifice/paladins/validation.py
CHANGED
@@ -31,19 +31,19 @@ class ValidationMixin:
|
|
31
31
|
if len(field_data.errors) > 0:
|
32
32
|
# title
|
33
33
|
if not is_err:
|
34
|
-
print(colored("\nERRORS:", "red", attrs=["bold"]))
|
35
|
-
print(colored("Model: ", "blue", attrs=["bold"]), end="")
|
36
|
-
print(colored(f"`{self.full_model_name()}`", "blue"))
|
34
|
+
print(colored("\nERRORS:", "red", attrs=["bold"])) # noqa: T201
|
35
|
+
print(colored("Model: ", "blue", attrs=["bold"]), end="") # noqa: T201
|
36
|
+
print(colored(f"`{self.full_model_name()}`", "blue")) # noqa: T201
|
37
37
|
is_err = True
|
38
38
|
# field name
|
39
|
-
print(colored("Field: ", "green", attrs=["bold"]), end="")
|
40
|
-
print(colored(f"`{field_name}`:", "green"))
|
39
|
+
print(colored("Field: ", "green", attrs=["bold"]), end="") # noqa: T201
|
40
|
+
print(colored(f"`{field_name}`:", "green")) # noqa: T201
|
41
41
|
# error messages
|
42
|
-
print(colored("\n".join(field_data.errors), "red"))
|
42
|
+
print(colored("\n".join(field_data.errors), "red")) # noqa: T201
|
43
43
|
if len(self._id.alerts) > 0:
|
44
44
|
# title
|
45
|
-
print(colored("AlERTS:", "yellow", attrs=["bold"]))
|
45
|
+
print(colored("AlERTS:", "yellow", attrs=["bold"])) # noqa: T201
|
46
46
|
# messages
|
47
|
-
print(colored("\n".join(self._id.alerts), "yellow"), end="\n\n")
|
47
|
+
print(colored("\n".join(self._id.alerts), "yellow"), end="\n\n") # noqa: T201
|
48
48
|
else:
|
49
|
-
print(end="\n\n")
|
49
|
+
print(end="\n\n") # noqa: T201
|
ramifice/utils/constants.py
CHANGED
@@ -64,7 +64,7 @@ REGEX: dict[str, re.Pattern] = {
|
|
64
64
|
"model_name": re.compile(r"^[A-Z][a-zA-Z0-9]{0,24}$"),
|
65
65
|
"color_code": re.compile(
|
66
66
|
r"^(?:#|0x)(?:[a-f0-9]{3}|[a-f0-9]{6}|[a-f0-9]{8})\b|(?:rgb|hsl)a?\([^\)]*\)$",
|
67
|
-
re.I,
|
67
|
+
re.I, # noqa: FURB167
|
68
68
|
),
|
69
69
|
"password": re.compile(r'^[-._!"`\'#%&,:;<>=@{}~\$\(\)\*\+\/\\\?\[\]\^\|a-zA-Z0-9]{8,256}$'),
|
70
70
|
}
|
ramifice/utils/fixtures.py
CHANGED
@@ -31,7 +31,7 @@ async def apply_fixture(
|
|
31
31
|
fixture_path: str = f"config/fixtures/{fixture_name}.yml"
|
32
32
|
data_yaml: dict[str, Any] | list[dict[str, Any]] | None = None
|
33
33
|
|
34
|
-
with open(fixture_path
|
34
|
+
with open(fixture_path) as file:
|
35
35
|
data_yaml = yaml.safe_load(file)
|
36
36
|
|
37
37
|
if not bool(data_yaml):
|
@@ -71,8 +71,8 @@ async def apply_fixture(
|
|
71
71
|
# If the check fails.
|
72
72
|
if not result_check["is_valid"]:
|
73
73
|
await collection.database.drop_collection(collection.name)
|
74
|
-
print(colored("\nFIXTURE:", "red", attrs=["bold"]))
|
75
|
-
print(colored(fixture_path, "blue", attrs=["bold"]))
|
74
|
+
print(colored("\nFIXTURE:", "red", attrs=["bold"])) # noqa: T201
|
75
|
+
print(colored(fixture_path, "blue", attrs=["bold"])) # noqa: T201
|
76
76
|
inst_model.print_err()
|
77
77
|
msg = f"Fixture `{fixture_name}` failed."
|
78
78
|
logger.critical(msg)
|
@@ -80,7 +80,7 @@ async def apply_fixture(
|
|
80
80
|
# Get data for document.
|
81
81
|
checked_data: dict[str, Any] = result_check["data"]
|
82
82
|
# Add date and time.
|
83
|
-
today = datetime.now()
|
83
|
+
today = datetime.now() # noqa: DTZ005
|
84
84
|
checked_data["created_at"] = today
|
85
85
|
checked_data["updated_at"] = today
|
86
86
|
# Run hook.
|
ramifice/utils/migration.py
CHANGED
@@ -52,9 +52,7 @@ class Migration:
|
|
52
52
|
"""
|
53
53
|
# Get access to super collection.
|
54
54
|
# (Contains Model state and dynamic field data.)
|
55
|
-
super_collection: AsyncCollection = constants.MONGO_DATABASE[
|
56
|
-
constants.SUPER_COLLECTION_NAME
|
57
|
-
]
|
55
|
+
super_collection: AsyncCollection = constants.MONGO_DATABASE[constants.SUPER_COLLECTION_NAME]
|
58
56
|
# Switch the `is_model_exist` parameter in `False`.
|
59
57
|
async for model_state in super_collection.find():
|
60
58
|
q_filter = {"collection_name": model_state["collection_name"]}
|
@@ -65,12 +63,10 @@ class Migration:
|
|
65
63
|
"""Get the state of the current model from a super collection."""
|
66
64
|
# Get access to super collection.
|
67
65
|
# (Contains Model state and dynamic field data.)
|
68
|
-
super_collection: AsyncCollection = constants.MONGO_DATABASE[
|
69
|
-
constants.SUPER_COLLECTION_NAME
|
70
|
-
]
|
66
|
+
super_collection: AsyncCollection = constants.MONGO_DATABASE[constants.SUPER_COLLECTION_NAME]
|
71
67
|
# Get state of current Model.
|
72
68
|
model_state: dict[str, Any] | None = await super_collection.find_one(
|
73
|
-
{"collection_name": metadata["collection_name"]}
|
69
|
+
{"collection_name": metadata["collection_name"]},
|
74
70
|
)
|
75
71
|
if model_state is not None:
|
76
72
|
model_state["is_model_exist"] = True
|
@@ -102,9 +98,7 @@ class Migration:
|
|
102
98
|
database = constants.MONGO_DATABASE
|
103
99
|
# Get access to super collection.
|
104
100
|
# (Contains Model state and dynamic field data.)
|
105
|
-
super_collection: AsyncCollection = constants.MONGO_DATABASE[
|
106
|
-
constants.SUPER_COLLECTION_NAME
|
107
|
-
]
|
101
|
+
super_collection: AsyncCollection = constants.MONGO_DATABASE[constants.SUPER_COLLECTION_NAME]
|
108
102
|
# Delete data for non-existent Models.
|
109
103
|
async for model_state in super_collection.find():
|
110
104
|
if model_state["is_model_exist"] is False:
|
@@ -172,7 +166,7 @@ class Migration:
|
|
172
166
|
is_migration_process=True,
|
173
167
|
)
|
174
168
|
if not result_check["is_valid"]:
|
175
|
-
print(colored("\n!!!>>MIGRATION<<!!!", "red", attrs=["bold"]))
|
169
|
+
print(colored("\n!!!>>MIGRATION<<!!!", "red", attrs=["bold"])) # noqa: T201
|
176
170
|
inst_model.print_err()
|
177
171
|
msg: str = "Migration failed."
|
178
172
|
logger.critical(msg)
|
@@ -183,12 +177,11 @@ class Migration:
|
|
183
177
|
for field_name, field_type in metadata["field_name_and_type"].items():
|
184
178
|
if (
|
185
179
|
field_type == "PasswordField"
|
186
|
-
and model_state["field_name_and_type"].get(field_name)
|
187
|
-
== "PasswordField"
|
180
|
+
and model_state["field_name_and_type"].get(field_name) == "PasswordField"
|
188
181
|
):
|
189
182
|
checked_data[field_name] = mongo_doc[field_name]
|
190
183
|
# Update date and time.
|
191
|
-
checked_data["updated_at"] = datetime.now()
|
184
|
+
checked_data["updated_at"] = datetime.now() # noqa: DTZ005
|
192
185
|
# Update the document in the database.
|
193
186
|
await model_collection.replace_one(
|
194
187
|
filter={"_id": checked_data["_id"]},
|
@@ -197,12 +190,10 @@ class Migration:
|
|
197
190
|
#
|
198
191
|
# Refresh the dynamic fields data for the current model.
|
199
192
|
for field_name, field_data in metadata["data_dynamic_fields"].items():
|
200
|
-
if model_state["data_dynamic_fields"].get(field_name, False) == False:
|
193
|
+
if model_state["data_dynamic_fields"].get(field_name, False) == False: # noqa: E712
|
201
194
|
model_state["data_dynamic_fields"][field_name] = field_data
|
202
195
|
else:
|
203
|
-
metadata["data_dynamic_fields"][field_name] = model_state[
|
204
|
-
"data_dynamic_fields"
|
205
|
-
][field_name]
|
196
|
+
metadata["data_dynamic_fields"][field_name] = model_state["data_dynamic_fields"][field_name]
|
206
197
|
# Refresh state of current Model.
|
207
198
|
model_state["data_dynamic_fields"] = metadata["data_dynamic_fields"]
|
208
199
|
model_state["field_name_and_type"] = metadata["field_name_and_type"]
|
@@ -224,9 +215,7 @@ class Migration:
|
|
224
215
|
# Apply fixture to current Model.
|
225
216
|
fixture_name: str | None = cls_model.META["fixture_name"]
|
226
217
|
if fixture_name is not None:
|
227
|
-
collection: AsyncCollection = constants.MONGO_DATABASE[
|
228
|
-
cls_model.META["collection_name"]
|
229
|
-
]
|
218
|
+
collection: AsyncCollection = constants.MONGO_DATABASE[cls_model.META["collection_name"]]
|
230
219
|
if await collection.estimated_document_count() == 0:
|
231
220
|
await apply_fixture(
|
232
221
|
fixture_name=fixture_name,
|
ramifice/utils/tools.py
CHANGED
@@ -37,7 +37,7 @@ def is_password(password: str | None) -> bool:
|
|
37
37
|
|
38
38
|
def to_human_size(size: int) -> str:
|
39
39
|
"""Convert number of bytes to readable format."""
|
40
|
-
idx = int(math.floor(math.log(size) / math.log(1024)))
|
40
|
+
idx = int(math.floor(math.log(size) / math.log(1024))) # noqa: RUF046
|
41
41
|
size = size if size < 1024 else abs(round(size / pow(1024, idx), 2))
|
42
42
|
order = ["bytes", "KB", "MB", "GB", "TB"][idx]
|
43
43
|
return f"{size} {order}"
|
ramifice/utils/translations.py
CHANGED
@@ -57,7 +57,7 @@ def add_languages(
|
|
57
57
|
) -> None:
|
58
58
|
"""Add languages."""
|
59
59
|
global DEFAULT_LOCALE, LANGUAGES
|
60
|
-
if not
|
60
|
+
if default_locale not in languages:
|
61
61
|
msg = "DEFAULT_LOCALE is not included in the LANGUAGES!"
|
62
62
|
logger.critical(msg)
|
63
63
|
raise PanicError(msg)
|
ramifice/utils/unit.py
CHANGED
@@ -32,16 +32,13 @@ class Unit(JsonMixin):
|
|
32
32
|
msg = "Class: `Unit` > Field: `field` => Not а `str` type!"
|
33
33
|
raise PanicError(msg)
|
34
34
|
if not isinstance(title, dict):
|
35
|
-
msg =
|
36
|
-
"Class: `Unit` > Field: `title` => Not а `str` type! "
|
37
|
-
+ 'Example: {"en": "Title", "ru": "Заголовок"}'
|
38
|
-
)
|
35
|
+
msg = "Class: `Unit` > Field: `title` => Not а `str` type! " + 'Example: {"en": "Title", "ru": "Заголовок"}'
|
39
36
|
raise PanicError(msg)
|
40
37
|
if not isinstance(value, (float, int, str)):
|
41
|
-
msg = "Class: `Unit` > Field: `value` => Not
|
38
|
+
msg = "Class: `Unit` > Field: `value` => Not a `float | int | str` type!"
|
42
39
|
raise PanicError(msg)
|
43
40
|
if not isinstance(is_delete, bool):
|
44
|
-
msg = "Class: `Unit` > Field: `is_delete` => Not
|
41
|
+
msg = "Class: `Unit` > Field: `is_delete` => Not a `bool` type!"
|
45
42
|
raise PanicError(msg)
|
46
43
|
|
47
44
|
JsonMixin.__init__(self)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ramifice
|
3
|
-
Version: 0.8.
|
3
|
+
Version: 0.8.28
|
4
4
|
Summary: ORM-pseudo-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/
|
@@ -60,6 +60,7 @@ Description-Content-Type: text/markdown
|
|
60
60
|
<a href="https://github.com/kebasyaty/ramifice/issues"><img src="https://img.shields.io/github/issues/kebasyaty/ramifice.svg" alt="GitHub issues"></a>
|
61
61
|
<a href="https://pepy.tech/projects/ramifice"><img src="https://static.pepy.tech/badge/ramifice" alt="PyPI Downloads"></a>
|
62
62
|
<a href="https://github.com/kebasyaty/ramifice/blob/main/LICENSE" alt="GitHub license"><img src="https://img.shields.io/github/license/kebasyaty/ramifice" alt="GitHub license"></a>
|
63
|
+
<a href="https://mypy-lang.org/" alt="Types: Mypy"><img src="https://img.shields.io/badge/types-Mypy-202235.svg?color=0c7ebf" alt="Types: Mypy"></a>
|
63
64
|
<a href="https://docs.astral.sh/ruff/" alt="Code style: Ruff"><img src="https://img.shields.io/badge/code%20style-Ruff-FDD835.svg" alt="Code style: Ruff"></a>
|
64
65
|
<a href="https://github.com/kebasyaty/ramifice" alt="PyPI implementation"><img src="https://img.shields.io/pypi/implementation/ramifice" alt="PyPI implementation"></a>
|
65
66
|
<a href="https://github.com/kebasyaty/ramifice" alt="GitHub repository"><img src="https://img.shields.io/badge/--ecebeb?logo=github&logoColor=000000" alt="GitHub repository"></a>
|
@@ -0,0 +1,83 @@
|
|
1
|
+
ramifice/__init__.py,sha256=rTkA9TUWsis-q056oslAcalr3rwNChMUcpQX5Q43Pzs,1520
|
2
|
+
ramifice/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
ramifice/commons/__init__.py,sha256=HwOckqlNkt4OzFbYqnLw9x0VXLbwO_mJaJ9MLYgSvtI,545
|
4
|
+
ramifice/commons/general.py,sha256=ZryiRH-qf_cH9HCul7EP11UU-k4YO_rp_kku2FWAwj4,5433
|
5
|
+
ramifice/commons/indexes.py,sha256=dBPVYeJGbEyENLEzGjQmQ2XYOr3qqzjonj6zyH4rl54,3696
|
6
|
+
ramifice/commons/many.py,sha256=sirqV6oEPMaBlYc8UvReLUQtwvbhr5d2V1kYQ-xpK8o,9378
|
7
|
+
ramifice/commons/one.py,sha256=Ppq7vZpmvcfnpurgH3rXSix1KUUwDHYeJQqKkqedE14,6955
|
8
|
+
ramifice/commons/tools.py,sha256=o0o-0W7VDAMPiEOWF9Du7W7py94fCLFx8KJc7LM6HP4,2423
|
9
|
+
ramifice/commons/unit_manager.py,sha256=OCDh8Ms-zCYgHEwwyXp83qYDmRBSgkkAnZiJHSuEGm8,4945
|
10
|
+
ramifice/fields/__init__.py,sha256=hjqCZG_kKsHdHtSd05vHn9SiFpk-YSvKEsVFaXim5Sw,2360
|
11
|
+
ramifice/fields/bool_field.py,sha256=d3sKQWMAfEycgtBIhIIov2XVoqLbN8th8i3H7YLrNdg,2769
|
12
|
+
ramifice/fields/choice_float_dyn_field.py,sha256=e-i7CtmDVqWzRJJ5Pq4PmI69riHDPx9NX51h2qFsjEE,3912
|
13
|
+
ramifice/fields/choice_float_field.py,sha256=2XyMkRa6uxc9q5cxB89upoCqaUaUqZ39BLLYcE9Hmc8,4811
|
14
|
+
ramifice/fields/choice_float_mult_dyn_field.py,sha256=45nr0FoY9roO2pJ0FfzBIMu6ih5cl7_3NyKVwtUAHrA,3979
|
15
|
+
ramifice/fields/choice_float_mult_field.py,sha256=lvcSWEwYFOuxpPect3kRh6QnDGfzB2Y0JkODmhfurQo,5121
|
16
|
+
ramifice/fields/choice_int_dyn_field.py,sha256=qUAZivbZSmGYhoPo-vu9P0psEjj-ZtUWjmjYv9GY6yc,3904
|
17
|
+
ramifice/fields/choice_int_field.py,sha256=e0E2P1s21918KeYaKQrMsYb64QXztdcBiHzH7J6cLEw,4797
|
18
|
+
ramifice/fields/choice_int_mult_dyn_field.py,sha256=QajFttWuw5Z_S_ik48zev83tVIiPOgHjzPFnxmkO_e4,3973
|
19
|
+
ramifice/fields/choice_int_mult_field.py,sha256=Aet8kmD8tmHk0IF13P4LTTpAQwKX8f7YwhkJSMVf3TI,5113
|
20
|
+
ramifice/fields/choice_text_dyn_field.py,sha256=H_BGtTuNNGJdXDZmGGPpi-7c0GtDGJwkyNFbKScLs28,3895
|
21
|
+
ramifice/fields/choice_text_field.py,sha256=Kkm_CZCNXlMH9_brp0bR93ByPUU0R8MKsleVvdrc6nc,4957
|
22
|
+
ramifice/fields/choice_text_mult_dyn_field.py,sha256=OrPZ-y2ihcJeLkTWJrcPgMijedq_5czbPEmISg1HdWU,3964
|
23
|
+
ramifice/fields/choice_text_mult_field.py,sha256=H3qp6B4Rw81FEycmBJ9wiwhTQc_hlE5TmRZJNj_Z-yc,5104
|
24
|
+
ramifice/fields/color_field.py,sha256=Q1ZezPW6Jl-9olKCx47pMdHTCauBY_lwoudxIhZpAgw,4449
|
25
|
+
ramifice/fields/date_field.py,sha256=svJjb6KgsmpW4RO8y3Opkh2uFwwSVfzyeb7nd5tNXLs,6267
|
26
|
+
ramifice/fields/date_time_field.py,sha256=jINGK1VrRt1boXmjJb6_WU7G7h_qnbUSolKNFOtVXFg,6324
|
27
|
+
ramifice/fields/email_field.py,sha256=joReU6YV-ViewMiRVvHozVjIhXuPMwxA-cmqwR5kkHY,4389
|
28
|
+
ramifice/fields/file_field.py,sha256=dAsOYXPjMNwC_t8jCyoNEwlRAsGEd9V_tiuix0qTukU,9476
|
29
|
+
ramifice/fields/float_field.py,sha256=0OjoR9nwDs-Isv_lJoAT_jtdKmnd7-MqltCUiCViups,5796
|
30
|
+
ramifice/fields/id_field.py,sha256=36VroZIgCH6uKuYjjWTXIycZ06ZGy4reLX6FhMUphCI,4757
|
31
|
+
ramifice/fields/image_field.py,sha256=dZOB8ctt-7KeB-ePDwgeIgpNP6tLfnxWBU_E5_6dApc,12855
|
32
|
+
ramifice/fields/integer_field.py,sha256=WKzmy-v2uLmIYlrTwcmuoUGfjWQhGD9wHukfQ0fUipk,5770
|
33
|
+
ramifice/fields/ip_field.py,sha256=GjDo1g5PEolqb8_AcDqgE_BnTITqew2rZcqmEn3S5WA,4293
|
34
|
+
ramifice/fields/password_field.py,sha256=lKELnyIjlAIJWeCR_3BCa0ZL5R0L73cf9zimigIgN3g,3902
|
35
|
+
ramifice/fields/phone_field.py,sha256=neaa9sCLtQR5zr0eiF6CkoSHIif2h2j01DY_VDgpNzk,4580
|
36
|
+
ramifice/fields/slug_field.py,sha256=wJtyf5LWP5pxw6G91_sYSs02QY7kvLYyB1_99_6gz5o,3552
|
37
|
+
ramifice/fields/text_field.py,sha256=fBVxBzHwj7R0TiSXnidqA5XHJdEz16WShT6TGjC-B6g,5299
|
38
|
+
ramifice/fields/url_field.py,sha256=MbaXUVbmYIaYHN4sldaSIsojqxUjT0zHDpuzGC1pHrY,4292
|
39
|
+
ramifice/fields/general/__init__.py,sha256=JzgIDseNQLB_IDwY9-JSiT_bONxvhJmbKl5PhQzTnpE,40
|
40
|
+
ramifice/fields/general/choice_group.py,sha256=fdxfUEKavnW3SahtmyXNDsIJ1O67wCqZb0g-qnNc9cc,896
|
41
|
+
ramifice/fields/general/date_group.py,sha256=0Y4njV6AboQKCpSpjNRWiO8iJF4EdnVWOvmRz_M_7MY,1185
|
42
|
+
ramifice/fields/general/field.py,sha256=8P_k66rSGpY9qfiyRvRcH4VcqmzCy6fphr_BLrf-2N0,1360
|
43
|
+
ramifice/fields/general/file_group.py,sha256=HjCww3B6eS9gUmr6AGZTXhHVhS_VBvn0XpbrViWA8a8,986
|
44
|
+
ramifice/fields/general/number_group.py,sha256=QvJnnpvWvU5J-99mWk7h-00hW7busClv1eSR_DPll4A,753
|
45
|
+
ramifice/fields/general/text_group.py,sha256=y5j_7I-TzOpr6vJpbEFHN1JRc6s0wa6BVSqnHMMmX-4,1077
|
46
|
+
ramifice/models/__init__.py,sha256=I4p5Y_oHG9ZLZ3vR44PpCGGvB-C2W7fSQPb5qJsm-VQ,178
|
47
|
+
ramifice/models/decorator.py,sha256=bFUN62UXLKSVteyd8GRZGEK-u-IgJQq1U_HrCrws5ZU,6350
|
48
|
+
ramifice/models/model.py,sha256=kexnWtfmQaiGZU2qKeAhuHLxmuIFFe-xHwCULzLs9bc,7639
|
49
|
+
ramifice/paladins/__init__.py,sha256=bFr12UzadCCpuIkGSd6reeIeQ5td8W7LfckduP84WXc,1517
|
50
|
+
ramifice/paladins/add_valid.py,sha256=c-vIkbbIBC94T4czxkQC40uwNEe6w8wQgNVgu4cjeoY,439
|
51
|
+
ramifice/paladins/check.py,sha256=7zRYKzaa2tXJq8OVNe52SEFt9YFkrElsf4-mvhVD_B0,6908
|
52
|
+
ramifice/paladins/delete.py,sha256=k3N2qlaHZLWtFUTqWvtkYaqW9h3uK7ecpLjKr5gfoGE,3690
|
53
|
+
ramifice/paladins/hooks.py,sha256=jTOcz5eb3WUpIy21h-CcnsISDDsTgDCWjitszcFxZFE,1057
|
54
|
+
ramifice/paladins/indexing.py,sha256=ep6iSUhnH70eaNASr0Kx3yeuRE_i9BEdVUUiJBo4hZE,363
|
55
|
+
ramifice/paladins/password.py,sha256=7lZmsl-bBely5zlVz0aCYlC5yf8nHp1YswoFF4CZWBI,3297
|
56
|
+
ramifice/paladins/refrash.py,sha256=oS-N1QVwQGwt5lSxS01bpM6ETGuMLV_RFt1u5v2uEds,1221
|
57
|
+
ramifice/paladins/save.py,sha256=ahuPKo6qh9MHPXs_QNo9RbeBvN74uWtuI27k84gx5f4,3631
|
58
|
+
ramifice/paladins/tools.py,sha256=8rkWPGrVMJiYN97EZuX52nVFVfB6qa08avYT4v8ohLA,2918
|
59
|
+
ramifice/paladins/validation.py,sha256=vJ55g4al-V_aGxFSrnXDwAxjJXWv00Z8ZGexFipRD1c,1890
|
60
|
+
ramifice/paladins/groups/__init__.py,sha256=GdIBJaMKz7L8pBKMAA__a4m-p0g0_RlzCcvDLDMMiec,958
|
61
|
+
ramifice/paladins/groups/bool_group.py,sha256=X8P4YDh02gNzxTo9rgeCnmnV88jApUPqPLYIkpf5vGg,841
|
62
|
+
ramifice/paladins/groups/choice_group.py,sha256=NkD2sKqBkdUMHY36pFdvL4uQ-81LXByRHF_lhCEAI6Y,1848
|
63
|
+
ramifice/paladins/groups/date_group.py,sha256=3i6U2mwFMxW8s5rRi7RtSr7my6a5Cdy5MRWe601hjGA,3780
|
64
|
+
ramifice/paladins/groups/file_group.py,sha256=vDeW5JCqKHWa43LILcVWJSU1TG-CrwKXQZhchWsZgM8,2975
|
65
|
+
ramifice/paladins/groups/id_group.py,sha256=9iurBTOuhG1_8Wmxc5piTMcUNxAW3H0ZavA1sW7uopY,1321
|
66
|
+
ramifice/paladins/groups/img_group.py,sha256=xSrDYqviuMt7mxOZiO0jKll1WnVlWRaSynk7ZvdEJ4c,6131
|
67
|
+
ramifice/paladins/groups/num_group.py,sha256=oiBqm9lFsyHBKZgxfWvcQUpePPIT_0TBGPVrt0ae57s,2285
|
68
|
+
ramifice/paladins/groups/pass_group.py,sha256=54kvAyoUCEjujTw0Dh6oUrtv3RU80sWEem_b-3Ytv0k,1920
|
69
|
+
ramifice/paladins/groups/slug_group.py,sha256=sf-9CebDLoCDsaxyPVJKMhi6D_tWFeg3ET8Qk5E8pU8,2505
|
70
|
+
ramifice/paladins/groups/text_group.py,sha256=TWvUxFctwDtXSJQL_E4TvHX1Yh-cDx5MJLGLAJyC6Xc,4478
|
71
|
+
ramifice/utils/__init__.py,sha256=lAD90nw2VfGSuf0SLjOkeFScBPmc48XFvecueAfq73w,468
|
72
|
+
ramifice/utils/constants.py,sha256=zDVG2D8u0UMNl1Ik90PhZCdxjmK81uwqxosorersbXE,2630
|
73
|
+
ramifice/utils/errors.py,sha256=eEV7-aVR0U19vKqTd9JRHFJXcOv6N1HtXSzqeQpdciE,2796
|
74
|
+
ramifice/utils/fixtures.py,sha256=0hdJGu895zDvVg5HUmRVUqDLZbvM-7BlhwTF6vhRqJI,3374
|
75
|
+
ramifice/utils/migration.py,sha256=rA6RMIB7xrLNGUJHPuvxA5O0B3NkmG155et82kOtu7g,11316
|
76
|
+
ramifice/utils/mixins.py,sha256=XSkxJllqsMxN7xcP_9kn3-GRS4a1l_QQpFOlD3e-tIM,1123
|
77
|
+
ramifice/utils/tools.py,sha256=EKNJAV9Ch17IrmghLcu7-I69gDNkDSqPepG9GKU7WkA,3163
|
78
|
+
ramifice/utils/translations.py,sha256=EWITTDd4uXukRubOchqGwNjmZWt5HxoxRgq_kKeGsR8,4646
|
79
|
+
ramifice/utils/unit.py,sha256=fxeWGWh5GkI8E9lxsf80HOh-NihSrqEmIQAQlUKMIaE,2497
|
80
|
+
ramifice-0.8.28.dist-info/METADATA,sha256=X_XGDUwRgnmu1K2qcI9zlEzKoKQSWbbquGD1DMsT28Q,21236
|
81
|
+
ramifice-0.8.28.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
82
|
+
ramifice-0.8.28.dist-info/licenses/LICENSE,sha256=LrEL0aTZx90HDwFUQCJutORiDjJL9AnuVvCtspXIqt4,1095
|
83
|
+
ramifice-0.8.28.dist-info/RECORD,,
|