ramifice 0.3.18__py3-none-any.whl → 0.3.20__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/decorators.py CHANGED
@@ -65,7 +65,10 @@ def model(
65
65
  "is_update_doc": is_update_doc if is_migrate_model else False,
66
66
  "is_delete_doc": is_delete_doc if is_migrate_model else False,
67
67
  }
68
- attrs["META"] = {**metadata, **caching(cls, service_name)}
68
+ attrs["META"] = {
69
+ **metadata,
70
+ **caching(cls, service_name),
71
+ }
69
72
 
70
73
  if is_migrate_model:
71
74
  return type(
@@ -96,7 +99,7 @@ def model(
96
99
 
97
100
 
98
101
  def caching(cls: Any, service_name: str) -> dict[str, Any]:
99
- """Get additional metadata for `Model.META`."""
102
+ """Add additional metadata to `Model.META`."""
100
103
  metadata: dict[str, Any] = {}
101
104
  model_name = cls.__name__
102
105
  if REGEX["model_name"].match(model_name) is None:
@@ -117,14 +120,14 @@ def caching(cls: Any, service_name: str) -> dict[str, Any]:
117
120
  # Count fields for migrating.
118
121
  count_fields_for_migrating = 0
119
122
 
120
- old_model = cls()
121
- old_model.fields()
123
+ raw_model = cls()
124
+ raw_model.fields()
122
125
  default_fields: dict[str, Any] = {
123
126
  "_id": IDField(),
124
127
  "created_at": DateTimeField(),
125
128
  "updated_at": DateTimeField(),
126
129
  }
127
- fields = {**old_model.__dict__, **default_fields}
130
+ fields = {**raw_model.__dict__, **default_fields}
128
131
  for f_name, f_type in fields.items():
129
132
  if not callable(f_type):
130
133
  f_type_str = f_type.__class__.__name__
@@ -4,7 +4,7 @@ import os
4
4
  import shutil
5
5
  import uuid
6
6
  from base64 import b64decode
7
- from datetime import datetime
7
+ from datetime import date
8
8
  from pathlib import Path
9
9
  from typing import Any
10
10
 
@@ -102,7 +102,7 @@ class FileField(Field, FileGroup, JsonMixin):
102
102
  """ # noqa: D205
103
103
  base64_str = base64_str or None
104
104
  filename = filename or None
105
- file_info = store.FILE_INFO_DICT.copy()
105
+ file_info: dict[str, str | int | bool] = {"save_as_is": False}
106
106
  file_info["is_new_file"] = True
107
107
  file_info["is_delete"] = is_delete
108
108
 
@@ -121,7 +121,7 @@ class FileField(Field, FileGroup, JsonMixin):
121
121
  # Create new (uuid) file name.
122
122
  f_uuid_name = f"{uuid.uuid4()}{extension}"
123
123
  # Create the current date for the directory name.
124
- date_str = datetime.now().strftime("%Y-%m-%d")
124
+ date_str: str = str(date.today())
125
125
  # Create path to target directory.
126
126
  dir_target_path = f"{self.media_root}/{self.target_dir}/{date_str}"
127
127
  # Create target directory if it does not exist.
@@ -142,11 +142,10 @@ class FileField(Field, FileGroup, JsonMixin):
142
142
  file_info["extension"] = extension
143
143
  # Add file size (in bytes).
144
144
  file_info["size"] = os.path.getsize(f_target_path)
145
-
145
+ #
146
146
  # to value.
147
147
  self.value = file_info
148
148
 
149
- # --------------------------------------------------------------------------
150
149
  def from_path(
151
150
  self,
152
151
  src_path: str | None = None,
@@ -154,7 +153,7 @@ class FileField(Field, FileGroup, JsonMixin):
154
153
  ) -> None:
155
154
  """Get file information and copy the file to the target directory."""
156
155
  src_path = src_path or None
157
- file_info = store.FILE_INFO_DICT.copy()
156
+ file_info: dict[str, str | int | bool] = {"save_as_is": False}
158
157
  file_info["is_new_file"] = True
159
158
  file_info["is_delete"] = is_delete
160
159
 
@@ -167,7 +166,7 @@ class FileField(Field, FileGroup, JsonMixin):
167
166
  # Create new (uuid) file name.
168
167
  f_uuid_name = f"{uuid.uuid4()}{extension}"
169
168
  # Create the current date for the directory name.
170
- date_str = datetime.now().strftime("%Y-%m-%d")
169
+ date_str: str = str(date.today())
171
170
  # Create path to target directory.
172
171
  dir_target_path = f"{self.media_root}/{self.target_dir}/{date_str}"
173
172
  # Create target directory if it does not exist.
@@ -186,6 +185,6 @@ class FileField(Field, FileGroup, JsonMixin):
186
185
  file_info["extension"] = extension
187
186
  # Add file size (in bytes).
188
187
  file_info["size"] = os.path.getsize(f_target_path)
189
-
188
+ #
190
189
  # to value.
191
190
  self.value = file_info
@@ -4,7 +4,7 @@ import os
4
4
  import shutil
5
5
  import uuid
6
6
  from base64 import b64decode
7
- from datetime import datetime
7
+ from datetime import date
8
8
  from pathlib import Path
9
9
  from typing import Any
10
10
 
@@ -135,14 +135,13 @@ class ImageField(Field, FileGroup, JsonMixin):
135
135
  base64_str: str | None = None,
136
136
  filename: str | None = None,
137
137
  is_delete: bool = False,
138
- add_wh: bool = False,
139
138
  ) -> None:
140
139
  """Convert base64 to a image,
141
140
  get image information and save in the target directory.
142
141
  """ # noqa: D205
143
142
  base64_str = base64_str or None
144
143
  filename = filename or None
145
- img_info = store.IMG_INFO_DICT.copy()
144
+ img_info: dict[str, str | int | bool] = {"save_as_is": False}
146
145
  img_info["is_new_img"] = True
147
146
  img_info["is_delete"] = is_delete
148
147
 
@@ -159,7 +158,7 @@ class ImageField(Field, FileGroup, JsonMixin):
159
158
  if item[0] == 40:
160
159
  break
161
160
  # Create the current date for the directory name.
162
- date_str = datetime.now().strftime("%Y-%m-%d")
161
+ date_str: str = str(date.today())
163
162
  # Directory name for the original image and its thumbnails.
164
163
  general_dir = uuid.uuid4()
165
164
  # Create path to target directory with images.
@@ -181,7 +180,7 @@ class ImageField(Field, FileGroup, JsonMixin):
181
180
  img_info["path"] = main_img_path
182
181
  img_info["url"] = f"{imgs_dir_url}/{new_original_name}"
183
182
  # Add width and height.
184
- if add_wh:
183
+ if self.__dict__.get("add_width_height", False):
185
184
  with Image.open(main_img_path) as img:
186
185
  width, height = img.size
187
186
  img_info["width"] = width
@@ -201,20 +200,18 @@ class ImageField(Field, FileGroup, JsonMixin):
201
200
  img_info["imgs_dir_url"] = imgs_dir_url
202
201
  # Add size of main image (in bytes).
203
202
  img_info["size"] = os.path.getsize(main_img_path)
204
-
203
+ #
205
204
  # to value.
206
205
  self.value = img_info
207
206
 
208
- # --------------------------------------------------------------------------
209
207
  def from_path(
210
208
  self,
211
209
  src_path: str | None = None,
212
210
  is_delete: bool = False,
213
- add_wh: bool = False,
214
211
  ) -> None:
215
212
  """Get image information and copy the image to the target directory."""
216
213
  src_path = src_path or None
217
- img_info = store.IMG_INFO_DICT.copy()
214
+ img_info: dict[str, str | int | bool] = {"save_as_is": False}
218
215
  img_info["is_new_img"] = True
219
216
  img_info["is_delete"] = is_delete
220
217
 
@@ -225,7 +222,7 @@ class ImageField(Field, FileGroup, JsonMixin):
225
222
  msg = f"The image `{src_path}` has no extension."
226
223
  raise FileHasNoExtensionError(msg)
227
224
  # Create the current date for the directory name.
228
- date_str = datetime.now().strftime("%Y-%m-%d")
225
+ date_str: str = str(date.today())
229
226
  # Directory name for the original image and its thumbnails.
230
227
  general_dir = uuid.uuid4()
231
228
  # Create path to target directory with images.
@@ -245,7 +242,7 @@ class ImageField(Field, FileGroup, JsonMixin):
245
242
  img_info["path"] = main_img_path
246
243
  img_info["url"] = f"{imgs_dir_url}/{new_original_name}"
247
244
  # Add width and height.
248
- if add_wh:
245
+ if self.__dict__.get("add_width_height", False):
249
246
  with Image.open(main_img_path) as img:
250
247
  width, height = img.size
251
248
  img_info["width"] = width
@@ -265,6 +262,6 @@ class ImageField(Field, FileGroup, JsonMixin):
265
262
  img_info["imgs_dir_url"] = imgs_dir_url
266
263
  # Add size of main image (in bytes).
267
264
  img_info["size"] = os.path.getsize(main_img_path)
268
-
265
+ #
269
266
  # to value.
270
267
  self.value = img_info
ramifice/migration.py CHANGED
@@ -15,7 +15,6 @@ from . import store
15
15
  from .errors import DoesNotMatchRegexError, NoModelsForMigrationError, PanicError
16
16
  from .fixtures import apply_fixture
17
17
  from .model import Model
18
- from .store import FILE_INFO_DICT, IMG_INFO_DICT
19
18
 
20
19
 
21
20
  class Monitor:
@@ -137,13 +136,19 @@ class Monitor:
137
136
  field_type = metadata["field_name_and_type"].get(field_name)
138
137
  if field_type is not None:
139
138
  if field_type == "FileField":
140
- file_data = FILE_INFO_DICT.copy()
141
- file_data["is_delete"] = True
142
- mongo_doc[field_name] = file_data
139
+ file_info = {
140
+ "path": "",
141
+ "is_delete": True,
142
+ "save_as_is": False,
143
+ }
144
+ mongo_doc[field_name] = file_info
143
145
  elif field_type == "ImageField":
144
- img_data = IMG_INFO_DICT.copy()
145
- img_data["is_delete"] = True
146
- mongo_doc[field_name] = img_data
146
+ img_info = {
147
+ "path": "",
148
+ "is_delete": True,
149
+ "save_as_is": False,
150
+ }
151
+ mongo_doc[field_name] = img_info
147
152
  else:
148
153
  mongo_doc[field_name] = None
149
154
  #
ramifice/model.py CHANGED
@@ -1,7 +1,8 @@
1
1
  """For converting Python classes into Ramifice Model."""
2
2
 
3
- import copy
4
3
  import json
4
+ import os
5
+ import shutil
5
6
  from abc import ABCMeta, abstractmethod
6
7
  from typing import Any
7
8
 
@@ -45,6 +46,29 @@ class Model(metaclass=ABCMeta):
45
46
  )
46
47
  self.fields()
47
48
  self.inject()
49
+ if not self.__class__.META["is_migrate_model"]:
50
+ for _, f_type in self.__dict__.items():
51
+ if not callable(f_type):
52
+ if f_type.group == "img":
53
+ f_type.__dict__["add_width_height"] = True
54
+
55
+ def __del__(self) -> None: # noqa: D105
56
+ # If the model is not migrated,
57
+ # it must delete files and images in the destructor.
58
+ if not self.__class__.META["is_migrate_model"]:
59
+ for _, f_type in self.__dict__.items():
60
+ if not callable(f_type):
61
+ value = f_type.value
62
+ if value is None:
63
+ continue
64
+ if f_type.group == "file":
65
+ value = value.get("path")
66
+ if value is not None:
67
+ os.remove(value)
68
+ elif f_type.group == "img":
69
+ value = value.get("imgs_dir_path")
70
+ if value is not None:
71
+ shutil.rmtree(value)
48
72
 
49
73
  @abstractmethod
50
74
  def fields(self) -> None:
@@ -3,7 +3,6 @@
3
3
  Supported fields: FileField
4
4
  """
5
5
 
6
- import os
7
6
  from typing import Any
8
7
 
9
8
  from ... import translations
@@ -46,7 +45,7 @@ class FileGroupMixin:
46
45
  return
47
46
  if not value["save_as_is"]:
48
47
  # If the file needs to be delete.
49
- if value["is_delete"] and len(value.path) == 0:
48
+ if value["is_delete"] and len(value["path"]) == 0:
50
49
  default = field.default or None
51
50
  # If necessary, use the default value.
52
51
  if default is not None:
@@ -67,12 +66,6 @@ class FileGroupMixin:
67
66
  )
68
67
  accumulate_error(params["full_model_name"], err_msg, params)
69
68
  return
70
- # Return if there is no need to save.
71
- if not params["is_save"]:
72
- if value["is_new_file"]:
73
- os.remove(value["path"])
74
- params["field_data"].value = None
75
- return
76
69
  # Insert result.
77
70
  if params["is_save"] and (value["is_new_file"] or value["save_as_is"]):
78
71
  value["is_delete"] = False
@@ -3,7 +3,6 @@
3
3
  Supported fields: ImageField
4
4
  """
5
5
 
6
- import shutil
7
6
  from typing import Any
8
7
 
9
8
  from PIL import Image
@@ -69,12 +68,6 @@ class ImgGroupMixin:
69
68
  )
70
69
  accumulate_error(params["full_model_name"], err_msg, params)
71
70
  return
72
- # Return if there is no need to save.
73
- if not params["is_save"]:
74
- if value["is_new_img"]:
75
- shutil.rmtree(value["imgs_dir_path"])
76
- params["field_data"].value = None
77
- return
78
71
  # Create thumbnails.
79
72
  if value["is_new_img"]:
80
73
  thumbnails = field.thumbnails
ramifice/store.py CHANGED
@@ -43,43 +43,3 @@ REGEX: dict[str, re.Pattern] = {
43
43
  ),
44
44
  "password": re.compile(r'^[-._!"`\'#%&,:;<>=@{}~\$\(\)\*\+\/\\\?\[\]\^\|a-zA-Z0-9]{8,256}$'),
45
45
  }
46
-
47
- # Caching a dictionary to transmit information about the file.
48
- # Hint: `FileField.value`.
49
- FILE_INFO_DICT: dict[str, str | int | bool] = dict(
50
- path="",
51
- url="",
52
- name="",
53
- size=0,
54
- is_new_file=False,
55
- is_delete=False,
56
- extension="",
57
- save_as_is=False,
58
- )
59
-
60
- # Caching a dictionary to transmit information about the image.
61
- # Hint: `ImageField.value`.
62
- IMG_INFO_DICT: dict[str, str | int | bool] = dict(
63
- path="",
64
- path_xs="",
65
- path_sm="",
66
- path_md="",
67
- path_lg="",
68
- url="",
69
- url_xs="",
70
- url_sm="",
71
- url_md="",
72
- url_lg="",
73
- name="",
74
- width=0,
75
- height=0,
76
- size=0,
77
- is_new_img=False,
78
- is_delete=False,
79
- extension="",
80
- imgs_dir_path="",
81
- imgs_dir_url="",
82
- save_as_is=False,
83
- # Extension to the upper register and delete the point.
84
- ext_upper="",
85
- )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ramifice
3
- Version: 0.3.18
3
+ Version: 0.3.20
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/
@@ -1,15 +1,15 @@
1
1
  ramifice/__init__.py,sha256=ISlaL2BprlJLE_N1fvtAqGrB3Dhniy9IZGoyWEYZhRU,678
2
2
  ramifice/add_valid.py,sha256=kvpMg7snL9tor0A23XRdgwiXazRwHfb8baoJUNjM_4Y,327
3
- ramifice/decorators.py,sha256=hTivOrCbTqnnbbbicgoET3bLSICSjMzqctLKzf2YseM,6144
3
+ ramifice/decorators.py,sha256=txbTYnKw5AtRZb7IshOzEHuoy8MAPB8wBcCTbk-6CcE,6181
4
4
  ramifice/errors.py,sha256=iuhq7fzpUmsOyeXeg2fJjta8yAuqlXLKsZVMpfUhtHE,1901
5
5
  ramifice/fixtures.py,sha256=NtxOnZslYJb4yvRpZbs3ckugmTwHQFS_9iCt2zddOC0,3102
6
6
  ramifice/hooks.py,sha256=Ri-ISfMT-IHaLO2eAqg8CODCTs3HRTxSylqspUKnVf4,873
7
7
  ramifice/indexing.py,sha256=wQpX2qei5Zc7iIq5yIV93Skp8Aa8ZD0vybnEk7cRuXs,271
8
- ramifice/migration.py,sha256=lksHC2f_19pDHp6Sg9pdwqA14jKxMsS8T7gfBdzIsDw,10932
8
+ ramifice/migration.py,sha256=t_Rm1OUQYrlaPQQd1uS5S7EYMvSuKUcWzi7P4JMkrOw,11114
9
9
  ramifice/mixins.py,sha256=gKLmWQ-QrGO3K5_k-h1tDa08lkCql_dte2Jy05q1wsM,1125
10
- ramifice/model.py,sha256=eJCrwURQuZApY84IpxvecS6dHTvT4MK3BpGFTEWz-H4,6536
10
+ ramifice/model.py,sha256=hKA_BrGBWcn-mYB9dHIJoSJYEteO6SdJdgwgjdaV7mc,7632
11
11
  ramifice/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- ramifice/store.py,sha256=Kqd2Zw7Wj2vnn_0eE6KmIOkWJRhDc6AZ0ZyqxENBetQ,2730
12
+ ramifice/store.py,sha256=MpDEPvUvbs11FXjakNtHPm9MekIv5p1U3as2Y80lTyc,1860
13
13
  ramifice/translations.py,sha256=GNGE0ULAA0aOY5pTxUd3MQW-nVaKvp6BeXWEcsR0s0o,4048
14
14
  ramifice/types.py,sha256=ljo6VscUGWEJ4Km4JYo8GEfxd1YK1CUbS8CfHp_MlEA,2390
15
15
  ramifice/utilities.py,sha256=c662nwFcWXSXNYfwqDnGlLWpA01KaK79GwTdApqtMh8,2442
@@ -38,10 +38,10 @@ ramifice/fields/color_field.py,sha256=sjVSoJU6TIZ66wzPx0WRl5zQsx-kINMMuxa_pSUpW6
38
38
  ramifice/fields/date_field.py,sha256=Vlaxgp3WeDNMwbnQcTGu8kyQ7gc7M-7sFBPfzu-4MVw,5205
39
39
  ramifice/fields/date_time_field.py,sha256=VpLeYJHs0df45fz4gnprtn7aipVFKGY4n02eRep7in0,5240
40
40
  ramifice/fields/email_field.py,sha256=wOM07nQ5fOSOTydQhg3b4dV_95F1bd97peQ_XAnV0MY,3720
41
- ramifice/fields/file_field.py,sha256=-1oxKg8Bs6lqNB2wIEldGBck5YwwgoDtCks2z1vHnww,7940
41
+ ramifice/fields/file_field.py,sha256=NMM9k-kVes7VarxvTQmsl2f2nvRKp-upjPHMDjNIrwY,7892
42
42
  ramifice/fields/float_field.py,sha256=4l7gzg46qQ7ZbXS6Z8GUhiUBR26rXChvO_uFx-lbUds,4555
43
43
  ramifice/fields/id_field.py,sha256=5wlY2j051TB2GPsw0iQkFiQBV_Y_o1W_QnCtBlaDuYQ,4126
44
- ramifice/fields/image_field.py,sha256=EX7J-qon60_FJDE3_pnink6pa5vTRGspj8v_Rk8JEt4,12301
44
+ ramifice/fields/image_field.py,sha256=u4YJ3vFtGj5uhVLjgrvV9gNLwLXT4jfVPUN2mlPKHfg,12269
45
45
  ramifice/fields/integer_field.py,sha256=Gnm5IBSvWtCLGbg5pOSAdKa5xLzqXgiigVbzw8zcjas,4531
46
46
  ramifice/fields/ip_field.py,sha256=D7xR3A-O049TQ_pEEKVTLsKF5cdr5O7ULyz4Pj3-cwQ,3601
47
47
  ramifice/fields/password_field.py,sha256=5BlZZ4mXM0CAYDHguwsK8KFnvkOOmr8R0yowHByNVD4,3451
@@ -68,14 +68,14 @@ ramifice/paladins/groups/__init__.py,sha256=hpqmWLsYAMvZHAbmMXluQSqLhkHOSTUAgLHy
68
68
  ramifice/paladins/groups/bool_group.py,sha256=fpxCySJ5JL7w1dLFPX1025zEU8CRsWSyQyXb3Hr3Z2s,819
69
69
  ramifice/paladins/groups/choice_group.py,sha256=OJeZjpnqKnSF1_bechtNepCCPjmp54x1T0c28DAa11c,1777
70
70
  ramifice/paladins/groups/date_group.py,sha256=-IS9pAHXdWK7tO9KQ2UyG1uf7TA43DKYCOCtOM2_tZ0,3844
71
- ramifice/paladins/groups/file_group.py,sha256=oQ61TCGoRF8kArOY0F2IXXUTOiRyyu0oh3F1reV8rmU,3298
71
+ ramifice/paladins/groups/file_group.py,sha256=9GzRY3sV8PYJh23ZPtMQYH5RDi4pibN-kIaSui4B5zY,3033
72
72
  ramifice/paladins/groups/id_group.py,sha256=tK3OL1pr-V8PHPyS7vmjmJi_sRU669EvkY_Fc4sRHzg,1352
73
- ramifice/paladins/groups/img_group.py,sha256=X8JDvxr1khNfsuPUXRn_1PoZnrjk_TKTklwujB8Rc9A,5927
73
+ ramifice/paladins/groups/img_group.py,sha256=j184UyyYZ8gNuAivkP1A57o9JlrGS_0sht6QKiblbDs,5643
74
74
  ramifice/paladins/groups/num_group.py,sha256=Jvb-lwHxapQybbLerC4t-_yO8N7Coo1fIlZ9eAGHcGs,2508
75
75
  ramifice/paladins/groups/pass_group.py,sha256=SEKpR2voNQtmywugDXJKY4XqPTL91CrJ87h0QNMqQqs,1952
76
76
  ramifice/paladins/groups/slug_group.py,sha256=_IRil2PwpY7cH7WaExNksKz61kQjvc27blrEufgUB30,2323
77
77
  ramifice/paladins/groups/text_group.py,sha256=nYZGwAIsJD-tX8RBtFlWvngO9RU4V0CnREUhxvV2UDo,3493
78
- ramifice-0.3.18.dist-info/METADATA,sha256=lojHKf4q5Rrxj4vXJxOfqmNnmZu0JRXalEJxAhoBNAU,18904
79
- ramifice-0.3.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
80
- ramifice-0.3.18.dist-info/licenses/LICENSE,sha256=LrEL0aTZx90HDwFUQCJutORiDjJL9AnuVvCtspXIqt4,1095
81
- ramifice-0.3.18.dist-info/RECORD,,
78
+ ramifice-0.3.20.dist-info/METADATA,sha256=ZpWGFOazkmaGbW9rMKja65dApz_DHCrA2_PBCynIqzw,18904
79
+ ramifice-0.3.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
80
+ ramifice-0.3.20.dist-info/licenses/LICENSE,sha256=LrEL0aTZx90HDwFUQCJutORiDjJL9AnuVvCtspXIqt4,1095
81
+ ramifice-0.3.20.dist-info/RECORD,,