ramifice 0.4.0__py3-none-any.whl → 0.4.2__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/models/model.py CHANGED
@@ -45,6 +45,11 @@ class Model(metaclass=ABCMeta):
45
45
  self.fields()
46
46
  self.inject()
47
47
 
48
+ @property
49
+ def id(self) -> IDField:
50
+ """Getter for the field `_id`."""
51
+ return self._id
52
+
48
53
  @abstractmethod
49
54
  def fields(self) -> None:
50
55
  """For adding fields."""
@@ -84,7 +84,9 @@ class CheckMixin(
84
84
  "field_data": None,
85
85
  "full_model_name": cls_model.META["full_model_name"],
86
86
  "is_migrate_model": is_migrate_model,
87
- "mongo_doc": await collection.find_one({"_id": doc_id}) if is_save else None,
87
+ "curr_doc": (
88
+ await collection.find_one({"_id": doc_id}) if is_save and is_update else None
89
+ ),
88
90
  }
89
91
 
90
92
  # Run checking fields.
@@ -129,9 +131,7 @@ class CheckMixin(
129
131
  if not is_update:
130
132
  self._id.value = None
131
133
  # Delete orphaned files.
132
- curr_doc: dict[str, Any] | None = (
133
- await collection.find_one({"_id": doc_id}) if is_update else None
134
- )
134
+ curr_doc: dict[str, Any] | None = params["curr_doc"]
135
135
  for field_name, field_data in self.__dict__.items():
136
136
  if callable(field_data) or field_data.ignored:
137
137
  continue
@@ -20,6 +20,7 @@ class NumGroupMixin:
20
20
  async def num_group(self, params: dict[str, Any]) -> None:
21
21
  """Checking number fields."""
22
22
  field = params["field_data"]
23
+ field_name = field.name
23
24
  # Get current value.
24
25
  value = field.value
25
26
  if value is None:
@@ -37,7 +38,7 @@ class NumGroupMixin:
37
38
  err_msg = translations._("Required field !")
38
39
  accumulate_error(err_msg, params)
39
40
  if params["is_save"]:
40
- params["result_map"][field.name] = None
41
+ params["result_map"][field_name] = None
41
42
  return
42
43
  # Validation the `max_number` field attribute.
43
44
  max_number = field.max_number
@@ -54,9 +55,9 @@ class NumGroupMixin:
54
55
  )
55
56
  accumulate_error(err_msg, params)
56
57
  # Validation the `unique` field attribute.
57
- if field.unique and not await check_uniqueness(value, params):
58
+ if field.unique and not await check_uniqueness(value, params, field_name):
58
59
  err_msg = translations._("Is not unique !")
59
60
  accumulate_error(err_msg, params)
60
61
  # Insert result.
61
62
  if params["is_save"]:
62
- params["result_map"][field.name] = value
63
+ params["result_map"][field_name] = value
@@ -25,23 +25,24 @@ class SlugGroupMixin:
25
25
  return
26
26
  #
27
27
  field = params["field_data"]
28
+ field_name = field.name
28
29
  raw_str_list: list[str] = []
29
30
  slug_sources = field.slug_sources
30
31
  #
31
- for field_name, field_data in self.__dict__.items():
32
+ for _field_name, field_data in self.__dict__.items():
32
33
  if callable(field_data):
33
34
  continue
34
- if field_name in slug_sources:
35
+ if _field_name in slug_sources:
35
36
  value = field_data.value
36
37
  if value is None:
37
38
  value = field_data.__dict__.get("default")
38
39
  if value is not None:
39
- raw_str_list.append(value if field_name != "_id" else str(value))
40
+ raw_str_list.append(value if _field_name != "_id" else str(value))
40
41
  else:
41
42
  err_msg = (
42
43
  f"Model: `{params['full_model_name']}` > "
43
- + f"Field: `{field.name}` => "
44
- + f"{field_name} - "
44
+ + f"Field: `{field_name}` => "
45
+ + f"{_field_name} - "
45
46
  + "This field is specified in slug_sources. "
46
47
  + "This field should be mandatory or assign a default value."
47
48
  )
@@ -51,13 +52,17 @@ class SlugGroupMixin:
51
52
  # Convert to slug.
52
53
  value = slugify("-".join(raw_str_list))
53
54
  # Validation of uniqueness of the value.
