osbot-utils 2.83.0__py3-none-any.whl → 2.84.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.
@@ -0,0 +1,76 @@
1
+ from types import SimpleNamespace
2
+
3
+ __SKIP__ = object()
4
+ __MISSING__ = object()
5
+
6
+ class __(SimpleNamespace):
7
+ def __enter__(self) : return self
8
+ def __exit__(self, exc_type, exc_val, exc_tb): return False
9
+
10
+ def __contains__(self, item): # Allow 'subset in superset' syntax
11
+ return self.contains(item)
12
+
13
+ def __eq__(self, other): # Enhanced equality that handles SKIP markers for dynamic values
14
+ if not isinstance(other, __):
15
+ return super().__eq__(other)
16
+
17
+ for key in set(self.__dict__.keys()) | set(other.__dict__.keys()):
18
+ self_val = getattr(self, key, None)
19
+ other_val = getattr(other, key, None)
20
+
21
+ if self_val is __SKIP__ or other_val is __SKIP__: # Skip comparison if either value is a skip marker
22
+ continue
23
+
24
+ if isinstance(self_val, __) and isinstance(other_val, __): # Handle nested __ objects recursively
25
+ if self_val.__eq__(other_val) is False: # Explicit recursive comparison
26
+ return False
27
+ elif self_val != other_val:
28
+ return False
29
+ return True
30
+
31
+ def contains(self, other):
32
+ other_dict = getattr(other, '__dict__', other) if hasattr(other, '__dict__') else other if isinstance(other, dict) else None
33
+ if other_dict is None:
34
+ return False
35
+
36
+ for key, expected_value in other_dict.items():
37
+ if expected_value is __SKIP__: # Skip this field
38
+ continue
39
+ if not hasattr(self, key):
40
+ return False
41
+ actual_value = getattr(self, key)
42
+
43
+ if isinstance(expected_value, __) and isinstance(actual_value, __):
44
+ if not actual_value.contains(expected_value):
45
+ return False
46
+ elif actual_value != expected_value:
47
+ return False
48
+ return True
49
+
50
+ def diff(self, other): # Return differences between objects for better test failure messages
51
+ differences = {}
52
+ all_keys = set(self.__dict__.keys()) | set(other.__dict__.keys() if hasattr(other, '__dict__') else other.keys() if isinstance(other, dict) else [])
53
+
54
+ for key in all_keys:
55
+ self_val = getattr(self, key, __MISSING__)
56
+ other_val = getattr(other, key, __MISSING__) if hasattr(other, '__dict__') else other.get(key, __MISSING__) if isinstance(other, dict) else __MISSING__
57
+
58
+ if self_val != other_val:
59
+ differences[key] = {'actual': self_val, 'expected': other_val}
60
+
61
+ return differences if differences else None
62
+
63
+ def excluding(self, *fields): # Return copy without specified fields for comparison"
64
+ result = __(**self.__dict__)
65
+ for field in fields:
66
+ delattr(result, field) if hasattr(result, field) else None
67
+ return result
68
+
69
+ def merge(self, **updates): # Create new instance with updates, handling nested __ objects
70
+ result = __(**self.__dict__)
71
+ for key, value in updates.items():
72
+ if isinstance(value, __) and hasattr(result, key) and isinstance(getattr(result, key), __):
73
+ setattr(result, key, getattr(result, key).merge(**value.__dict__))
74
+ else:
75
+ setattr(result, key, value)
76
+ return result
@@ -1,10 +1,6 @@
1
- # todo add tests
2
- from types import SimpleNamespace
1
+ from types import SimpleNamespace
3
2
 
4
- class __(SimpleNamespace):
5
-
6
- def __enter__(self) : return self
7
- def __exit__(self, exc_type, exc_val, exc_tb): return False
3
+ from osbot_utils.testing.__ import __
8
4
 
9
5
  def base_classes(cls):
10
6
  if type(cls) is type:
osbot_utils/version CHANGED
@@ -1 +1 @@
1
- v2.83.0
1
+ v2.84.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: osbot_utils
3
- Version: 2.83.0
3
+ Version: 2.84.0
4
4
  Summary: OWASP Security Bot - Utils
5
5
  License: MIT
6
6
  Author: Dinis Cruz
@@ -21,7 +21,7 @@ Description-Content-Type: text/markdown
21
21
 
22
22
  # OSBot-Utils
23
23
 
