pythagoras 0.24.2__py3-none-any.whl → 0.24.4__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.
Files changed (24) hide show
  1. pythagoras/.DS_Store +0 -0
  2. pythagoras/_010_basic_portals/__init__.py +0 -1
  3. pythagoras/_010_basic_portals/basic_portal_core_classes.py +2 -14
  4. pythagoras/_020_ordinary_code_portals/code_normalizer.py +37 -9
  5. pythagoras/_020_ordinary_code_portals/function_processing.py +58 -15
  6. pythagoras/_020_ordinary_code_portals/ordinary_decorator.py +14 -0
  7. pythagoras/_020_ordinary_code_portals/ordinary_portal_core_classes.py +196 -24
  8. pythagoras/_030_data_portals/data_portal_core_classes.py +74 -22
  9. pythagoras/_030_data_portals/ready_and_get.py +45 -4
  10. pythagoras/_030_data_portals/storable_decorator.py +18 -1
  11. pythagoras/_040_logging_code_portals/exception_processing_tracking.py +30 -2
  12. pythagoras/_040_logging_code_portals/execution_environment_summary.py +60 -24
  13. pythagoras/_040_logging_code_portals/kw_args.py +74 -12
  14. pythagoras/_040_logging_code_portals/logging_decorator.py +23 -1
  15. pythagoras/_040_logging_code_portals/logging_portal_core_classes.py +368 -15
  16. pythagoras/_040_logging_code_portals/notebook_checker.py +9 -1
  17. pythagoras/_040_logging_code_portals/uncaught_exceptions.py +40 -0
  18. pythagoras/_050_safe_code_portals/safe_decorator.py +27 -1
  19. pythagoras/_050_safe_code_portals/safe_portal_core_classes.py +87 -11
  20. pythagoras/_090_swarming_portals/swarming_portals.py +4 -6
  21. {pythagoras-0.24.2.dist-info → pythagoras-0.24.4.dist-info}/METADATA +3 -3
  22. {pythagoras-0.24.2.dist-info → pythagoras-0.24.4.dist-info}/RECORD +23 -24
  23. pythagoras/_010_basic_portals/not_picklable_class.py +0 -36
  24. {pythagoras-0.24.2.dist-info → pythagoras-0.24.4.dist-info}/WHEEL +0 -0
@@ -2,7 +2,15 @@
2
2
  _is_in_notebook: bool|None = None
3
3
 
4
4
  def is_executed_in_notebook() -> bool:
5
- """ Return True if running inside a Jupyter notebook. """
5
+ """Return whether code is running inside a Jupyter/IPython notebook.
6
+
7
+ Uses a lightweight heuristic: checks if IPython is present and whether the
8
+ current shell exposes the set_custom_exc attribute, which is specific to
9
+ IPython interactive environments (including Jupyter).
10
+
11
+ Returns:
12
+ bool: True if running inside a Jupyter/IPython notebook, False otherwise.
13
+ """
6
14
  global _is_in_notebook
7
15
  if _is_in_notebook is not None:
8
16
  return _is_in_notebook