54
- if not await check_uniqueness(value, params):
55
+ if not await check_uniqueness(
56
+ value,
57
+ params,
58
+ field_name,
59
+ ):
55
60
  err_msg = (
56
61
  f"Model: `{params['full_model_name']}` > "
57
- + f"Field: `{field.name}` > "
62
+ + f"Field: `{field_name}` > "
58
63
  + f"Parameter: `slug_sources` => "
59
64
  + "At least one field should be unique!"
60
65
  )
61
66
  raise PanicError(err_msg)
62
67
  # Add value to map.
63
- params["result_map"][field.name] = value
68
+ params["result_map"][field_name] = value
@@ -25,6 +25,7 @@ class TextGroupMixin:
25
25
  async def text_group(self, params: dict[str, Any]) -> None:
26
26
  """Checking text fields."""
27
27
  field = params["field_data"]
28
+ field_name = field.name
28
29
  field_type: str = field.field_type
29
30
  is_text_field: bool = "TextField" == field_type
30
31
  # Get current value.
@@ -32,7 +33,7 @@ class TextGroupMixin:
32
33
 
33
34
  if is_text_field:
34
35
  if not isinstance(value, (str, dict, type(None))):
35
- panic_type_error("str | None", params)
36
+ panic_type_error("str | dict | None", params)
36
37
  else:
37
38
  if not isinstance(value, (str, type(None))):
38
39
  panic_type_error("str | None", params)
@@ -42,7 +43,7 @@ class TextGroupMixin:
42
43
  err_msg = translations._("Required field !")
43
44
  accumulate_error(err_msg, params)
44
45
  if params["is_save"]:
45
- params["result_map"][field.name] = None
46
+ params["result_map"][field_name] = None
46
47
  return
47
48
  # Validation the `maxlength` field attribute.
48
49
  maxlength: int | None = field.__dict__.get("maxlength")
@@ -50,7 +51,12 @@ class TextGroupMixin:
50
51
  err_msg = translations._("The length of the string exceeds maxlength=%d !" % maxlength)
51
52
  accumulate_error(err_msg, params)
52
53
  # Validation the `unique` field attribute.
53
- if field.unique and not await check_uniqueness(value, params):
54
+ if field.unique and not await check_uniqueness(
55
+ value,
56
+ params,
57
+ field_name,
58
+ is_text_field,
59
+ ):
54
60
  err_msg = translations._("Is not unique !")
55
61
  accumulate_error(err_msg, params)
56
62
  # Validation Email, Url, IP, Color, Phone.
@@ -80,13 +86,13 @@ class TextGroupMixin:
80
86
  # Insert result.
81
87
  if params["is_save"]:
82
88
  if is_text_field:
83
- mult_lang_text: dict[str, str] = {}
84
- if params["mongo_doc"] is not None:
85
- mult_lang_text = params["mongo_doc"][field.name]
89
+ mult_lang_text: dict[str, str] = (
90
+ params["curr_doc"][field_name] if params["is_update"] else {}
91
+ )
86
92
  if isinstance(value, dict):
87
93
  for lang, text in value.items():
88
94
  mult_lang_text[lang] = text
89
95
  else:
90
96
  mult_lang_text[translations.CURRENT_LOCALE] = value
91
97
  value = mult_lang_text
92
- params["result_map"][field.name] = value
98
+ params["result_map"][field_name] = value
@@ -54,14 +54,26 @@ def accumulate_error(err_msg: str, params: dict[str, Any]) -> None:
54
54
  async def check_uniqueness(
55
55
  value: str | int | float,
56
56
  params: dict[str, Any],
57
+ field_name: str | None = None,
58
+ is_text_field: bool = False,
57
59
  ) -> bool:
58
60
  """Check the uniqueness of the value in the collection."""
59
61
  if not params["is_migrate_model"]:
60
62
  return True
61
- q_filter = {
62
- "$and": [
63
- {"_id": {"$ne": params["doc_id"]}},
64
- {params["field_data"].name: value},
65
- ],
66
- }
63
+ q_filter = None
64
+ if is_text_field:
65
+ lang_filter = [{f"{field_name}.{lang}": value} for lang in translations.LANGUAGES]
66
+ q_filter = {
67
+ "$and": [
68
+ {"_id": {"$ne": params["doc_id"]}},
69
+ {"$or": lang_filter},
70
+ ],
71
+ }
72
+ else:
73
+ q_filter = {
74
+ "$and": [
75
+ {"_id": {"$ne": params["doc_id"]}},
76
+ {field_name: value},
77
+ ],
78
+ }
67
79
  return await params["collection"].find_one(q_filter) is None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ramifice