24
- ![Current Release](https://img.shields.io/badge/release-v2.83.0-blue)
24
+ ![Current Release](https://img.shields.io/badge/release-v2.84.0-blue)
25
25
  ![Python](https://img.shields.io/badge/python-3.8+-green)
26
26
  ![Type-Safe](https://img.shields.io/badge/Type--Safe-✓-brightgreen)
27
27
  ![Caching](https://img.shields.io/badge/Caching-Built--In-orange)
@@ -340,6 +340,7 @@ osbot_utils/testing/Temp_Zip.py,sha256=gppbJchk4tw_bu-7Vt6iJS9mGxeCvNNMMDzeVKHqR
340
340
  osbot_utils/testing/Temp_Zip_In_Memory.py,sha256=ibDIWt3K4CX558PbkLbX3InHyWYZcwQwajFm1kAPW5U,3284
341
341
  osbot_utils/testing/Unit_Test.py,sha256=MReR_wDGbbXFDPz7cmuGflcTxRB6TBnO9mYqRpSq8Pk,1304
342
342
  osbot_utils/testing/Unzip_File.py,sha256=V5H97XO9rlvG5EYOSzAH4kTtAH1ohZ8R8ImvJh46ZNg,1177
343
+ osbot_utils/testing/__.py,sha256=7eKP4vgV7pPbk5bSSufdvAEXy2eYh5bq36Ez8eC2SoQ,3579
343
344
  osbot_utils/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
344
345
  osbot_utils/testing/performance/Performance_Measure__Session.py,sha256=CWce0vJAZH_PDbIgK5bNcNFr1qsB37FQJKd05K-63kk,9108
345
346
  osbot_utils/testing/performance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -457,7 +458,7 @@ osbot_utils/utils/Json.py,sha256=TvfDoXwOkWzWH-9KMnme5C7iFsMZOleAeue92qmkH6g,883
457
458
  osbot_utils/utils/Json_Cache.py,sha256=mLPkkDZN-3ZVJiDvV1KBJXILtKkTZ4OepzOsDoBPhWg,2006
458
459
  osbot_utils/utils/Lists.py,sha256=tPz5x5s3sRO97WZ_nsxREBPC5cwaHrhgaYBhsrffTT8,5599
459
460
  osbot_utils/utils/Misc.py,sha256=H_xexJgiTxB3jDeDiW8efGQbO0Zuy8MM0iQ7qXC92JI,17363
460
- osbot_utils/utils/Objects.py,sha256=iyQ6RojK87iQRoGbh1twNHHy7wSrAro_l4jduly9Do0,13706
461
+ osbot_utils/utils/Objects.py,sha256=ZgAwAI8DM8MhFe37WAr2Di5f9-ig3hgayMEinLCF5tc,13571
461
462
  osbot_utils/utils/Png.py,sha256=V1juGp6wkpPigMJ8HcxrPDIP4bSwu51oNkLI8YqP76Y,1172
462
463
  osbot_utils/utils/Process.py,sha256=lr3CTiEkN3EiBx3ZmzYmTKlQoPdkgZBRjPulMxG-zdo,2357
463
464
  osbot_utils/utils/Python_Logger.py,sha256=M9Oi62LxfnRSlCN8GhaiwiBINvcSdGy39FCWjyDD-Xg,12792
@@ -469,8 +470,8 @@ osbot_utils/utils/Toml.py,sha256=grjWkVPIMVkawJ499FVIJKxQp8FJ2wcsd0Z3YIR4drM,114
469
470
  osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
470
471
  osbot_utils/utils/Zip.py,sha256=mG42lgTY0tnm14T3P1-DSAIZKkTiYoO3odZ1aOUdc1I,14394
471
472
  osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
472
- osbot_utils/version,sha256=qwiNjSxD3OqsUSFY0ezoeNZIUfvD-vn0S4zNzFmoc50,8
473
- osbot_utils-2.83.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
474
- osbot_utils-2.83.0.dist-info/METADATA,sha256=sKYHVqnqbtD8rlM8ZOCZTXN5ddMjIOM1TtneLGfAlcg,7918
475
- osbot_utils-2.83.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
476
- osbot_utils-2.83.0.dist-info/RECORD,,
473
+ osbot_utils/version,sha256=ESwW1ZvlyVyIbR4QPkYcAvo5MLsWHFvHuLuDhW9Qi6I,8
474
+ osbot_utils-2.84.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
475
+ osbot_utils-2.84.0.dist-info/METADATA,sha256=CnE2-oGdX31QV4nRgKaiaHUOf9aG7xZrh-8Rz_vHutk,7918
476
+ osbot_utils-2.84.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
477
+ osbot_utils-2.84.0.dist-info/RECORD,,