@@ -16,6 +16,17 @@ from .._800_signatures_and_converters.random_signatures import (
16
16
 
17
17
 
18
18
  def pth_excepthook(exc_type, exc_value, trace_back) -> None:
19
+ """sys.excepthook replacement that logs uncaught exceptions.
20
+
21
+ Args:
22
+ exc_type: The exception class.
23
+ exc_value: The exception instance.
24
+ trace_back: Traceback object for the exception.
25
+
26
+ Side Effects:
27
+ - Records the exception in the active LoggingCodePortal's crash history.
28
+ - Calls the original sys.__excepthook__ after logging.
29
+ """
19
30
  if _exception_needs_to_be_processed(exc_type, exc_value, trace_back):
20
31
  exception_id = "app_"+ get_random_signature() + "_crash"
21
32
  event_body = add_execution_environment_summary(
@@ -30,6 +41,17 @@ def pth_excepthook(exc_type, exc_value, trace_back) -> None:
30
41
 
31
42
  def pth_excepthandler(_, exc_type, exc_value
32
43
  , trace_back, tb_offset=None) -> None:
44
+ """IPython custom exception handler that logs uncaught exceptions.
45
+
46
+ This signature matches IPython's set_custom_exc handler protocol.
47
+
48
+ Args:
49
+ _: Unused first parameter required by IPython.
50
+ exc_type: The exception class.
51
+ exc_value: The exception instance.
52
+ trace_back: Traceback object for the exception.
53
+ tb_offset: Optional traceback offset used by IPython. Unused.
54
+ """
33
55
  if _exception_needs_to_be_processed(exc_type, exc_value, trace_back):
34
56
  exception_id = "app_" + get_random_signature() + "_crash"
35
57
  event_body = add_execution_environment_summary(
@@ -45,6 +67,15 @@ _previous_excepthook = None
45
67
  _number_of_handlers_registrations = 0
46
68
 
47
69
  def register_systemwide_uncaught_exception_handlers() -> None:
70
+ """Install Pythagoras handlers for uncaught exceptions system-wide.
71
+
72
+ In standard Python, replaces sys.excepthook; in Jupyter/IPython,
73
+ registers a custom exception handler via IPython.set_custom_exc when
74
+ available. Multiple registrations are reference-counted and idempotent.
75
+
76
+ Returns:
77
+ None
78
+ """
48
79
  global _number_of_handlers_registrations, _previous_excepthook
49
80
  _number_of_handlers_registrations += 1
50
81
  if _number_of_handlers_registrations > 1:
@@ -64,6 +95,15 @@ def register_systemwide_uncaught_exception_handlers() -> None:
64
95
 
65
96
 
66
97
  def unregister_systemwide_uncaught_exception_handlers() -> None:
98
+ """Uninstall previously registered Pythagoras exception handlers.
99
+
100
+ Decrements the registration reference counter. When it reaches zero,
101
+ restores the previous sys.excepthook (if any) and removes the custom
102
+ IPython exception handler in notebook environments.
103
+
104
+ Returns:
105
+ None
106
+ """
67
107
  global _number_of_handlers_registrations, _previous_excepthook
68
108
  _number_of_handlers_registrations -= 1
69
109
  if _number_of_handlers_registrations > 0:
@@ -7,12 +7,29 @@ from .safe_portal_core_classes import SafeFn, SafeCodePortal
7
7
 
8
8
 
9
9
  class safe(logging):
10
- """A decorator that converts a Python function into a SafeFn object.
10
+ """Decorator that wraps a callable into a SafeFn for portal execution.
11
+
12
+ Usage:
13
+ @safe()
14
+ def my_fn(x: int) -> int:
15
+ return x + 1
16
+
17
+ Notes:
18
+ This decorator configures only logging-related behavior for now. Actual
19
+ safety/sandboxing is not yet implemented.
11
20
  """
12
21
 
13
22
  def __init__(self
14
23
  , excessive_logging: bool|None|Joker = KEEP_CURRENT
15
24
  , portal: SafeCodePortal | None = None):
25
+ """Create a safe decorator bound to an optional portal.
26
+
27
+ Args:
28
+ excessive_logging: Whether to enable verbose logging for wrapped
29
+ calls. KEEP_CURRENT inherits from current context.
30
+ portal: The SafeCodePortal to attach the resulting SafeFn to. If
31
+ None, the active portal (if any) may be used by lower layers.
32
+ """
16
33
  assert isinstance(portal, SafeCodePortal) or portal is None
17
34
  logging.__init__(self=self
18
35
  , portal=portal
@@ -20,6 +37,15 @@ class safe(logging):
20
37
 
21
38
 
22
39
  def __call__(self,fn:Callable)->SafeFn:
40
+ """Wrap a Python callable into a SafeFn.
41
+
42
+ Args:
43
+ fn: The function to wrap.
44
+
45
+ Returns:
46
+ SafeFn: The wrapped function that can be executed via a portal and
47
+ will record logging information.
48
+ """
23
49
  wrapper = SafeFn(fn
24
50
  , portal=self._portal
25
51
  , excessive_logging=self._excessive_logging)
@@ -13,20 +13,43 @@ It will be done soon by integrating https://pypi.org/project/RestrictedPython/
13
13
 
14
14
  from __future__ import annotations
15
15
 
16
- from typing import Callable
17
-
18
- # from parameterizable import register_parameterizable_class
19
- from persidict import PersiDict, Joker, KEEP_CURRENT
20
-
21
16
  from .._040_logging_code_portals.logging_portal_core_classes import *
22
17
 
23
18
 
24
19
  class SafeCodePortal(LoggingCodePortal):
20
+ """A portal that executes functions with logging under a "safe" contract.
21
+
22
+ Currently, SafeCodePortal inherits all behavior from LoggingCodePortal.
23
+ True sandboxing/isolation has not yet been implemented and will be
24
+ introduced in the future (see Notes).
25
+
26
+ Notes:
27
+ The actual safety guarantees (prohibiting access to external
28
+ filesystem, network, process state, etc.) are not yet enforced.
29
+ The plan is to integrate RestrictedPython to implement a proper
30
+ sandbox. Until then, SafeCodePortal behaves like LoggingCodePortal
31
+ but keeps the API intended for safe execution.
32
+ """
33
+
25
34
  def __init__(self
26
35
  , root_dict: PersiDict|str|None = None
27
36
  , p_consistency_checks: float|Joker = KEEP_CURRENT
28
37
  , excessive_logging: bool|Joker = KEEP_CURRENT
29
38
  ):
39
+ """Initialize a SafeCodePortal.
40
+
41
+ Args:
42
+ root_dict: Root persistent dictionary or its path used by the
43
+ underlying data portal for storing execution artifacts. If a
44
+ string is provided, it is treated as a path on disk. If None,
45
+ an in-memory structure may be used (depending on configuration).
46
+ p_consistency_checks: Probability in [0, 1] of running additional
47
+ consistency checks on persistent state mutations. Use
48
+ KEEP_CURRENT to inherit the active setting from parent context.
49
+ excessive_logging: Whether to enable verbose logging of execution
50
+ attempts, results, outputs and events. Use KEEP_CURRENT to
51
+ inherit the active setting from parent context.
52
+ """
30
53
  LoggingCodePortal.__init__(self
31
54
  , root_dict=root_dict
32
55
  , p_consistency_checks=p_consistency_checks
@@ -34,26 +57,60 @@ class SafeCodePortal(LoggingCodePortal):
34
57
 
35
58
 
36
59
  class SafeFnCallSignature(LoggingFnCallSignature):
37
- """A signature of a call to a safe function"""
60
+ """A signature object describing a call to a SafeFn.
61
+
62
+ This specialization only narrows the types returned by some accessors
63
+ (e.g., fn) to Safe* counterparts. All logging behavior and storage layout
64
+ are inherited from LoggingFnCallSignature.
65
+ """
38
66
  _fn_cache: SafeFn | None
39
67
 
40
68
  def __init__(self, fn: SafeFn, arguments: dict):
69
+ """Construct a signature for a specific SafeFn call.
70
+
71
+ Args:
72
+ fn: The safe function object to be called.
73
+ arguments: The keyword arguments to use for the call.
74
+ """
41
75
  assert isinstance(fn, SafeFn)
42
76
  assert isinstance(arguments, dict)
43
77
  super().__init__(fn, arguments)
44
78
 
45
79
  @property
46
80
  def fn(self) -> SafeFn:
47
- """Return the function object referenced by the signature."""
81
+ """Return the SafeFn referenced by this signature.
82
+
83
+ Returns:
84
+ SafeFn: The underlying safe function instance.
85
+ """
48
86
  return super().fn
49
87
 
50
88
 
51
89
  class SafeFn(LoggingFn):
90
+ """A function wrapper intended for safe execution within a portal.
91
+
92
+ SafeFn currently behaves like LoggingFn, adding only type-narrowed
93
+ accessors for convenience. Future versions will enforce sandboxed
94
+ execution (see Notes).
95
+
96
+ Notes:
97
+ No actual sandboxing is performed yet. Behavior equals LoggingFn.
98
+ """
99
+
52
100
  def __init__(self
53
101
  , fn: Callable|str
54
102
  , portal: LoggingCodePortal|None = None
55
103
  , excessive_logging: bool|Joker = KEEP_CURRENT
56
104
  ):
105
+ """Create a SafeFn wrapper.
106
+
107
+ Args:
108
+ fn: The Python callable to wrap or its import string.
109
+ portal: The portal to associate with this function. If None, the
110
+ active portal (if any) may be used by the underlying layers.
111
+ excessive_logging: Whether to enable verbose logging for this fn.
112
+ Use KEEP_CURRENT to inherit from the surrounding context.
113
+ """
57
114
  LoggingFn.__init__(self
58
115
  , fn = fn
59
116
  , portal=portal
@@ -61,23 +118,42 @@ class SafeFn(LoggingFn):
61
118
 
62
119
 
63
120
  def __getstate__(self):
64
- """This method is called when the object is pickled."""
121
+ """Return picklable state.
122
+
123
+ Returns:
124
+ dict: The state returned by the parent LoggingFn for pickling.
125
+ """
65
126
  state = super().__getstate__()
66
127
  return state
67
128
 
68
129
 
69
130
  def __setstate__(self, state):
70
- """This method is called when the object is unpickled."""
131
+ """Restore object state after unpickling.
132
+
133
+ Args:
134
+ state: The state previously produced by __getstate__.
135
+ """
71
136
  super().__setstate__(state)
72
137
 
73
138
 
74
139
  @property
75
140
  def portal(self) -> SafeCodePortal:
141
+ """Return the associated SafeCodePortal.
142
+
143
+ Returns:
144
+ SafeCodePortal: The portal that owns this function.
145
+ """
76
146
  return super().portal
77
147
 
78
148
 
79
149
  def get_signature(self, arguments:dict) -> SafeFnCallSignature:
80
- return SafeFnCallSignature(fn=self, arguments=arguments)
150
+ """Create a SafeFnCallSignature for a given call.
81
151
 
152
+ Args:
153
+ arguments: The keyword arguments for the call.
82
154
 
83
- # register_parameterizable_class(SafeCodePortal)
155
+ Returns:
156
+ SafeFnCallSignature: A typed call signature suitable for execution
157
+ and logging through the portal.
158
+ """
159
+ return SafeFnCallSignature(fn=self, arguments=arguments)
@@ -23,7 +23,7 @@ from parameterizable import (
23
23
  access_jsparams)
24
24
  from persidict import PersiDict, Joker, KEEP_CURRENT
25
25
 
26
- from parameterizable.json_processor import _Markers
26
+ from parameterizable import *
27
27
 
28
28
  from .. import VALIDATION_SUCCESSFUL
29
29
  from .._010_basic_portals import get_all_known_portals
@@ -212,10 +212,8 @@ class SwarmingPortal(PureCodePortal):
212
212
  del self._max_n_workers_cache
213
213
  super()._invalidate_cache()
214
214
 
215
- # parameterizable.register_parameterizable_class(SwarmingPortal)
216
215
 
217
-
218
- def _launch_many_background_workers(portal_init_jsparams:JsonSerializedParams) -> None:
216
+ def _launch_many_background_workers(portal_init_jsparams:JsonSerializedObject) -> None:
219
217
  """Launch many background worker processes."""
220
218
 
221
219
 
@@ -265,7 +263,7 @@ def _launch_many_background_workers(portal_init_jsparams:JsonSerializedParams) -
265
263
  list_of_all_workers = new_list_of_all_workers
266
264
 
267
265
 
268
- def _background_worker(portal_init_jsparams:JsonSerializedParams) -> None:
266
+ def _background_worker(portal_init_jsparams:JsonSerializedObject) -> None:
269
267
  """Background worker that keeps processing random execution requests."""
270
268
  portal = parameterizable.loadjs(portal_init_jsparams)
271
269
  assert isinstance(portal, SwarmingPortal)
@@ -283,7 +281,7 @@ def _background_worker(portal_init_jsparams:JsonSerializedParams) -> None:
283
281
  portal._randomly_delay_execution()
284
282
 
285
283
 
286
- def _process_random_execution_request(portal_init_jsparams:JsonSerializedParams):
284
+ def _process_random_execution_request(portal_init_jsparams:JsonSerializedObject):
287
285
  """Process one random execution request."""
288
286
  # portal = parameterizable.get_object_from_portable_params(
289
287
  # portal_init_params)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pythagoras
3
- Version: 0.24.2
3
+ Version: 0.24.4
4
4
  Summary: Planet-scale distributed computing in Python.
5
5
  Keywords: cloud,ML,AI,serverless,distributed,parallel,machine-learning,deep-learning,pythagoras
6
6
  Author: Volodymyr (Vlad) Pavlov
@@ -16,7 +16,6 @@ Classifier: Topic :: Scientific/Engineering
16
16
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
17
17
  Classifier: Topic :: Software Development :: Libraries
18
18
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
- Requires-Dist: persidict==0.104.1
20
19
  Requires-Dist: lz4
21
20
  Requires-Dist: joblib
22
21
  Requires-Dist: scikit-learn
@@ -27,11 +26,12 @@ Requires-Dist: autopep8
27
26
  Requires-Dist: deepdiff
28
27
  Requires-Dist: numpy
29
28
  Requires-Dist: pytest
29
+ Requires-Dist: persidict==0.104.2
30
30
  Requires-Dist: boto3
31
31
  Requires-Dist: moto
32
32
  Requires-Dist: uv
33
33
  Requires-Dist: nvidia-ml-py
34
- Requires-Dist: parameterizable==0.100.0
34
+ Requires-Dist: parameterizable==0.101.0
35
35
  Requires-Dist: persidict[aws] ; extra == 'aws'
36
36
  Requires-Dist: boto3 ; extra == 'aws'
37
37
  Requires-Dist: moto ; extra == 'aws'
@@ -1,32 +1,31 @@
1
- pythagoras/.DS_Store,sha256=QNNcLWt_ymcoqL6JxhBobOuDsh4y1v4N3tzxs_WL_a8,6148
2
- pythagoras/_010_basic_portals/__init__.py,sha256=ER0kV_th7hba4nXXjoP-joN-cqkUMoH4iRSCgKUP75Y,1703
3
- pythagoras/_010_basic_portals/basic_portal_core_classes.py,sha256=Uzg85PPfiOOYz4LSpMLYj1HKlurUGIUaIsD7ysNqczc,24407
1
+ pythagoras/.DS_Store,sha256=4fJ-j5kHYgNLz5ki6QI2jkwoTuthfKswojnfe4naJ8U,8196
2
+ pythagoras/_010_basic_portals/__init__.py,sha256=L6vahRANApOIIdzw3wuAIZtJRijepneOevXnlhrZmj4,1668
3
+ pythagoras/_010_basic_portals/basic_portal_core_classes.py,sha256=UcvgxajJdtb7bgNkhUrehjN6Hd39iCNFtVqeC71qYoU,23979
4
4
  pythagoras/_010_basic_portals/exceptions.py,sha256=CMtSyRb47YKZtANN-iCQBvvyYPKdKqomLygRE1fjSNk,1248
5
5
  pythagoras/_010_basic_portals/long_infoname.py,sha256=KXOmHfQ_5hdZNqfB3Cif2CQiZ3XI3UAOEXKl3DLLYF4,1366
6
- pythagoras/_010_basic_portals/not_picklable_class.py,sha256=hSU069pixbaRaV_TX0KDdy3kupB9GVqkzYwxU9DzEkE,1442
7
6
  pythagoras/_010_basic_portals/portal_tester.py,sha256=x6HiJ3GW9XWplnsT6Ob7QCy2J_JPgGpdaJ8QRyFH-e8,3353
8
7
  pythagoras/_010_basic_portals/post_init_metaclass.py,sha256=94FEVMCJBUReRb-fo2-LW8YWXUXw5lLLYlXMnlxHJuU,1495
9
8
  pythagoras/_020_ordinary_code_portals/__init__.py,sha256=p3kSqaQYj0xlhk9BwptFgA1USdTbfHkAB5Q9MH-ANI0,1295
10
- pythagoras/_020_ordinary_code_portals/code_normalizer.py,sha256=7L3P5AaZKS9IPqrIEv5UJc3HHDP48fw6EGQWXZcxQtM,5004
11
- pythagoras/_020_ordinary_code_portals/function_processing.py,sha256=rlhB0dpaUztv6SM2wlUdaUdETcV2pVUICYufVrQCRcc,3623
12
- pythagoras/_020_ordinary_code_portals/ordinary_decorator.py,sha256=J4qx03NEEgpYWvg4D8UkAL0PdtAt2sQyMN1op6LMFsA,1028
13
- pythagoras/_020_ordinary_code_portals/ordinary_portal_core_classes.py,sha256=bY2Hzy19lTezv96dSc1l5SsaGxNkMTOq8IsfnkdV1wY,9743
9
+ pythagoras/_020_ordinary_code_portals/code_normalizer.py,sha256=GJXvBX85W230OcwNAg8XXHAE4m39Q70piJ9g2jcIr4Q,6616
10
+ pythagoras/_020_ordinary_code_portals/function_processing.py,sha256=b9Y4vNf1KSRkpUfS9UmWj3N_CNuPDgUMXdnR3IeyAoM,5021
11
+ pythagoras/_020_ordinary_code_portals/ordinary_decorator.py,sha256=ETmy-HKRzCJfzTPOI-gelQT2tlJpVLRu4I85yv02vuo,1437
12
+ pythagoras/_020_ordinary_code_portals/ordinary_portal_core_classes.py,sha256=C5nobGkYZBi2IHc1Pjfxjx_8h_ajF3Sf9Jq3yxFIR68,15963
14
13
  pythagoras/_030_data_portals/__init__.py,sha256=f_F9DCmuVgPMgzwRjuNj6FI63S3oXu7lj3zU66Nw7Hc,1427
15
- pythagoras/_030_data_portals/data_portal_core_classes.py,sha256=CJmJD2uzZwDuk8lQEJbpWAtN25UF57tkKYTot_yZmfo,20418
16
- pythagoras/_030_data_portals/ready_and_get.py,sha256=UKiQHkLhdAdvEwP5BTdoAnp4XEs7HDGx6026M2eMuc0,2842
17
- pythagoras/_030_data_portals/storable_decorator.py,sha256=l8W3GhVmIscgjoCTGq3tmdehKGDLIVnFbTM-GW-1G4g,578
14
+ pythagoras/_030_data_portals/data_portal_core_classes.py,sha256=D_Zg-q15II7IwweEGdBAMhGt09DYN_v_G0XFb5K3WB4,22459
15
+ pythagoras/_030_data_portals/ready_and_get.py,sha256=lgkDygF4lFnZXcCvP5dmvzQX64wrZ8AnYJTI7v2ppng,4172
16
+ pythagoras/_030_data_portals/storable_decorator.py,sha256=u70K8J44NTlofc4HmKHtxxbwKdUkBz6BDsIWds4dALQ,1160
18
17
  pythagoras/_040_logging_code_portals/__init__.py,sha256=q2hVyOVgE-9Ru3ycilK98YS9Rat8tSc6erd7AtGxpaA,996
19
- pythagoras/_040_logging_code_portals/exception_processing_tracking.py,sha256=sU-FCayvppF6gafBRAKsJcMC0JMBcnCCiLzu3yFmxiA,778
20
- pythagoras/_040_logging_code_portals/execution_environment_summary.py,sha256=hTvTbadYAtisZ4H8rq-n_hsKPCS38jsSz8lw_A1DIqY,2268
21
- pythagoras/_040_logging_code_portals/kw_args.py,sha256=4EYpPrr2xCgFAarmdFRKlEvGhIHC9kk9kc-VPW4S-XA,2717
22
- pythagoras/_040_logging_code_portals/logging_decorator.py,sha256=079w2_Z5HhXFLrgyXQekjuOby9CdUgFUGRbRT5lpujU,891
23
- pythagoras/_040_logging_code_portals/logging_portal_core_classes.py,sha256=HOk5rRUn6Xtd1ERvxTOvlv3k3G6X9eSVoFePO-6A2lI,21972
24
- pythagoras/_040_logging_code_portals/notebook_checker.py,sha256=5lQJDIDzhRIRSmX1T88nAREMEMoDDFf0OIKcvTpnhzk,541
18
+ pythagoras/_040_logging_code_portals/exception_processing_tracking.py,sha256=DH1eeJAeVL6Fn-6sXBqx3Ocu2RXxVhLqdH1mvhM24VY,1850
19
+ pythagoras/_040_logging_code_portals/execution_environment_summary.py,sha256=-0ynNibGfRh3J1Sq-N9j7eN1FlGvetEBiW0L4K_qJ30,3813
20
+ pythagoras/_040_logging_code_portals/kw_args.py,sha256=j3Iao80gTBjPx6dk1Azd9D8pcdQ3QdfpkQtQq-4ATV0,4954
21
+ pythagoras/_040_logging_code_portals/logging_decorator.py,sha256=-BGduV2U5SJ40qW8afRCUMrzYv5Pf_CgB4HlSEGDmlA,1766
22
+ pythagoras/_040_logging_code_portals/logging_portal_core_classes.py,sha256=R--DuvPGKzEB4ojWrmmuVU2SezUBVrSXrmdFjnrf72g,34977
23
+ pythagoras/_040_logging_code_portals/notebook_checker.py,sha256=qO7zfMC20hM4tSxlqB7gy6WI4imWX4Xl7ojSwgeVu0A,871
25
24
  pythagoras/_040_logging_code_portals/output_capturer.py,sha256=ohCp6qqxL7IuJGfnFuCIgj5Oc4HmC8c7uZGE_uzWkZk,4216
26
- pythagoras/_040_logging_code_portals/uncaught_exceptions.py,sha256=B3bPvX5nnJJx4JjLSGdl1xXOBU2pqo3CP-MomJAfXaE,3121
25
+ pythagoras/_040_logging_code_portals/uncaught_exceptions.py,sha256=vQrY1mOYdAeKaCmCCY1MUy4xoXurQkfwQuDA43giPl0,4564
27
26
  pythagoras/_050_safe_code_portals/__init__.py,sha256=YR-V6W2WZ17SjqmTyY2xdY16xTVEEuLs2MddJj_WCZU,557
28
- pythagoras/_050_safe_code_portals/safe_decorator.py,sha256=ZTsIMmtb3eGAWSpwdMYXRmIyaJiqV6mdFbB_Mqng784,804
29
- pythagoras/_050_safe_code_portals/safe_portal_core_classes.py,sha256=G1jYgKaOzkzYxIBMvlLYKMPk2OOpK_SQzMQVsHfBJqY,2562
27
+ pythagoras/_050_safe_code_portals/safe_decorator.py,sha256=AYvX7-km2reRMZ55ndO_2IS2SfHbnpyFv79AVwGg7Po,1681
28
+ pythagoras/_050_safe_code_portals/safe_portal_core_classes.py,sha256=naY4R91N5bcCq8C_-YeBqhrr6UG8zkEQ5t8C3O8ytOw,5673
30
29
  pythagoras/_060_autonomous_code_portals/__init__.py,sha256=hnv_dxxRx8c7IDf1QgVYHfYoeVAz8oD9K0oWI_o9N20,1704
31
30
  pythagoras/_060_autonomous_code_portals/autonomous_decorators.py,sha256=diWX03jZaInc55jAg391ZRBh-St5exJRLDZiS7dqYvg,2895
32
31
  pythagoras/_060_autonomous_code_portals/autonomous_portal_core_classes.py,sha256=21JNwBgEoIHXwCrBPb_eN5vMaHTZ98LdFkHuaMHtkI0,6665
@@ -46,7 +45,7 @@ pythagoras/_080_pure_code_portals/pure_decorator.py,sha256=WHZQzmyxgCpALHrqfeiOM
46
45
  pythagoras/_080_pure_code_portals/recursion_pre_validator.py,sha256=n03ooGISJvuwNWteBN9t7CFFSLYAu86AHHFJVcywPqg,1865
47
46
  pythagoras/_090_swarming_portals/__init__.py,sha256=TuA17PftTBudptAblNtBlD46BqUiitksOtf3y01QKm0,514
48
47
  pythagoras/_090_swarming_portals/output_suppressor.py,sha256=ENRtQtK_-7A94lAqtUQsIWrvtcgKniEpaWcZZZrpfQM,611
49
- pythagoras/_090_swarming_portals/swarming_portals.py,sha256=ZZuzkAf4Ls9oZyg_yUbj3kEEmXGTPjTCevVh-w7AAkE,12784
48
+ pythagoras/_090_swarming_portals/swarming_portals.py,sha256=3d8sRniGdW_rKp2zKxdqoCvLA4Em1XW5xofhFtzDLf0,12696
50
49
  pythagoras/_100_top_level_API/__init__.py,sha256=s5LtwskY2nwkRPFKzP0PrCzQ1c9oScZO0kM9_bWLi3U,64
51
50
  pythagoras/_100_top_level_API/default_local_portal.py,sha256=SnykTpTXg1KuT1qwDnrAZ63lYshMy-0nNiUgoOVMxCs,339
52
51
  pythagoras/_100_top_level_API/top_level_API.py,sha256=S2NXW4bfL98o6Txn6NM0EeBb1nzwFtPSl-yWNevAQIE,906
@@ -60,6 +59,6 @@ pythagoras/_900_project_stats_collector/__init__.py,sha256=Eagt-BhPPtBGgpMywx2lk
60
59
  pythagoras/_900_project_stats_collector/project_analyzer.py,sha256=uhycFKjUIXEpYcZYnak3yn4JFhchl-oZ7wt6spFxhoY,3574
61
60
  pythagoras/__init__.py,sha256=TMPtJdSi_WShCpJnsVVdO48Wcvs78GMbUi5gHc1eMLw,1233
62
61
  pythagoras/core/__init__.py,sha256=cXtQ-Vbm8TqzazvkFws5cV3AEEYbEKzNXYeuHeLGFK0,328
63
- pythagoras-0.24.2.dist-info/WHEEL,sha256=X16MKk8bp2DRsAuyteHJ-9qOjzmnY0x1aj0P1ftqqWA,78
64
- pythagoras-0.24.2.dist-info/METADATA,sha256=F29Q0LJjaqiCRK0zXQfgwe8BliFOmx4RrNmAbVoWFLA,7467
65
- pythagoras-0.24.2.dist-info/RECORD,,
62
+ pythagoras-0.24.4.dist-info/WHEEL,sha256=X16MKk8bp2DRsAuyteHJ-9qOjzmnY0x1aj0P1ftqqWA,78
63
+ pythagoras-0.24.4.dist-info/METADATA,sha256=o7l1zf9TCe9tz4nhG5KtKVU_z4qI9QQV-h0IHSitI_g,7467
64
+ pythagoras-0.24.4.dist-info/RECORD,,
@@ -1,36 +0,0 @@
1
- class NotPicklable:
2
- """A mixin class that prevents objects from being pickled or unpickled.
3
-
4
- This class provides a mechanism to explicitly prevent instances from being
5
- serialized using Python's pickle module. Classes that inherit from this
6
- mixin will raise TypeError exceptions when pickle attempts to serialize
7
- or deserialize them.
8
-
9
- This is useful for objects that contain non-serializable resources or
10
- should not be persisted for security or architectural reasons.
11
- """
12
-
13
- def __getstate__(self):
14
- """Prevent object serialization by raising TypeError.
15
-
16
- This method is called by pickle when attempting to serialize the object.
17
- It unconditionally raises a TypeError to prevent pickling.
18
-
19
- Raises:
20
- TypeError: Always raised to prevent the object from being pickled.
21
- """
22
- raise TypeError(f"{type(self).__name__} cannot be pickled")
23
-
24
- def __setstate__(self, state):
25
- """Prevent object deserialization by raising TypeError.
26
-
27
- This method is called by pickle when attempting to deserialize the object.
28
- It unconditionally raises a TypeError to prevent unpickling.
29
-
30
- Args:
31
- state: The state dictionary that would be used for unpickling.
32
-
33
- Raises:
34
- TypeError: Always raised to prevent the object from being unpickled.
35
- """
36
- raise TypeError(f"{type(self).__name__} cannot be unpickled")