3
- Version: 0.4.0
3
+ Version: 0.4.2
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/
@@ -135,12 +135,22 @@ from datetime import datetime
135
135
 
136
136
  from pymongo import AsyncMongoClient
137
137
  from ramifice import model, translations, migration
138
- from ramifice.fields import DateField, EmailField, ImageField, PasswordField, TextField, FileField
138
+ from ramifice.fields import (
139
+ DateField,
140
+ EmailField,
141
+ FileField,
142
+ ImageField,
143
+ PasswordField,
144
+ TextField,
145
+ )
139
146
 
140
147
 
141
148
  @model(service_name="Accounts")
142
149
  class User:
150
+ """Model of User."""
151
+
143
152
  def fields(self):
153
+ """For adding fields."""
144
154
  # For custom translations.
145
155
  gettext = translations.gettext
146
156
  ngettext = translations.ngettext
@@ -228,7 +238,7 @@ async def main():
228
238
  user.print_err()
229
239
 
230
240
  print("User details:")
231
- user_details = await User.find_one_to_raw_doc({"_id": user._id.value})
241
+ user_details = await User.find_one_to_raw_doc({"_id": user.id.value})
232
242
  pprint.pprint(user_details)
233
243
 
234
244
  # Remove User.
@@ -45,15 +45,15 @@ ramifice/fields/general/number_group.py,sha256=AqlCY-t6JHZ2QVBe7mk5nPt6z8M4VJ_RA
45
45
  ramifice/fields/general/text_group.py,sha256=6GD2Fe6Toz6zZjAAlcy5rPVCAGh6Yn1ltdIrFg9RF18,1057
46
46
  ramifice/models/__init__.py,sha256=h_QQ5rSJNZ-7kmx7wIFd8E8RmUS94b_x4jdwMbq8zm4,15
47
47
  ramifice/models/decorator.py,sha256=jOEn-0v0m_tM7mow45-tM-8LADUmwlG2DWZsEuC9S_w,6834
48
- ramifice/models/model.py,sha256=6iD4c6Rk9Y5SFXnKNULWk7PlgVfzU_i4arF6SX6nysg,6495
48
+ ramifice/models/model.py,sha256=ZvgIbcuSXuAkBl_FofOZXGwWMwlqKB-PwTMyXiqK-Fo,6610
49
49
  ramifice/models/pseudo.py,sha256=PhLQM4zXdaOtTSmNFzwN4twlUmdvA1D_-YOMJtaOIwM,6754
50
50
  ramifice/paladins/__init__.py,sha256=PIP3AXI2KBRXNcLJUF0d7ygJ7VLOAxlhb4HRKQ9MGYY,516
51
- ramifice/paladins/check.py,sha256=hz9uQtAarZG9P2I5bwVYgKn2Nk_BD2wB3yqEdD3w494,6838
51
+ ramifice/paladins/check.py,sha256=SdDC9cE4I_Pt9L9NTatEzNYtwpcCIy03yCJqi1O6qM8,6796
52
52
  ramifice/paladins/delete.py,sha256=tw50E98D5eFZ7gHGnh_8ztUB1LeTeWWKZvIcQqlgbF8,3352
53
53
  ramifice/paladins/password.py,sha256=w1XWh3bsncH1VTVjCLxyKI2waxMvltwcsPWW3V9Ib84,3027
54
54
  ramifice/paladins/refrash.py,sha256=fw-9x_NKGzreipBt_F9KF6FTsYm9hSzfq4ubi1FHYrQ,1065
55
55
  ramifice/paladins/save.py,sha256=EG0_v-imCQPax2pJIAXPoQcSL99g8abY2EeGJMvXBW4,3864
56
- ramifice/paladins/tools.py,sha256=d3sKH6GzPlt7SxR9JyTEY3YgmqhwNvwPOg3hg80-zoU,2297
56
+ ramifice/paladins/tools.py,sha256=SCmESo8isvcy0yk43Rj1J5BZ1xSZbNV1KLhhBrzfezY,2687
57
57
  ramifice/paladins/validation.py,sha256=gcEJXIEPu1g7Z54vl14YTs5rCmxOEYsgQH1usFfyy7k,1730
58
58
  ramifice/paladins/groups/__init__.py,sha256=hpqmWLsYAMvZHAbmMXluQSqLhkHOSTUAgLHyTM1LTYI,472
