osbot-utils 1.68.0__py3-none-any.whl → 1.70.0__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.
@@ -14,7 +14,7 @@ from osbot_utils.helpers.Random_Guid import Random_Guid
14
14
  from osbot_utils.helpers.Random_Guid_Short import Random_Guid_Short
15
15
  from osbot_utils.helpers.Timestamp_Now import Timestamp_Now
16
16
  from osbot_utils.utils.Dev import pprint
17
- from osbot_utils.utils.Json import json_parse
17
+ from osbot_utils.utils.Json import json_parse, json_to_bytes, json_to_gz
18
18
  from osbot_utils.utils.Misc import list_set
19
19
  from osbot_utils.utils.Objects import default_value, value_type_matches_obj_annotation_for_attr, \
20
20
  raise_exception_on_obj_type_annotation_mismatch, obj_is_attribute_annotation_of_type, enum_from_value, \
@@ -54,22 +54,6 @@ immutable_types = (bool, int, float, complex, str, tuple, frozenset, bytes, None
54
54
  class Type_Safe:
55
55
 
56
56
  def __init__(self, **kwargs):
57
- """
58
- Initialize an instance of the derived class, strictly assigning provided keyword
59
- arguments to corresponding instance attributes.
60
-
61
- Parameters:
62
- **kwargs: Variable length keyword arguments.
63
-
64
- Raises:
65
- Exception: If a key from kwargs does not correspond to any attribute
66
- pre-defined in the class, an exception is raised to prevent
67
- setting an undefined attribute.
68
-
69
- """
70
- # if 'disable_type_safety' in kwargs: # special case
71
- # self.__type_safety__ = kwargs['disable_type_safety'] is False
72
- # del kwargs['disable_type_safety']
73
57
 
74
58
  for (key, value) in self.__cls_kwargs__().items(): # assign all default values to self
75
59
  if value is not None: # when the value is explicitly set to None on the class static vars, we can't check for type safety
@@ -230,9 +214,16 @@ class Type_Safe:
230
214
  # global methods added to any class that base classes this
231
215
  # todo: see if there should be a prefix on these methods, to make it easier to spot them
232
216
  # of if these are actually that useful that they should be added like this
217
+ def bytes(self):
218
+ return json_to_bytes(self.json())
219
+
220
+ def bytes_gz(self):
221
+ return json_to_gz(self.json())
222
+
233
223
  def json(self):
234
224
  return self.serialize_to_dict()
235
225
 
226
+
236
227
  def merge_with(self, target):
237
228
  original_attrs = {k: v for k, v in self.__dict__.items() if k not in target.__dict__} # Store the original attributes of self that should be retained.
238
229
  self.__dict__ = target.__dict__ # Set the target's __dict__ to self, now self and target share the same __dict__.
@@ -0,0 +1,9 @@
1
+ from osbot_utils.utils.Str import safe_id
2
+
3
+ class Safe_Id(str):
4
+ def __new__(cls, value):
5
+ sanitized_value = safe_id(value)
6
+ return str.__new__(cls, sanitized_value)
7
+
8
+ def __str__(self):
9
+ return self
@@ -1,9 +1,9 @@
1
- from osbot_utils.base_classes.Type_Safe import Type_Safe
2
- from osbot_utils.utils.Dev import pprint
3
- from osbot_utils.utils.Files import files_list, file_create_from_bytes, temp_file, parent_folder, parent_folder_create
4
- from osbot_utils.utils.Misc import random_text
5
- from osbot_utils.utils.Regex import list__match_regex, list__match_regexes
6
- from osbot_utils.utils.Zip import zip_bytes_empty, zip_bytes__files, zip_bytes__add_file, zip_bytes__add_files, \
1
+ from osbot_utils.base_classes.Type_Safe import Type_Safe
2
+ from osbot_utils.utils.Dev import pprint
3
+ from osbot_utils.utils.Files import files_list, file_create_from_bytes, temp_file, parent_folder, parent_folder_create
4
+ from osbot_utils.utils.Misc import random_text
5
+ from osbot_utils.utils.Regex import list__match_regex, list__match_regexes
6
+ from osbot_utils.utils.Zip import zip_bytes_empty, zip_bytes__files, zip_bytes__add_file, zip_bytes__add_files, \
7
7
  zip_bytes__replace_files, zip_bytes__replace_file, zip_bytes__file_list, zip_bytes__file, \
8
8
  zip_bytes__add_file__from_disk, zip_bytes__add_files__from_disk, zip_files, zip_file__files, zip_bytes__remove_files
9
9
 
osbot_utils/utils/Json.py CHANGED
@@ -5,6 +5,8 @@ from osbot_utils.utils.Misc import str_lines, str_md5, str_sha256
5
5
  from osbot_utils.utils.Files import file_create_gz, file_create, load_file_gz, file_contents, file_lines, file_lines_gz
6
6
  from osbot_utils.utils.Zip import str_to_gz, gz_to_str
7
7
 
8
+ def bytes_to_json_loads(data):
9
+ return json.loads(data.decode())
8
10
 
9
11
  def json_dumps(python_object, indent=4, pretty=True, sort_keys=False, default=str, raise_exception=False):
10
12
  if python_object:
@@ -135,6 +137,7 @@ class Json:
135
137
  def json_save_tmp_file(python_object, pretty=True):
136
138
  return Json.save_file(python_object=python_object, pretty=pretty, path=None)
137
139
 
140
+ bytes_to_json = bytes_to_json_loads
138
141
  file_create_json = Json.save_file_pretty
139
142
  file_contents_json = Json.load_file
140
143
 
@@ -158,6 +161,7 @@ json_md5 = Json.md5
158
161
  json_lines_loads = Json.loads_json_lines
159
162
  json_parse = Json.loads
160
163
  json_lines_parse = Json.loads_json_lines
164
+ json_to_bytes = json_dumps_to_bytes
161
165
  json_to_str = json_dumps
162
166
  json_round_trip = Json.round_trip
163
167
  json_save = Json.save_file
osbot_utils/utils/Str.py CHANGED
@@ -5,17 +5,18 @@ from osbot_utils.utils.Files import safe_file_name
5
5
 
6
6
  # todo: refactor this this class all str related methods (mainly from the Misc class)
7
7
 
8
- ANSI_ESCAPE_PATTERN = re.compile(r'\x1b\[[0-9;]*m')
8
+ REGEX__ANSI_ESCAPE_PATTERN = re.compile(r'\x1b\[[0-9;]*m')
9
+ REGEX__SAFE_ID_REGEX = re.compile(r'[^a-zA-Z0-9_-]')
9
10
 
10
11
  def ansi_text_visible_length(ansi_text):
11
12
  if type(ansi_text) is str:
12
- ansi_escape = re.compile(ANSI_ESCAPE_PATTERN) # This regex matches the escape sequences used for text formatting
13
+ ansi_escape = re.compile(REGEX__ANSI_ESCAPE_PATTERN) # This regex matches the escape sequences used for text formatting
13
14
  visible_text = ansi_escape.sub('', ansi_text) # Remove the escape sequences
14
15
  return len(visible_text) # Return the length of the remaining text
15
16
 
16
17
  def ansi_to_text(ansi_text: str):
17
18
  if type(ansi_text) is str:
18
- return ANSI_ESCAPE_PATTERN.sub('', ansi_text)
19
+ return REGEX__ANSI_ESCAPE_PATTERN.sub('', ansi_text)
19
20
 
20
21
  def ansis_to_texts(ansis_texts: list): # todo: find a better name for this method :)
21
22
  if type(ansis_texts) is list:
@@ -33,6 +34,23 @@ def strip_quotes(value: str): # Remove surrounding quo
33
34
  return value[1:-1]
34
35
  return value
35
36
 
37
+ def safe_id(value):
38
+ if value is None or value == "":
39
+ raise ValueError("Invalid ID: The ID must not be empty.")
40
+
41
+ if not isinstance(value, str):
42
+ value = str(value)
43
+
44
+ if len(value) > 36:
45
+ raise ValueError(f"Invalid ID: The ID must not exceed 36 characters (was {len(value)}).")
46
+
47
+ sanitized_value = REGEX__SAFE_ID_REGEX.sub('_', value)
48
+
49
+ if set(sanitized_value) == {'_'}:
50
+ raise ValueError("Invalid ID: The sanitized ID must not consist entirely of underscores.")
51
+
52
+ return sanitized_value
53
+
36
54
  def str_dedent(value, strip=True):
37
55
  result = textwrap.dedent(value)
38
56
  if strip:
@@ -54,6 +72,9 @@ def str_max_width(target, value):
54
72
  def str_safe(value):
55
73
  return safe_file_name(value)
56
74
 
75
+ def str_safe_id(value):
76
+ return safe_id(value)
77
+
57
78
  def str_starts_with(source, prefix):
58
79
  if source is None or prefix is None:
59
80
  return False
osbot_utils/utils/Zip.py CHANGED
@@ -4,10 +4,8 @@ import os
4
4
  import shutil
5
5
  import tarfile
6
6
  import zipfile
7
- from os.path import abspath
8
-
9
- from osbot_utils.utils.Misc import list_set
10
-
7
+ from os.path import abspath
8
+ from osbot_utils.utils.Misc import list_set
11
9
  from osbot_utils.utils.Files import temp_folder, folder_files, temp_file, is_file, file_copy, file_move, file_exists, \
12
10
  file_contents_as_bytes
13
11
 
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v1.68.0
1
+ v1.70.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: osbot_utils
3
- Version: 1.68.0
3
+ Version: 1.70.0
4
4
  Summary: OWASP Security Bot - Utils
5
5
  Home-page: https://github.com/owasp-sbot/OSBot-Utils
6
6
  License: MIT
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
23
23
 
24
24
  Powerful Python util methods and classes that simplify common apis and tasks.
25
25
 
26
- ![Current Release](https://img.shields.io/badge/release-v1.68.0-blue)
26
+ ![Current Release](https://img.shields.io/badge/release-v1.70.0-blue)
27
27
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
28
28
 
29
29
 
@@ -2,7 +2,7 @@ osbot_utils/__init__.py,sha256=DdJDmQc9zbQUlPVyTJOww6Ixrn9n4bD3ami5ItQfzJI,16
2
2
  osbot_utils/base_classes/Cache_Pickle.py,sha256=kPCwrgUbf_dEdxUz7vW1GuvIPwlNXxuRhb-H3AbSpII,5884
3
3
  osbot_utils/base_classes/Kwargs_To_Disk.py,sha256=HHoy05NC_w35WcT-OnSKoSIV_cLqaU9rdjH0_KNTM0E,1096
4
4
  osbot_utils/base_classes/Kwargs_To_Self.py,sha256=weFNsBfBNV9W_qBkN-IdBD4yYcJV_zgTxBRO-ZlcPS4,141
5
- osbot_utils/base_classes/Type_Safe.py,sha256=7gB1vNKkM-CNXTlFV_BCqX-HACsu7Lu4vEgenKYPRMY,18806
5
+ osbot_utils/base_classes/Type_Safe.py,sha256=2cQ5qxJV2Ow3YQCkm_VwK7LoVet3pLjfShdgsBUkFt4,18261
6
6
  osbot_utils/base_classes/Type_Safe__List.py,sha256=-80C9OhsK6iDR2dAG8yNLAZV0qg5x3faqvSUigFCMJw,517
7
7
  osbot_utils/base_classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  osbot_utils/context_managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -68,9 +68,10 @@ osbot_utils/helpers/Python_Audit.py,sha256=shpZlluJwqJBAlad6xN01FkgC1TsQ48RLvR5Z
68
68
  osbot_utils/helpers/Random_Guid.py,sha256=hBBcjetZMYgdagWbkS1j7AYAQ5k6JFbDpbPBi9gTj1A,373
69
69
  osbot_utils/helpers/Random_Guid_Short.py,sha256=YP_k5OLuYvXWGU2OEnQHk_OGViBQofTWKm3pUdQaJao,404
70
70
  osbot_utils/helpers/Random_Seed.py,sha256=14btja8LDN9cMGWaz4fCNcMRU_eyx49gas-_PQvHgy4,634
71
+ osbot_utils/helpers/Safe_Id.py,sha256=k9GbZ_0ZNTJ5LIWGiEk9Rd-zjo2OPudDn6u9cezWNOk,225
71
72
  osbot_utils/helpers/Timestamp_Now.py,sha256=Vmdsm-pgvxkkQ_Qj_9Watr8rXXSvc-aBxWMPFGQx8Z0,371
72
73
  osbot_utils/helpers/Type_Registry.py,sha256=Ajk3SyMSKDi2g9SJYUtTgg7PZkAgydaHcpbGuEN3S94,311
73
- osbot_utils/helpers/Zip_Bytes.py,sha256=d5hYXNOJkOaYa7h2CJ0Y3ojEuGTOvCxPuSic2quwMY4,4236
74
+ osbot_utils/helpers/Zip_Bytes.py,sha256=KB5zWfCf6ET4alNfqNrSp5DxZ3Jp9oDHpc6tK2iO_qg,4320
74
75
  osbot_utils/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
76
  osbot_utils/helpers/ast/Ast.py,sha256=lcPQOSxXI6zgmMnIVF9WM6ISqViWX-sq4d_UC0CDG8s,1155
76
77
  osbot_utils/helpers/ast/Ast_Base.py,sha256=5rHMupBlN_n6lOC31UnSW_lWqxqxaE31v0gn-t32OgQ,3708
@@ -289,7 +290,7 @@ osbot_utils/utils/Files.py,sha256=7fdqbfFyo6Ow5Repi_dZAzHqGb0XYh6tDALYAy42pBY,22
289
290
  osbot_utils/utils/Functions.py,sha256=0E6alPJ0fJpBiJgFOWooCOi265wSRyxxXAJ5CELBnso,3498
290
291
  osbot_utils/utils/Http.py,sha256=Cm_-b2EgxKoQJ47ThZp-dgHCdeGv4UcCNLfTOH94-7s,7790
291
292
  osbot_utils/utils/Int.py,sha256=PmlUdU4lSwf4gJdmTVdqclulkEp7KPCVUDO6AcISMF4,116
292
- osbot_utils/utils/Json.py,sha256=yIT2hUI23gYd24Uf3LCjqPNV67zS46rYZftcCM3jw-Q,6492
293
+ osbot_utils/utils/Json.py,sha256=8fpYFXzNPSrwYfXMt3eGKpe-lhxh1kEaCRae1X1943A,6662
293
294
  osbot_utils/utils/Json_Cache.py,sha256=mLPkkDZN-3ZVJiDvV1KBJXILtKkTZ4OepzOsDoBPhWg,2006
294
295
  osbot_utils/utils/Lists.py,sha256=tPz5x5s3sRO97WZ_nsxREBPC5cwaHrhgaYBhsrffTT8,5599
295
296
  osbot_utils/utils/Misc.py,sha256=4MkG2BE1VzZfV4KPzYZ4jVAoUwoA3pTTVPi609ldLGA,16961
@@ -299,14 +300,14 @@ osbot_utils/utils/Process.py,sha256=lr3CTiEkN3EiBx3ZmzYmTKlQoPdkgZBRjPulMxG-zdo,
299
300
  osbot_utils/utils/Python_Logger.py,sha256=tx8N6wRKL3RDHboDRKZn8SirSJdSAE9cACyJkxrThZ8,12792
300
301
  osbot_utils/utils/Regex.py,sha256=0ubgp8HKsS3PNe2H6XlzMIcUuV7jhga3VkQVDNOJWuA,866
301
302
  osbot_utils/utils/Status.py,sha256=Yq4s0TelXgn0i2QjCP9V8mP30GabXp_UL-jjM6Iwiw4,4305
302
- osbot_utils/utils/Str.py,sha256=kxdY8ROX4FdJtCaMTfOc8fK_xcDICprNkefHu2MMNU4,2585
303
+ osbot_utils/utils/Str.py,sha256=pHcPE3xZ0aBz35aXIW2hdA5WN6vhRqsNT8A-7MNNIY0,3252
303
304
  osbot_utils/utils/Threads.py,sha256=lnh4doZWYUIoWBZRU_780QPeAIKGDh7INuqmU8Fzmdc,3042
304
305
  osbot_utils/utils/Toml.py,sha256=-_Yv5T8ZhGGoDSSoNEdFhSsXiK_JPjGkPijm4JoeHSk,1669
305
306
  osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
306
- osbot_utils/utils/Zip.py,sha256=G6Hk_hDcm9yvWzhTKzhT0R_6f0NBIAchHqMxGb3kfh4,14037
307
+ osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
307
308
  osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
308
- osbot_utils/version,sha256=lOa1cqmJZag742z9JQnsjouTwB_HoLgro5epV0jmwxk,8
309
- osbot_utils-1.68.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
310
- osbot_utils-1.68.0.dist-info/METADATA,sha256=oWpZsCTtpvZQb53NbpSnbBpxkfy2gLzH0uTqf5ES0N8,1317
311
- osbot_utils-1.68.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
312
- osbot_utils-1.68.0.dist-info/RECORD,,
309
+ osbot_utils/version,sha256=WI_wFg4NBrE5c9MJt5exrOXrSfHGB8Bq2u9jyP_mFJ0,8
310
+ osbot_utils-1.70.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
311
+ osbot_utils-1.70.0.dist-info/METADATA,sha256=1IuNEeFqJOaJkhPGjdqafVMeccaKvSLuY6ZIBEp1rRE,1317
312
+ osbot_utils-1.70.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
313
+ osbot_utils-1.70.0.dist-info/RECORD,,