ramifice 0.8.29__py3-none-any.whl → 0.8.31__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/__init__.py CHANGED
@@ -23,21 +23,20 @@ The project is more concentrated for web development or for applications with a
23
23
 
24
24
  __all__ = (
25
25
  "NamedTuple",
26
+ "to_human_size",
26
27
  "model",
27
28
  "translations",
28
29
  "Migration",
29
- "to_human_size",
30
30
  "Unit",
31
31
  )
32
32
 
33
33
  import logging
34
34
 
35
- from xloft import NamedTuple
35
+ from xloft import NamedTuple, to_human_size
36
36
 
37
37
  from ramifice.models.decorator import model
38
38
  from ramifice.utils import translations
39
39
  from ramifice.utils.migration import Migration
40
- from ramifice.utils.tools import to_human_size
41
40
  from ramifice.utils.unit import Unit
42
41
 
43
42
  logging.basicConfig(
@@ -15,7 +15,11 @@ from anyio import Path, open_file, to_thread
15
15
  from ramifice.fields.general.field import Field
16
16
  from ramifice.fields.general.file_group import FileGroup
17
17
  from ramifice.utils import constants
18
- from ramifice.utils.constants import MEDIA_ROOT, MEDIA_URL
18
+ from ramifice.utils.constants import (
19
+ MEDIA_ROOT,
20
+ MEDIA_URL,
21
+ UTC_TIMEZONE,
22
+ )
19
23
  from ramifice.utils.errors import FileHasNoExtensionError
20
24
  from ramifice.utils.mixins import JsonMixin
21
25
 
@@ -147,7 +151,7 @@ class FileField(Field, FileGroup, JsonMixin):
147
151
  # Create new (uuid) file name.
148
152
  f_uuid_name = f"{uuid.uuid4()}{extension}"
149
153
  # Create the current date for the directory name.
150
- date_str: str = str(datetime.now().date()) # noqa: DTZ005
154
+ date_str: str = str(datetime.now(UTC_TIMEZONE).date())
151
155
  # Create path to target directory.
152
156
  dir_target_path = f"{MEDIA_ROOT}/uploads/{self.target_dir}/{date_str}"
153
157
  # Create target directory if it does not exist.
@@ -193,7 +197,7 @@ class FileField(Field, FileGroup, JsonMixin):
193
197
  # Create new (uuid) file name.
194
198
  f_uuid_name = f"{uuid.uuid4()}{extension}"
195
199
  # Create the current date for the directory name.
196
- date_str: str = str(datetime.now().date()) # noqa: DTZ005
200
+ date_str: str = str(datetime.now(UTC_TIMEZONE).date())
197
201
  # Create path to target directory.
198
202
  dir_target_path = f"{MEDIA_ROOT}/uploads/{self.target_dir}/{date_str}"
199
203
  # Create target directory if it does not exist.
@@ -15,7 +15,11 @@ from anyio import Path, open_file, to_thread
15
15
  from ramifice.fields.general.field import Field
16
16
  from ramifice.fields.general.file_group import FileGroup
17
17
  from ramifice.utils import constants
18
- from ramifice.utils.constants import MEDIA_ROOT, MEDIA_URL
18
+ from ramifice.utils.constants import (
19
+ MEDIA_ROOT,
20
+ MEDIA_URL,
21
+ UTC_TIMEZONE,
22
+ )
19
23
  from ramifice.utils.errors import FileHasNoExtensionError
20
24
  from ramifice.utils.mixins import JsonMixin
21
25
 
@@ -173,7 +177,7 @@ class ImageField(Field, FileGroup, JsonMixin):
173
177
  if item[0] == 40:
174
178
  break
175
179
  # Create the current date for the directory name.
176
- date_str: str = str(datetime.now().date()) # noqa: DTZ005
180
+ date_str: str = str(datetime.now(UTC_TIMEZONE).date())
177
181
  # Directory name for the original image and its thumbnails.
178
182
  general_dir = uuid.uuid4()
179
183
  # Create path to target directory with images.
@@ -232,7 +236,7 @@ class ImageField(Field, FileGroup, JsonMixin):
232
236
  logger.error(msg)
233
237
  raise FileHasNoExtensionError(msg)
234
238
  # Create the current date for the directory name.
235
- date_str: str = str(datetime.now().date()) # noqa: DTZ005
239
+ date_str: str = str(datetime.now(UTC_TIMEZONE).date())
236
240
  # Directory name for the original image and its thumbnails.
237
241
  general_dir = uuid.uuid4()
238
242
  # Create path to target directory with images.
@@ -7,12 +7,13 @@ __all__ = ("FileGroupMixin",)
7
7
 
8
8
  from typing import Any
9
9
 
10
+ from xloft import to_human_size
11
+
10
12
  from ramifice.paladins.tools import (
11
13
  accumulate_error,
12
14
  panic_type_error,
13
15
  )
14
16
  from ramifice.utils import translations
15
- from ramifice.utils.tools import to_human_size
16
17
 
17
18
 
18
19
  class FileGroupMixin:
@@ -9,10 +9,10 @@ from asyncio import to_thread
9
9
  from typing import Any
10
10
 
11
11
  from PIL import Image
12
+ from xloft import to_human_size
12
13
 
13
14
  from ramifice.paladins.tools import accumulate_error, panic_type_error
14
15
  from ramifice.utils import translations
15
- from ramifice.utils.tools import to_human_size
16
16
 
17
17
 
18
18
  class ImgGroupMixin:
ramifice/paladins/save.py CHANGED
@@ -10,6 +10,7 @@ from pymongo.asynchronous.collection import AsyncCollection
10
10
 
11
11
  from ramifice.paladins.tools import ignored_fields_to_none, refresh_from_mongo_doc
12
12
  from ramifice.utils import constants
13
+ from ramifice.utils.constants import UTC_TIMEZONE
13
14
  from ramifice.utils.errors import PanicError
14
15
 
15
16
  logger = logging.getLogger(__name__)
@@ -46,7 +47,7 @@ class SaveMixin:
46
47
  # Create or update a document in database.
47
48
  if result_check["is_update"]:
48
49
  # Update date and time.
49
- checked_data["updated_at"] = datetime.now() # noqa: DTZ005
50
+ checked_data["updated_at"] = datetime.now(UTC_TIMEZONE)
50
51
  # Run hook.
51
52
  await self.pre_update()
52
53
  # Update doc.
@@ -66,7 +67,7 @@ class SaveMixin:
66
67
  refresh_from_mongo_doc(self, mongo_doc)
67
68
  else:
68
69
  # Add date and time.
69
- today = datetime.now() # noqa: DTZ005
70
+ today = datetime.now(UTC_TIMEZONE)
70
71
  checked_data["created_at"] = today
71
72
  checked_data["updated_at"] = today
72
73
  # Run hook.
@@ -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"])) # noqa: T201
35
- print(colored("Model: ", "blue", attrs=["bold"]), end="") # noqa: T201
36
- print(colored(f"`{self.full_model_name()}`", "blue")) # noqa: T201
34
+ print(colored("\nERRORS:", "red", attrs=["bold"]))
35
+ print(colored("Model: ", "blue", attrs=["bold"]), end="")
36
+ print(colored(f"`{self.full_model_name()}`", "blue"))
37
37
  is_err = True
38
38
  # field name
39
- print(colored("Field: ", "green", attrs=["bold"]), end="") # noqa: T201
40
- print(colored(f"`{field_name}`:", "green")) # noqa: T201
39
+ print(colored("Field: ", "green", attrs=["bold"]), end="")
40
+ print(colored(f"`{field_name}`:", "green"))
41
41
  # error messages
42
- print(colored("\n".join(field_data.errors), "red")) # noqa: T201
42
+ print(colored("\n".join(field_data.errors), "red"))
43
43
  if len(self._id.alerts) > 0:
44
44
  # title
45
- print(colored("AlERTS:", "yellow", attrs=["bold"])) # noqa: T201
45
+ print(colored("AlERTS:", "yellow", attrs=["bold"]))
46
46
  # messages
47
- print(colored("\n".join(self._id.alerts), "yellow"), end="\n\n") # noqa: T201
47
+ print(colored("\n".join(self._id.alerts), "yellow"), end="\n\n")
48
48
  else:
49
- print(end="\n\n") # noqa: T201
49
+ print(end="\n\n")
@@ -11,6 +11,7 @@ List of variables:
11
11
  - `MEDIA_URL` - URL that handles the media served from MEDIA_ROOT, used for managing stored files.
12
12
  - `STATIC_ROOT` - The absolute path to the directory where static files are located.
13
13
  - `STATIC_URL` - URL to use when referring to static files located in STATIC_ROOT.
14
+ - `UTC_TIMEZONE` - Caching a patterns of regular expression.
14
15
  - `REGEX` - Caching a patterns of regular expression.
15
16
  """
16
17
 
@@ -24,11 +25,13 @@ __all__ = (
24
25
  "MEDIA_URL",
25
26
  "STATIC_ROOT",
26
27
  "STATIC_URL",
28
+ "UTC_TIMEZONE",
27
29
  "REGEX",
28
30
  )
29
31
 
30
32
  import re
31
33
 
34
+ import pytz
32
35
  from pymongo import AsyncMongoClient
33
36
  from pymongo.asynchronous.database import AsyncDatabase
34
37
 
@@ -57,6 +60,8 @@ STATIC_ROOT: str = "public/static"
57
60
  # URL to use when referring to
58
61
  # static files located in STATIC_ROOT.
59
62
  STATIC_URL: str = "/static"
63
+ # Caching a UTC timezone object.
64
+ UTC_TIMEZONE = pytz.timezone("UTC")
60
65
  # Caching a patterns of regular expression.
61
66
  REGEX: dict[str, re.Pattern] = {
62
67
  "database_name": re.compile(r"^[a-zA-Z][-_a-zA-Z0-9]{0,59}$"),
@@ -14,6 +14,7 @@ from dateutil.parser import parse
14
14
  from pymongo.asynchronous.collection import AsyncCollection
15
15
  from termcolor import colored
16
16
 
17
+ from ramifice.utils.constants import UTC_TIMEZONE
17
18
  from ramifice.utils.errors import PanicError
18
19
 
19
20
  logger = logging.getLogger(__name__)
@@ -71,8 +72,8 @@ async def apply_fixture(
71
72
  # If the check fails.
72
73
  if not result_check["is_valid"]:
73
74
  await collection.database.drop_collection(collection.name)
74
- print(colored("\nFIXTURE:", "red", attrs=["bold"])) # noqa: T201
75
- print(colored(fixture_path, "blue", attrs=["bold"])) # noqa: T201
75
+ print(colored("\nFIXTURE:", "red", attrs=["bold"]))
76
+ print(colored(fixture_path, "blue", attrs=["bold"]))
76
77
  inst_model.print_err()
77
78
  msg = f"Fixture `{fixture_name}` failed."
78
79
  logger.critical(msg)
@@ -80,7 +81,7 @@ async def apply_fixture(
80
81
  # Get data for document.
81
82
  checked_data: dict[str, Any] = result_check["data"]
82
83
  # Add date and time.
83
- today = datetime.now() # noqa: DTZ005
84
+ today = datetime.now(UTC_TIMEZONE)
84
85
  checked_data["created_at"] = today
85
86
  checked_data["updated_at"] = today
86
87
  # Run hook.
@@ -16,7 +16,12 @@ from termcolor import colored
16
16
 
17
17
  from ramifice.models.model import Model
18
18
  from ramifice.utils import constants
19
- from ramifice.utils.errors import DoesNotMatchRegexError, NoModelsForMigrationError, PanicError
19
+ from ramifice.utils.constants import UTC_TIMEZONE
20
+ from ramifice.utils.errors import (
21
+ DoesNotMatchRegexError,
22
+ NoModelsForMigrationError,
23
+ PanicError,
24
+ )
20
25
  from ramifice.utils.fixtures import apply_fixture
21
26
 
22
27
  logger = logging.getLogger(__name__)
@@ -166,7 +171,7 @@ class Migration:
166
171
  is_migration_process=True,
167
172
  )
168
173
  if not result_check["is_valid"]:
169
- print(colored("\n!!!>>MIGRATION<<!!!", "red", attrs=["bold"])) # noqa: T201
174
+ print(colored("\n!!!>>MIGRATION<<!!!", "red", attrs=["bold"]))
170
175
  inst_model.print_err()
171
176
  msg: str = "Migration failed."
172
177
  logger.critical(msg)
@@ -181,7 +186,7 @@ class Migration:
181
186
  ):
182
187
  checked_data[field_name] = mongo_doc[field_name]
183
188
  # Update date and time.
184
- checked_data["updated_at"] = datetime.now() # noqa: DTZ005
189
+ checked_data["updated_at"] = datetime.now(UTC_TIMEZONE)
185
190
  # Update the document in the database.
186
191
  await model_collection.replace_one(
187
192
  filter={"_id": checked_data["_id"]},
ramifice/utils/tools.py CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  __all__ = (
4
4
  "is_password",
5
- "to_human_size",
6
5
  "get_file_size",
7
6
  "normal_email",
8
7
  "is_email",
@@ -15,7 +14,6 @@ __all__ = (
15
14
  )
16
15
 
17
16
  import ipaddress
18
- import math
19
17
  from asyncio import to_thread
20
18
  from os.path import getsize
21
19
  from typing import Any
@@ -35,14 +33,6 @@ def is_password(password: str | None) -> bool:
35
33
  return True
36
34
 
37
35
 
38
- def to_human_size(size: int) -> str:
39
- """Convert number of bytes to readable format."""
40
- idx = int(math.floor(math.log(size) / math.log(1024))) # noqa: RUF046
41
- size = size if size < 1024 else abs(round(size / pow(1024, idx), 2))
42
- order = ["bytes", "KB", "MB", "GB", "TB"][idx]
43
- return f"{size} {order}"
44
-
45
-
46
36
  async def get_file_size(path: str) -> int:
47
37
  """Get file size in bytes."""
48
38
  size: int = await to_thread(getsize, path)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ramifice
3
- Version: 0.8.29
3
+ Version: 0.8.31
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/
@@ -33,6 +33,7 @@ Requires-Dist: pillow>=11.2.1
33
33
  Requires-Dist: pymongo>=4.13.0
34
34
  Requires-Dist: python-dateutil>=2.9.0.post0
35
35
  Requires-Dist: python-slugify>=8.0.4
36
+ Requires-Dist: pytz>=2025.2
36
37
  Requires-Dist: pyyaml>=6.0.2
37
38
  Requires-Dist: termcolor>=3.1.0
38
39
  Requires-Dist: xloft>=0.1.6
@@ -1,4 +1,4 @@
1
- ramifice/__init__.py,sha256=XdLGeKCFqIVRyaj4M_dpdVvQ8Kx8rL3FtyuR08Ehnc4,1590
1
+ ramifice/__init__.py,sha256=Nikv9qaOVLEwtxWIKB9rS6v1SPLgkM2DqQ9PtOlt-x0,1557
2
2
  ramifice/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  ramifice/commons/__init__.py,sha256=HwOckqlNkt4OzFbYqnLw9x0VXLbwO_mJaJ9MLYgSvtI,545
4
4
  ramifice/commons/general.py,sha256=ZryiRH-qf_cH9HCul7EP11UU-k4YO_rp_kku2FWAwj4,5433
@@ -25,10 +25,10 @@ ramifice/fields/color_field.py,sha256=Q1ZezPW6Jl-9olKCx47pMdHTCauBY_lwoudxIhZpAg
25
25
  ramifice/fields/date_field.py,sha256=svJjb6KgsmpW4RO8y3Opkh2uFwwSVfzyeb7nd5tNXLs,6267
26
26
  ramifice/fields/date_time_field.py,sha256=jINGK1VrRt1boXmjJb6_WU7G7h_qnbUSolKNFOtVXFg,6324
27
27
  ramifice/fields/email_field.py,sha256=joReU6YV-ViewMiRVvHozVjIhXuPMwxA-cmqwR5kkHY,4389
28
- ramifice/fields/file_field.py,sha256=dAsOYXPjMNwC_t8jCyoNEwlRAsGEd9V_tiuix0qTukU,9476
28
+ ramifice/fields/file_field.py,sha256=06tN6MS1_dIlqZZjPzRmtiCu42Jt_MA5KneqidiAV28,9503
29
29
  ramifice/fields/float_field.py,sha256=0OjoR9nwDs-Isv_lJoAT_jtdKmnd7-MqltCUiCViups,5796
30
30
  ramifice/fields/id_field.py,sha256=36VroZIgCH6uKuYjjWTXIycZ06ZGy4reLX6FhMUphCI,4757
31
- ramifice/fields/image_field.py,sha256=dZOB8ctt-7KeB-ePDwgeIgpNP6tLfnxWBU_E5_6dApc,12855
31
+ ramifice/fields/image_field.py,sha256=hj7Zkxakqxhoj5C7bIzepuDEXcgyvyVE8REKWAU-NKo,12882
32
32
  ramifice/fields/integer_field.py,sha256=WKzmy-v2uLmIYlrTwcmuoUGfjWQhGD9wHukfQ0fUipk,5770
33
33
  ramifice/fields/ip_field.py,sha256=GjDo1g5PEolqb8_AcDqgE_BnTITqew2rZcqmEn3S5WA,4293
34
34
  ramifice/fields/password_field.py,sha256=lKELnyIjlAIJWeCR_3BCa0ZL5R0L73cf9zimigIgN3g,3902
@@ -54,30 +54,30 @@ ramifice/paladins/hooks.py,sha256=jTOcz5eb3WUpIy21h-CcnsISDDsTgDCWjitszcFxZFE,10
54
54
  ramifice/paladins/indexing.py,sha256=ep6iSUhnH70eaNASr0Kx3yeuRE_i9BEdVUUiJBo4hZE,363
55
55
  ramifice/paladins/password.py,sha256=7lZmsl-bBely5zlVz0aCYlC5yf8nHp1YswoFF4CZWBI,3297
56
56
  ramifice/paladins/refrash.py,sha256=oS-N1QVwQGwt5lSxS01bpM6ETGuMLV_RFt1u5v2uEds,1221
57
- ramifice/paladins/save.py,sha256=ahuPKo6qh9MHPXs_QNo9RbeBvN74uWtuI27k84gx5f4,3631
57
+ ramifice/paladins/save.py,sha256=Dh9-qtnn9pNlWMfoCocjGjwO6F1nri2UyZh1vEuEHtU,3674
58
58
  ramifice/paladins/tools.py,sha256=8rkWPGrVMJiYN97EZuX52nVFVfB6qa08avYT4v8ohLA,2918
59
- ramifice/paladins/validation.py,sha256=vJ55g4al-V_aGxFSrnXDwAxjJXWv00Z8ZGexFipRD1c,1890
59
+ ramifice/paladins/validation.py,sha256=3x8WUR0bTDkzJj41mEZyKc6brEmNukKpy0fc0NsniwQ,1764
60
60
  ramifice/paladins/groups/__init__.py,sha256=GdIBJaMKz7L8pBKMAA__a4m-p0g0_RlzCcvDLDMMiec,958
61
61
  ramifice/paladins/groups/bool_group.py,sha256=X8P4YDh02gNzxTo9rgeCnmnV88jApUPqPLYIkpf5vGg,841
62
62
  ramifice/paladins/groups/choice_group.py,sha256=NkD2sKqBkdUMHY36pFdvL4uQ-81LXByRHF_lhCEAI6Y,1848
63
63
  ramifice/paladins/groups/date_group.py,sha256=3i6U2mwFMxW8s5rRi7RtSr7my6a5Cdy5MRWe601hjGA,3780
64
- ramifice/paladins/groups/file_group.py,sha256=vDeW5JCqKHWa43LILcVWJSU1TG-CrwKXQZhchWsZgM8,2975
64
+ ramifice/paladins/groups/file_group.py,sha256=_BbAveMZiwII7ZkCdePUSHzdkz3jVsKP2Aiop7lfedI,2962
65
65
  ramifice/paladins/groups/id_group.py,sha256=9iurBTOuhG1_8Wmxc5piTMcUNxAW3H0ZavA1sW7uopY,1321
66
- ramifice/paladins/groups/img_group.py,sha256=xSrDYqviuMt7mxOZiO0jKll1WnVlWRaSynk7ZvdEJ4c,6131
66
+ ramifice/paladins/groups/img_group.py,sha256=5kmdkVnXKCeCiOnuO5T8Rq3U_R6gwXsHLYi7CtMfMfI,6116
67
67
  ramifice/paladins/groups/num_group.py,sha256=oiBqm9lFsyHBKZgxfWvcQUpePPIT_0TBGPVrt0ae57s,2285
68
68
  ramifice/paladins/groups/pass_group.py,sha256=54kvAyoUCEjujTw0Dh6oUrtv3RU80sWEem_b-3Ytv0k,1920
69
69
  ramifice/paladins/groups/slug_group.py,sha256=sf-9CebDLoCDsaxyPVJKMhi6D_tWFeg3ET8Qk5E8pU8,2505
70
70
  ramifice/paladins/groups/text_group.py,sha256=TWvUxFctwDtXSJQL_E4TvHX1Yh-cDx5MJLGLAJyC6Xc,4478
71
71
  ramifice/utils/__init__.py,sha256=lAD90nw2VfGSuf0SLjOkeFScBPmc48XFvecueAfq73w,468
72
- ramifice/utils/constants.py,sha256=zDVG2D8u0UMNl1Ik90PhZCdxjmK81uwqxosorersbXE,2630
72
+ ramifice/utils/constants.py,sha256=fWVOganZbNHcUB4CXzEd0fr2Ch1NgL9OkgBsF08IzSo,2797
73
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
74
+ ramifice/utils/fixtures.py,sha256=0WUy0srEHH3QQugZ2pFOQ9MhgqFp1M3N9gUq7DSSJvw,3393
75
+ ramifice/utils/migration.py,sha256=4XAmMfiCN3UV-NEQPKDjK_39yfkLFgorHsdIcdZcA0k,11370
76
76
  ramifice/utils/mixins.py,sha256=XSkxJllqsMxN7xcP_9kn3-GRS4a1l_QQpFOlD3e-tIM,1123
77
- ramifice/utils/tools.py,sha256=EKNJAV9Ch17IrmghLcu7-I69gDNkDSqPepG9GKU7WkA,3163
77
+ ramifice/utils/tools.py,sha256=d5S38ksia6avBpLzXM3e3fzmRUMd8gM43JGAzJ7Nh6w,2799
78
78
  ramifice/utils/translations.py,sha256=EWITTDd4uXukRubOchqGwNjmZWt5HxoxRgq_kKeGsR8,4646
79
79
  ramifice/utils/unit.py,sha256=fxeWGWh5GkI8E9lxsf80HOh-NihSrqEmIQAQlUKMIaE,2497
80
- ramifice-0.8.29.dist-info/METADATA,sha256=hfYwYXqfRfVsffnIR8v6hpZ7xrqOL83KMSYJ0ZHyy_s,21066
81
- ramifice-0.8.29.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
82
- ramifice-0.8.29.dist-info/licenses/LICENSE,sha256=LrEL0aTZx90HDwFUQCJutORiDjJL9AnuVvCtspXIqt4,1095
83
- ramifice-0.8.29.dist-info/RECORD,,
80
+ ramifice-0.8.31.dist-info/METADATA,sha256=72dzx-jP8VnFxA2e79IfZ5C8NFbpKvJFOh2J0TC6cYM,21094
81
+ ramifice-0.8.31.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
82
+ ramifice-0.8.31.dist-info/licenses/LICENSE,sha256=LrEL0aTZx90HDwFUQCJutORiDjJL9AnuVvCtspXIqt4,1095
83
+ ramifice-0.8.31.dist-info/RECORD,,