59
59
  ramifice/paladins/groups/bool_group.py,sha256=oJc9mw9KGrnK_Pj7uXixYYQAJphcXLr_xSQv3PMUlcU,792
@@ -62,10 +62,10 @@ ramifice/paladins/groups/date_group.py,sha256=B9usKKrHX16F1ckik60Xkub1tawgNENSHT
62
62
  ramifice/paladins/groups/file_group.py,sha256=-xgtrLOTlKXc71Mnbu3I_LbYnTEd8OprnhtYcJbaDtg,2932
63
63
  ramifice/paladins/groups/id_group.py,sha256=q5BeoM1e7mZmX0zVgemva9K-9ihJKBrX8kxvMh-uhhQ,1268
64
64
  ramifice/paladins/groups/img_group.py,sha256=RoD_QnW0F0DAzrGQmRi8jMZnWy2IomlFn6A5jTM02iA,5542
65
- ramifice/paladins/groups/num_group.py,sha256=FHT9D2S3TsxdMypqoBgZsIzlaLY0KjXdPYqB95vvTRI,2229
65
+ ramifice/paladins/groups/num_group.py,sha256=6jT7nfIiVoQTlI2UdkcQOlHIDYjllFqSH7Nb87uJgzg,2274
66
66
  ramifice/paladins/groups/pass_group.py,sha256=YU5a-NwohEutoEx2N5JmGfg8uPiYiW0XJ8XYsOih6eA,1859
67
- ramifice/paladins/groups/slug_group.py,sha256=o-lr1ssfhTcBovlS6pWA2TQdg1qI6tlDjZ2iKkz-584,2191
68
- ramifice/paladins/groups/text_group.py,sha256=TVMo19IU-bLEb-xOeNNfSejTr0lDYahrQhWMHvle-Ws,3896
67
+ ramifice/paladins/groups/slug_group.py,sha256=joBB5litljbv2h5JKEMzF71s_DKMWH6nzgThLiLZx2E,2307
68
+ ramifice/paladins/groups/text_group.py,sha256=67gk-vEoZImifCqIzWYexc0Yj2__srFAUqmOHRhBgOk,4005
69
69
  ramifice/utils/__init__.py,sha256=xixHoOX4ja5jIUZemem1qn4k4aonv3G3Q76azQK_pkU,43
70
70
  ramifice/utils/errors.py,sha256=iuhq7fzpUmsOyeXeg2fJjta8yAuqlXLKsZVMpfUhtHE,1901
71
71
  ramifice/utils/fixtures.py,sha256=NtxOnZslYJb4yvRpZbs3ckugmTwHQFS_9iCt2zddOC0,3102
@@ -79,7 +79,7 @@ ramifice/utils/mixins/add_valid.py,sha256=TLOObedzXNA9eCylfAVbVCqIKE5sV-P5AdIN7a
79
79
  ramifice/utils/mixins/hooks.py,sha256=33jvJRhfnJeL2Hd_YFXk3M_7wjqHaByU2wRjKyboL6s,914
80
80
  ramifice/utils/mixins/indexing.py,sha256=Z0427HoaVRyNmSNN8Fx0mSICgAKV-gDdu3iR5qYUEbs,329
81
81
  ramifice/utils/mixins/json_converter.py,sha256=WhigXyDAV-FfILaZuwvRFRIk0D90Rv3dG5t-mv5fVyc,1107
82
- ramifice-0.4.0.dist-info/METADATA,sha256=hzKA83Yk4QFj5gAQWnu7X9y-ove9os6gEIiRYj3w3DE,20962
83
- ramifice-0.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
84
- ramifice-0.4.0.dist-info/licenses/LICENSE,sha256=LrEL0aTZx90HDwFUQCJutORiDjJL9AnuVvCtspXIqt4,1095
85
- ramifice-0.4.0.dist-info/RECORD,,
82
+ ramifice-0.4.2.dist-info/METADATA,sha256=ZJlFn29k4RDuT4iyHoqJQl4VTx4otqyDr27fb6I3KKA,21049
83
+ ramifice-0.4.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
84
+ ramifice-0.4.2.dist-info/licenses/LICENSE,sha256=LrEL0aTZx90HDwFUQCJutORiDjJL9AnuVvCtspXIqt4,1095
85
+ ramifice-0.4.2.dist-info/RECORD,,