orionis 0.436.0__py3-none-any.whl → 0.438.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.
Files changed (68) hide show
  1. orionis/console/contracts/kernel.py +16 -3
  2. orionis/console/dumper/contracts/dump.py +8 -9
  3. orionis/console/dynamic/progress_bar.py +21 -29
  4. orionis/console/output/console.py +12 -0
  5. orionis/container/context/manager.py +27 -17
  6. orionis/container/context/scope.py +8 -7
  7. orionis/container/contracts/service_provider.py +12 -8
  8. orionis/container/providers/service_provider.py +9 -16
  9. orionis/container/resolver/resolver.py +29 -22
  10. orionis/foundation/contracts/application.py +437 -47
  11. orionis/foundation/contracts/config.py +14 -6
  12. orionis/foundation/providers/console_provider.py +16 -15
  13. orionis/foundation/providers/dumper_provider.py +20 -8
  14. orionis/foundation/providers/logger_provider.py +19 -14
  15. orionis/foundation/providers/path_resolver_provider.py +17 -14
  16. orionis/foundation/providers/progress_bar_provider.py +15 -14
  17. orionis/foundation/providers/testing_provider.py +20 -14
  18. orionis/foundation/providers/workers_provider.py +19 -14
  19. orionis/metadata/framework.py +1 -1
  20. orionis/services/asynchrony/contracts/coroutines.py +1 -0
  21. orionis/services/asynchrony/coroutines.py +2 -0
  22. orionis/services/asynchrony/exceptions/exception.py +2 -0
  23. orionis/services/environment/core/dot_env.py +9 -0
  24. orionis/services/environment/dynamic/caster.py +31 -2
  25. orionis/services/environment/key/key_generator.py +1 -0
  26. orionis/services/environment/validators/key_name.py +1 -0
  27. orionis/services/environment/validators/types.py +5 -1
  28. orionis/services/introspection/abstract/contracts/reflection.py +188 -221
  29. orionis/services/introspection/abstract/reflection.py +311 -178
  30. orionis/services/introspection/callables/contracts/reflection.py +64 -21
  31. orionis/services/introspection/callables/reflection.py +98 -23
  32. orionis/services/introspection/concretes/reflection.py +278 -181
  33. orionis/services/introspection/dependencies/contracts/reflection.py +21 -18
  34. orionis/services/introspection/dependencies/entities/callable_dependencies.py +15 -16
  35. orionis/services/introspection/dependencies/entities/class_dependencies.py +24 -16
  36. orionis/services/introspection/dependencies/entities/known_dependencies.py +19 -13
  37. orionis/services/introspection/dependencies/entities/method_dependencies.py +22 -16
  38. orionis/services/introspection/dependencies/reflection.py +0 -3
  39. orionis/services/introspection/instances/reflection.py +16 -6
  40. orionis/services/log/contracts/log_service.py +4 -0
  41. orionis/services/log/handlers/filename.py +2 -0
  42. orionis/services/paths/contracts/resolver.py +0 -3
  43. orionis/services/paths/resolver.py +0 -3
  44. {orionis-0.436.0.dist-info → orionis-0.438.0.dist-info}/METADATA +1 -1
  45. {orionis-0.436.0.dist-info → orionis-0.438.0.dist-info}/RECORD +68 -67
  46. tests/container/core/__init__.py +0 -0
  47. tests/container/mocks/mock_complex_classes.py +502 -192
  48. tests/container/mocks/mock_simple_classes.py +72 -6
  49. tests/container/validators/test_is_valid_alias.py +1 -1
  50. tests/foundation/config/database/test_foundation_config_database.py +54 -28
  51. tests/foundation/config/filesystems/test_foundation_config_filesystems_aws.py +40 -22
  52. tests/foundation/config/filesystems/test_foundation_config_filesystems_public.py +75 -48
  53. tests/foundation/config/logging/test_foundation_config_logging_channels.py +49 -37
  54. tests/foundation/config/logging/test_foundation_config_logging_monthly.py +80 -42
  55. tests/foundation/config/logging/test_foundation_config_logging_stack.py +46 -22
  56. tests/foundation/config/root/test_foundation_config_root_paths.py +37 -44
  57. tests/foundation/config/session/test_foundation_config_session.py +65 -20
  58. tests/foundation/config/startup/test_foundation_config_startup.py +37 -33
  59. tests/services/introspection/dependencies/test_reflect_dependencies.py +77 -25
  60. tests/services/introspection/reflection/test_reflection_abstract.py +403 -47
  61. /orionis/services/introspection/concretes/contracts/{concrete.py → reflection.py} +0 -0
  62. {orionis-0.436.0.dist-info → orionis-0.438.0.dist-info}/WHEEL +0 -0
  63. {orionis-0.436.0.dist-info → orionis-0.438.0.dist-info}/licenses/LICENCE +0 -0
  64. {orionis-0.436.0.dist-info → orionis-0.438.0.dist-info}/top_level.txt +0 -0
  65. {orionis-0.436.0.dist-info → orionis-0.438.0.dist-info}/zip-safe +0 -0
  66. /tests/container/{test_container.py → core/test_container.py} +0 -0
  67. /tests/container/{test_singleton.py → core/test_singleton.py} +0 -0
  68. /tests/container/{test_thread_safety.py → core/test_thread_safety.py} +0 -0
@@ -13,54 +13,81 @@ from orionis.services.introspection.exceptions import (
13
13
  )
14
14
 
15
15
  class ReflectionAbstract(IReflectionAbstract):
16
+ """
17
+ A reflection utility class for introspecting abstract base classes (interfaces).
18
+
19
+ This class provides comprehensive introspection capabilities for abstract base classes,
20
+ allowing examination of their structure, methods, attributes, and metadata. It enforces
21
+ that the target class must be an abstract base class that directly inherits from abc.ABC.
22
+ """
16
23
 
17
24
  @staticmethod
18
25
  def isAbstractClass(abstract: Type) -> bool:
19
26
  """
20
- Checks if the provided object is an abstract base class (interface).
27
+ Determine if the provided object is an abstract base class.
21
28
 
22
29
  Parameters
23
30
  ----------
24
31
  abstract : Type
25
- The class to check.
32
+ The class object to check for abstract base class characteristics.
26
33
 
27
34
  Returns
28
35
  -------
29
36
  bool
30
- True if 'abstract' is an abstract base class, False otherwise.
37
+ True if the object is a class type with abstract methods that directly
38
+ inherits from abc.ABC, False otherwise.
31
39
  """
40
+ # Check if the object is a class, has abstract methods, and directly inherits from ABC
32
41
  return isinstance(abstract, type) and bool(getattr(abstract, '__abstractmethods__', False)) and ABC in abstract.__bases__
33
42
 
34
43
  @staticmethod
35
44
  def ensureIsAbstractClass(abstract: Type) -> bool:
36
45
  """
37
- Ensures that the provided object is an abstract base class (interface) and directly inherits from ABC.
46
+ Validate that the provided object is a valid abstract base class.
38
47
 
39
48
  Parameters
40
49
  ----------
41
50
  abstract : Type
42
- The class to check.
51
+ The class object to validate for abstract base class compliance.
52
+
53
+ Returns
54
+ -------
55
+ bool
56
+ True if validation passes successfully.
43
57
 
44
58
  Raises
45
59
  ------
46
60
  ReflectionTypeError
47
- If 'abstract' is not a class type, not an abstract base class, or does not directly inherit from ABC.
61
+ If the object is not a class type, lacks abstract methods, or does not
62
+ directly inherit from abc.ABC.
48
63
  """
64
+
65
+ # Check if the provided abstract is a class type, has abstract methods, and directly inherits from ABC
49
66
  if not isinstance(abstract, type):
50
67
  raise ReflectionTypeError(f"Expected a class type for 'abstract', got {type(abstract).__name__!r}")
51
68
  if not bool(getattr(abstract, '__abstractmethods__', False)):
52
69
  raise ReflectionTypeError(f"Provided class '{abstract.__name__}' is not an interface (abstract base class)")
53
70
  if ABC not in abstract.__bases__:
54
71
  raise ReflectionTypeError(f"Provided class '{abstract.__name__}' must directly inherit from abc.ABC")
72
+
73
+ # If all checks pass, return True
55
74
  return True
56
75
 
57
76
  def __init__(self, abstract: Type) -> None:
58
77
  """
59
- Initializes the ReflectionAbstract instance with the given abstract class.
60
- Args:
61
- abstract (Type): The abstract base class (interface) to be reflected.
62
- Raises:
63
- TypeError: If the provided abstract is not an abstract base class.
78
+ Initialize the ReflectionAbstract instance with an abstract base class.
79
+
80
+ Parameters
81
+ ----------
82
+ abstract : Type
83
+ The abstract base class to be used for reflection operations.
84
+ Must be a valid abstract base class that directly inherits from abc.ABC.
85
+
86
+ Raises
87
+ ------
88
+ ReflectionTypeError
89
+ If the provided class is not a valid abstract base class or does not
90
+ directly inherit from abc.ABC.
64
91
  """
65
92
 
66
93
  # Ensure the provided abstract is an abstract base class (interface)
@@ -71,141 +98,183 @@ class ReflectionAbstract(IReflectionAbstract):
71
98
 
72
99
  def getClass(self) -> Type:
73
100
  """
74
- Returns the class type that this reflection concrete is based on.
101
+ Get the class type associated with this reflection instance.
75
102
 
76
103
  Returns
77
104
  -------
78
105
  Type
79
- The class type provided during initialization.
106
+ The abstract base class type that was provided during initialization.
80
107
  """
108
+
109
+ # Return the abstract class type
81
110
  return self.__abstract
82
111
 
83
112
  def getClassName(self) -> str:
84
113
  """
85
- Returns the name of the class type.
114
+ Get the name of the reflected abstract class.
86
115
 
87
116
  Returns
88
117
  -------
89
118
  str
90
- The name of the class type.
119
+ The name of the abstract class provided during initialization.
91
120
  """
121
+
122
+ # Return the name of the abstract class
92
123
  return self.__abstract.__name__
93
124
 
94
125
  def getModuleName(self) -> str:
95
126
  """
96
- Returns the name of the module where the class is defined.
127
+ Get the module name where the reflected abstract class is defined.
97
128
 
98
129
  Returns
99
130
  -------
100
131
  str
101
- The name of the module.
132
+ The fully qualified module name containing the abstract class definition.
102
133
  """
134
+
135
+ # Return the module name of the abstract class
103
136
  return self.__abstract.__module__
104
137
 
105
138
  def getModuleWithClassName(self) -> str:
106
139
  """
107
- Returns the module name concatenated with the class name.
140
+ Get the fully qualified name of the abstract class including its module.
108
141
 
109
142
  Returns
110
143
  -------
111
144
  str
112
- The module name followed by the class name.
145
+ The complete module path and class name separated by a dot
146
+ (e.g., 'module.submodule.ClassName').
113
147
  """
148
+
149
+ # Return the fully qualified name of the class
114
150
  return f"{self.getModuleName()}.{self.getClassName()}"
115
151
 
116
152
  def getDocstring(self) -> str:
117
153
  """
118
- Returns the docstring of the class.
154
+ Retrieve the docstring of the reflected abstract class.
119
155
 
120
156
  Returns
121
157
  -------
122
158
  str or None
123
- The docstring of the class, or None if not defined.
159
+ The docstring of the abstract class if available, None otherwise.
124
160
  """
161
+
162
+ # Return the docstring of the abstract class
125
163
  return self.__abstract.__doc__ if self.__abstract.__doc__ else None
126
164
 
127
165
  def getBaseClasses(self) -> list:
128
166
  """
129
- Returns a list of base classes of the reflected class.
167
+ Get the base classes of the reflected abstract class.
130
168
 
131
169
  Returns
132
170
  -------
133
- list
134
- A list of base classes.
171
+ list of Type
172
+ List containing all direct base classes of the reflected abstract class.
135
173
  """
174
+
175
+ # Return the base classes of the abstract class
136
176
  return self.__abstract.__bases__
137
177
 
138
178
  def getSourceCode(self) -> str:
139
179
  """
140
- Returns the source code of the class.
180
+ Retrieve the complete source code of the reflected abstract class.
141
181
 
142
182
  Returns
143
183
  -------
144
184
  str
145
- The source code of the class.
185
+ The complete source code of the abstract class as a string.
146
186
 
147
187
  Raises
148
188
  ------
149
189
  ReflectionValueError
150
- If the source code cannot be retrieved.
190
+ If the source code cannot be retrieved due to file system errors
191
+ or other unexpected exceptions.
151
192
  """
193
+
194
+ # Attempt to get the source code of the abstract class
152
195
  try:
153
196
  return inspect.getsource(self.__abstract)
197
+
198
+ # Handle OSError if the source code cannot be retrieved
154
199
  except OSError as e:
155
200
  raise ReflectionValueError(f"Could not retrieve source code for '{self.__abstract.__name__}': {e}")
156
201
 
202
+ # Handle any other unexpected exceptions
203
+ except Exception as e:
204
+ raise ReflectionValueError(f"An unexpected error occurred while retrieving source code for '{self.__abstract.__name__}': {e}")
205
+
157
206
  def getFile(self) -> str:
158
207
  """
159
- Returns the file path where the class is defined.
208
+ Get the file path where the reflected abstract class is defined.
160
209
 
161
210
  Returns
162
211
  -------
163
212
  str
164
- The file path of the class definition.
213
+ The absolute file path containing the abstract class definition.
165
214
 
166
215
  Raises
167
216
  ------
168
217
  ReflectionValueError
169
- If the file path cannot be retrieved.
218
+ If the file path cannot be retrieved due to type errors or
219
+ other unexpected exceptions.
170
220
  """
221
+
222
+ # Attempt to get the file path of the abstract class
171
223
  try:
172
224
  return inspect.getfile(self.__abstract)
225
+
226
+ # Handle TypeError if the file path cannot be retrieved
173
227
  except TypeError as e:
174
228
  raise ReflectionValueError(f"Could not retrieve file for '{self.__abstract.__name__}': {e}")
175
229
 
230
+ # Handle any other unexpected exceptions
231
+ except Exception as e:
232
+ raise ReflectionValueError(f"An unexpected error occurred while retrieving file for '{self.__abstract.__name__}': {e}")
233
+
176
234
  def getAnnotations(self) -> dict:
177
235
  """
178
- Returns the type annotations of the class.
236
+ Get the type annotations defined on the reflected abstract class.
179
237
 
180
238
  Returns
181
239
  -------
182
240
  dict
183
- A dictionary of type annotations.
241
+ Dictionary mapping attribute names to their annotated types.
242
+ Private attribute names are normalized by removing name mangling prefixes.
184
243
  """
244
+
245
+ # Retrieve the annotations from the abstract class
185
246
  annotations = {}
247
+
248
+ # Iterate through the annotations and handle private attribute name mangling
186
249
  for k, v in getattr(self.__abstract, '__annotations__', {}).items():
250
+
251
+ # Handle private attribute name mangling for clarity
187
252
  annotations[str(k).replace(f"_{self.getClassName()}", "")] = v
253
+
254
+ # Return the annotations dictionary
188
255
  return annotations
189
256
 
190
257
  def hasAttribute(self, attribute: str) -> bool:
191
258
  """
192
- Checks if the class has a specific attribute.
259
+ Check if the reflected abstract class has a specific attribute.
193
260
 
194
261
  Parameters
195
262
  ----------
196
263
  attribute : str
197
- The name of the attribute to check.
264
+ Name of the attribute to check for existence.
198
265
 
199
266
  Returns
200
267
  -------
201
268
  bool
202
- True if the class has the specified attribute, False otherwise.
269
+ True if the attribute exists in the class, False otherwise.
203
270
  """
271
+
272
+ # Check if the attribute exists in the class attributes
204
273
  return attribute in self.getAttributes()
205
274
 
206
275
  def getAttribute(self, attribute: str):
207
276
  """
208
- Returns the value of a specific class attribute.
277
+ Retrieve the value of a specific class attribute.
209
278
 
210
279
  Parameters
211
280
  ----------
@@ -215,31 +284,42 @@ class ReflectionAbstract(IReflectionAbstract):
215
284
  Returns
216
285
  -------
217
286
  Any
218
- The value of the specified class attribute.
287
+ The value of the specified class attribute if it exists, None otherwise.
219
288
 
220
289
  Raises
221
290
  ------
222
291
  ReflectionValueError
223
292
  If the attribute does not exist or is not accessible.
224
293
  """
294
+
295
+ # Get all class attributes (excluding methods and properties)
225
296
  attrs = self.getAttributes()
297
+
298
+ # Retrieve the attribute value if it exists
226
299
  return attrs.get(attribute, None)
227
300
 
228
301
  def setAttribute(self, name: str, value) -> bool:
229
302
  """
230
- Set an attribute value.
303
+ Set the value of a class attribute.
231
304
 
232
305
  Parameters
233
306
  ----------
234
307
  name : str
235
- The attribute name
308
+ The name of the attribute to set. Must be a valid Python identifier
309
+ and not a reserved keyword.
236
310
  value : Any
237
- The value to set
311
+ The value to assign to the attribute. Must not be callable.
312
+
313
+ Returns
314
+ -------
315
+ bool
316
+ True if the attribute was successfully set.
238
317
 
239
318
  Raises
240
319
  ------
241
320
  ReflectionValueError
242
- If the attribute is read-only or invalid
321
+ If the attribute name is invalid, is a Python keyword, or if the
322
+ value is callable (use setMethod for callables).
243
323
  """
244
324
 
245
325
  # Ensure the name is a valid attr name with regular expression
@@ -258,49 +338,58 @@ class ReflectionAbstract(IReflectionAbstract):
258
338
  # Set the attribute on the class itself
259
339
  setattr(self.__abstract, name, value)
260
340
 
341
+ # Return True to indicate successful setting of the attribute
261
342
  return True
262
343
 
263
344
  def removeAttribute(self, name: str) -> bool:
264
345
  """
265
- Remove an attribute from the class.
346
+ Remove an attribute from the reflected abstract class.
266
347
 
267
348
  Parameters
268
349
  ----------
269
350
  name : str
270
351
  The name of the attribute to remove.
271
352
 
353
+ Returns
354
+ -------
355
+ bool
356
+ True if the attribute was successfully removed.
357
+
272
358
  Raises
273
359
  ------
274
360
  ReflectionValueError
275
361
  If the attribute does not exist or cannot be removed.
276
362
  """
363
+
364
+ # Check if the attribute exists in the class
277
365
  if not self.hasAttribute(name):
278
366
  raise ReflectionValueError(f"Attribute '{name}' does not exist in class '{self.getClassName()}'.")
279
367
 
280
- # Handle private attribute name mangling
368
+ # Handle private attribute name mangling for correct attribute resolution
281
369
  if name.startswith("__") and not name.endswith("__"):
282
370
  class_name = self.getClassName()
283
371
  name = f"_{class_name}{name}"
284
372
 
373
+ # Delete the attribute from the class itself
285
374
  delattr(self.__abstract, name)
286
375
 
376
+ # Return True to indicate successful removal
287
377
  return True
288
378
 
289
379
  def getAttributes(self) -> dict:
290
380
  """
291
- Returns a dictionary of all class attributes (not instance attributes).
292
-
293
- Parameters
294
- ----------
295
- None
381
+ Retrieve all class-level attributes from the reflected abstract class.
296
382
 
297
383
  Returns
298
384
  -------
299
385
  dict
300
- A dictionary where keys are the names of class attributes and values are their corresponding values.
301
- Only attributes that are not callable, not static/class methods, not properties, and do not start with
302
- underscores (including dunder, protected, or private) are included.
386
+ Dictionary containing all class attributes including public, protected,
387
+ private, and dunder attributes. Keys are attribute names and values are
388
+ their corresponding values. Excludes callable objects, static/class methods,
389
+ and properties.
303
390
  """
391
+
392
+ # Return a dictionary containing all class attributes
304
393
  return {
305
394
  **self.getPublicAttributes(),
306
395
  **self.getProtectedAttributes(),
@@ -310,117 +399,159 @@ class ReflectionAbstract(IReflectionAbstract):
310
399
 
311
400
  def getPublicAttributes(self) -> dict:
312
401
  """
313
- Returns a dictionary of public class attributes (not instance attributes).
314
-
315
- Parameters
316
- ----------
317
- None
402
+ Retrieve all public class-level attributes.
318
403
 
319
404
  Returns
320
405
  -------
321
406
  dict
322
- A dictionary where keys are the names of public class attributes and values are their corresponding values.
323
- Only attributes that are not callable, not static/class methods, not properties, and do not start with
324
- underscores (including dunder, protected, or private) are included.
407
+ Dictionary where keys are names of public class attributes and values
408
+ are their corresponding values. Includes only attributes that do not
409
+ start with underscores and are not callable, static methods, class
410
+ methods, or properties.
325
411
  """
412
+
413
+ # Get the class name for name mangling checks
326
414
  class_name = self.getClassName()
415
+
416
+ # Retrieve all attributes from the class
327
417
  attributes = self.__abstract.__dict__
418
+
419
+ # Initialize a dictionary to hold public attributes
328
420
  public = {}
329
421
 
330
422
  # Exclude dunder, protected, and private attributes
331
423
  for attr, value in attributes.items():
424
+
425
+ # Skip callables, static methods, class methods, and properties
332
426
  if callable(value) or isinstance(value, staticmethod) or isinstance(value, classmethod) or isinstance(value, property):
333
427
  continue
428
+
429
+ # Skip dunder attributes
334
430
  if attr.startswith("__") and attr.endswith("__"):
335
431
  continue
432
+
433
+ # Skip private attributes (name-mangled)
336
434
  if attr.startswith(f"_{class_name}"):
337
435
  continue
436
+
437
+ # Skip protected attributes (single underscore)
338
438
  if attr.startswith("_"):
339
439
  continue
440
+
441
+ # Set public attributes
340
442
  public[attr] = value
341
443
 
444
+ # Ensure the class name is not a keyword
342
445
  return public
343
446
 
344
447
  def getProtectedAttributes(self) -> dict:
345
448
  """
346
- Returns a dictionary of protected class attributes (not instance attributes).
347
-
348
- Parameters
349
- ----------
350
- None
449
+ Retrieve all protected class-level attributes.
351
450
 
352
451
  Returns
353
452
  -------
354
453
  dict
355
- A dictionary where keys are the names of protected class attributes and values are their corresponding values.
356
- Only attributes that are not callable, not static/class methods, not properties, and start with a single underscore
357
- (indicating protected visibility) are included.
454
+ Dictionary where keys are names of protected class attributes and values
455
+ are their corresponding values. Includes only attributes that start with
456
+ a single underscore (protected visibility) and are not callable, static
457
+ methods, class methods, or properties. Excludes dunder, public, and
458
+ private attributes.
358
459
  """
460
+
461
+ # Get the class name for name mangling checks
359
462
  class_name = self.getClassName()
463
+
464
+ # Retrieve all attributes from the class
360
465
  attributes = self.__abstract.__dict__
466
+
467
+ # Initialize a dictionary to hold protected attributes
361
468
  protected = {}
362
469
 
363
470
  # Exclude dunder, public, and private attributes
364
471
  for attr, value in attributes.items():
472
+
473
+ # Skip callables, static methods, class methods, and properties
365
474
  if callable(value) or isinstance(value, staticmethod) or isinstance(value, classmethod) or isinstance(value, property):
366
475
  continue
476
+
477
+ # Skip dunder attributes
367
478
  if attr.startswith("__") and attr.endswith("__"):
368
479
  continue
480
+
481
+ # Skip private attributes (name-mangled)
369
482
  if attr.startswith(f"_{class_name}"):
370
483
  continue
484
+
485
+ # Only include attributes that start with a single underscore (protected)
371
486
  if not attr.startswith("_"):
372
487
  continue
488
+
489
+ # Exclude internal abc attributes
373
490
  if attr.startswith("_abc_"):
374
491
  continue
492
+
493
+ # Set protected attributes
375
494
  protected[attr] = value
376
495
 
377
496
  return protected
378
497
 
379
498
  def getPrivateAttributes(self) -> dict:
380
499
  """
381
- Returns a dictionary of private class attributes (not instance attributes).
382
-
383
- Parameters
384
- ----------
385
- None
500
+ Retrieve all private class-level attributes.
386
501
 
387
502
  Returns
388
503
  -------
389
504
  dict
390
- A dictionary where keys are the names of private class attributes and values are their corresponding values.
391
- Only attributes that are not callable, not static/class methods, not properties, and start with double underscores
392
- (indicating private visibility) are included.
505
+ Dictionary where keys are names of private class attributes with name
506
+ mangling prefixes removed for clarity, and values are their corresponding
507
+ values. Includes only name-mangled attributes (starting with _ClassName)
508
+ that are not callable, static methods, class methods, or properties.
393
509
  """
510
+
511
+ # Get the class name for name mangling checks
394
512
  class_name = self.getClassName()
513
+
514
+ # Retrieve all attributes from the class
395
515
  attributes = self.__abstract.__dict__
516
+
517
+ # Initialize a dictionary to hold private attributes
396
518
  private = {}
397
519
 
398
- # Exclude dunder, public, and protected attributes
520
+ # Exclude callables, static methods, class methods, and properties
399
521
  for attr, value in attributes.items():
522
+
523
+ # If the attribute is callable, a static method, a class method, or a property, skip it
400
524
  if callable(value) or isinstance(value, staticmethod) or isinstance(value, classmethod) or isinstance(value, property):
401
525
  continue
526
+
527
+ # Include only name-mangled private attributes
402
528
  if attr.startswith(f"_{class_name}"):
403
529
  private[str(attr).replace(f"_{class_name}", "")] = value
404
530
 
531
+ # Return the dictionary of private attributes
405
532
  return private
406
533
 
407
534
  def getDunderAttributes(self) -> dict:
408
535
  """
409
- Returns a dictionary of dunder (double underscore) class attributes (not instance attributes).
410
-
411
- Parameters
412
- ----------
413
- None
536
+ Retrieve all dunder (double underscore) class-level attributes.
414
537
 
415
538
  Returns
416
539
  -------
417
540
  dict
418
- A dictionary where keys are the names of dunder class attributes and values are their corresponding values.
419
- Only attributes that are not callable, not static/class methods, not properties, and start with double underscores
420
- (indicating dunder visibility) are included.
541
+ Dictionary where keys are names of dunder (magic) class attributes and
542
+ values are their corresponding values. Includes only attributes that
543
+ start and end with double underscores and are not callable, static
544
+ methods, class methods, or properties. Excludes certain built-in
545
+ dunder attributes.
421
546
  """
547
+
548
+ # Retrieve all attributes from the class
422
549
  attributes = self.__abstract.__dict__
550
+
551
+ # Initialize a dictionary to hold dunder attributes
423
552
  dunder = {}
553
+
554
+ # List of built-in dunder attributes to exclude from the result
424
555
  exclude = [
425
556
  "__class__", "__delattr__", "__dir__", "__doc__", "__eq__", "__format__", "__ge__", "__getattribute__",
426
557
  "__gt__", "__hash__", "__init__", "__init_subclass__", "__le__", "__lt__", "__module__", "__ne__",
@@ -430,58 +561,67 @@ class ReflectionAbstract(IReflectionAbstract):
430
561
  "__abstractmethods__", "__code__", "__defaults__", "__kwdefaults__", "__closure__"
431
562
  ]
432
563
 
433
- # Exclude public, protected, and private attributes
564
+ # Iterate through all attributes and filter for dunder attributes
434
565
  for attr, value in attributes.items():
566
+
567
+ # Skip callables, static/class methods, properties, and non-dunder attributes
435
568
  if callable(value) or isinstance(value, staticmethod) or isinstance(value, classmethod) or isinstance(value, property) or not attr.startswith("__"):
436
569
  continue
570
+
571
+ # Skip excluded built-in dunder attributes
437
572
  if attr in exclude:
438
573
  continue
574
+
575
+ # Only include attributes that start and end with double underscores
439
576
  if attr.startswith("__") and attr.endswith("__"):
440
577
  dunder[attr] = value
441
578
 
579
+ # Return the dictionary of dunder attributes
442
580
  return dunder
443
581
 
444
582
  def getMagicAttributes(self) -> dict:
445
583
  """
446
- Returns a dictionary of magic (dunder) class attributes (not instance attributes).
447
-
448
- Parameters
449
- ----------
450
- None
584
+ Get a dictionary of magic (dunder) class attributes.
451
585
 
452
586
  Returns
453
587
  -------
454
588
  dict
455
- A dictionary where keys are the names of magic class attributes and values are their corresponding values.
456
- Only attributes that are not callable, not static/class methods, not properties, and start with double underscores
457
- (indicating magic visibility) are included.
589
+ Dictionary where keys are names of magic class attributes and values
590
+ are their corresponding values. Includes only attributes that start
591
+ with double underscores and are not callable, static methods, class
592
+ methods, or properties.
458
593
  """
459
594
  return self.getDunderAttributes()
460
595
 
461
596
  def hasMethod(self, name: str) -> bool:
462
597
  """
463
- Check if the instance has a specific method.
598
+ Check if the abstract class has a specific method.
464
599
 
465
600
  Parameters
466
601
  ----------
467
602
  name : str
468
- The method name to check
603
+ The method name to check for existence.
469
604
 
470
605
  Returns
471
606
  -------
472
607
  bool
473
- True if the method exists, False otherwise
608
+ True if the method exists in the class, False otherwise.
474
609
  """
475
610
  return name in self.getMethods()
476
611
 
477
612
  def removeMethod(self, name: str) -> bool:
478
613
  """
479
- Remove a method from the class.
614
+ Remove a method from the abstract class.
480
615
 
481
616
  Parameters
482
617
  ----------
483
618
  name : str
484
- The method name to remove
619
+ The method name to remove.
620
+
621
+ Returns
622
+ -------
623
+ bool
624
+ True if the method was successfully removed.
485
625
 
486
626
  Raises
487
627
  ------
@@ -504,17 +644,17 @@ class ReflectionAbstract(IReflectionAbstract):
504
644
 
505
645
  def getMethodSignature(self, name: str) -> inspect.Signature:
506
646
  """
507
- Get the signature of a method.
647
+ Get the signature of a method in the abstract class.
508
648
 
509
649
  Parameters
510
650
  ----------
511
651
  name : str
512
- The method name to get the signature for
652
+ The method name to get the signature for.
513
653
 
514
654
  Returns
515
655
  -------
516
- str
517
- The signature of the method
656
+ inspect.Signature
657
+ The signature object of the specified method.
518
658
 
519
659
  Raises
520
660
  ------
@@ -535,12 +675,13 @@ class ReflectionAbstract(IReflectionAbstract):
535
675
 
536
676
  def getMethods(self) -> List[str]:
537
677
  """
538
- Get all method names of the instance.
678
+ Get all method names from the abstract class.
539
679
 
540
680
  Returns
541
681
  -------
542
682
  List[str]
543
- List of method names
683
+ List containing all method names including public, protected, private,
684
+ static, and class methods.
544
685
  """
545
686
  return [
546
687
  *self.getPublicMethods(),
@@ -556,16 +697,14 @@ class ReflectionAbstract(IReflectionAbstract):
556
697
 
557
698
  def getPublicMethods(self) -> list:
558
699
  """
559
- Returns a list of public class methods (not instance methods).
560
-
561
- Parameters
562
- ----------
563
- None
700
+ Get all public class methods.
564
701
 
565
702
  Returns
566
703
  -------
567
- dict
568
- A list where each element is the name of a public class method.
704
+ list
705
+ List of public class method names. Excludes dunder, protected, private
706
+ methods and non-callable attributes like properties, static methods,
707
+ and class methods.
569
708
  """
570
709
  class_name = self.getClassName()
571
710
  attributes = self.__abstract.__dict__
@@ -586,12 +725,12 @@ class ReflectionAbstract(IReflectionAbstract):
586
725
 
587
726
  def getPublicSyncMethods(self) -> list:
588
727
  """
589
- Get all public synchronous method names of the class.
728
+ Get all public synchronous method names from the abstract class.
590
729
 
591
730
  Returns
592
731
  -------
593
732
  list
594
- List of public synchronous method names
733
+ List of public synchronous method names. Excludes asynchronous methods.
595
734
  """
596
735
  methods = self.getPublicMethods()
597
736
  sync_methods = []
@@ -602,12 +741,12 @@ class ReflectionAbstract(IReflectionAbstract):
602
741
 
603
742
  def getPublicAsyncMethods(self) -> list:
604
743
  """
605
- Get all public asynchronous method names of the class.
744
+ Get all public asynchronous method names from the abstract class.
606
745
 
607
746
  Returns
608
747
  -------
609
748
  list
610
- List of public asynchronous method names
749
+ List of public asynchronous method names. Includes only coroutine functions.
611
750
  """
612
751
  methods = self.getPublicMethods()
613
752
  async_methods = []
@@ -618,16 +757,14 @@ class ReflectionAbstract(IReflectionAbstract):
618
757
 
619
758
  def getProtectedMethods(self) -> list:
620
759
  """
621
- Returns a list of protected class methods (not instance methods).
622
-
623
- Parameters
624
- ----------
625
- None
760
+ Get all protected class methods.
626
761
 
627
762
  Returns
628
763
  -------
629
- dict
630
- A list where each element is the name of a protected class method.
764
+ list
765
+ List of protected class method names. Includes only methods that start
766
+ with a single underscore and are not static methods, class methods,
767
+ or properties.
631
768
  """
632
769
  class_name = self.getClassName()
633
770
  attributes = self.__abstract.__dict__
@@ -675,16 +812,14 @@ class ReflectionAbstract(IReflectionAbstract):
675
812
 
676
813
  def getPrivateMethods(self) -> list:
677
814
  """
678
- Returns a list of private class methods (not instance methods).
679
-
680
- Parameters
681
- ----------
682
- None
815
+ Get all private class methods.
683
816
 
684
817
  Returns
685
818
  -------
686
819
  list
687
- A list where each element is the name of a private class method.
820
+ List of private class method names with class name prefixes removed
821
+ for clarity. Includes only name-mangled methods that start with
822
+ _ClassName and are not static methods, class methods, or properties.
688
823
  """
689
824
  class_name = self.getClassName()
690
825
  attributes = self.__abstract.__dict__
@@ -732,16 +867,13 @@ class ReflectionAbstract(IReflectionAbstract):
732
867
 
733
868
  def getPublicClassMethods(self) -> list:
734
869
  """
735
- Returns a list of public class methods (not instance methods).
736
-
737
- Parameters
738
- ----------
739
- None
870
+ Get all public class methods from the abstract class.
740
871
 
741
872
  Returns
742
873
  -------
743
874
  list
744
- A list where each element is the name of a public class method.
875
+ List of public class method names. Includes only methods decorated
876
+ with @classmethod that do not start with underscores.
745
877
  """
746
878
  class_name = self.getClassName()
747
879
  attributes = self.__abstract.__dict__
@@ -908,16 +1040,13 @@ class ReflectionAbstract(IReflectionAbstract):
908
1040
 
909
1041
  def getPublicStaticMethods(self) -> list:
910
1042
  """
911
- Returns a list of public static methods of the class.
912
-
913
- Parameters
914
- ----------
915
- None
1043
+ Get all public static methods from the abstract class.
916
1044
 
917
1045
  Returns
918
1046
  -------
919
1047
  list
920
- A list where each element is the name of a public static method.
1048
+ List of public static method names. Includes only methods decorated
1049
+ with @staticmethod that do not start with underscores.
921
1050
  """
922
1051
  class_name = self.getClassName()
923
1052
  attributes = self.__abstract.__dict__
@@ -1084,16 +1213,14 @@ class ReflectionAbstract(IReflectionAbstract):
1084
1213
 
1085
1214
  def getDunderMethods(self) -> list:
1086
1215
  """
1087
- Returns a list of dunder (double underscore) methods of the class.
1088
-
1089
- Parameters
1090
- ----------
1091
- None
1216
+ Get all dunder (double underscore) methods from the abstract class.
1092
1217
 
1093
1218
  Returns
1094
1219
  -------
1095
1220
  list
1096
- A list where each element is the name of a dunder method.
1221
+ List of dunder method names. Includes only methods that start and
1222
+ end with double underscores and are callable, excluding certain
1223
+ built-in methods.
1097
1224
  """
1098
1225
  attributes = self.__abstract.__dict__
1099
1226
  dunder_methods = []
@@ -1109,27 +1236,23 @@ class ReflectionAbstract(IReflectionAbstract):
1109
1236
 
1110
1237
  def getMagicMethods(self) -> list:
1111
1238
  """
1112
- Returns a list of magic (dunder) methods of the class.
1113
-
1114
- Parameters
1115
- ----------
1116
- None
1239
+ Get all magic (dunder) methods from the abstract class.
1117
1240
 
1118
1241
  Returns
1119
1242
  -------
1120
1243
  list
1121
- A list where each element is the name of a magic method.
1244
+ List of magic method names. This is an alias for getDunderMethods().
1122
1245
  """
1123
1246
  return self.getDunderMethods()
1124
1247
 
1125
1248
  def getProperties(self) -> List:
1126
1249
  """
1127
- Get all properties of the instance.
1250
+ Get all properties from the abstract class.
1128
1251
 
1129
1252
  Returns
1130
1253
  -------
1131
- List[str]
1132
- List of property names
1254
+ List
1255
+ List of property names with name mangling prefixes removed for clarity.
1133
1256
  """
1134
1257
 
1135
1258
  properties = []
@@ -1141,12 +1264,14 @@ class ReflectionAbstract(IReflectionAbstract):
1141
1264
 
1142
1265
  def getPublicProperties(self) -> List:
1143
1266
  """
1144
- Get all public properties of the instance.
1267
+ Get all public properties from the abstract class.
1145
1268
 
1146
1269
  Returns
1147
1270
  -------
1148
- List:
1149
- List of public property names and their values
1271
+ List
1272
+ List of public property names with name mangling prefixes removed
1273
+ for clarity. Includes only properties that do not start with
1274
+ underscores.
1150
1275
  """
1151
1276
  properties = []
1152
1277
  cls_name = self.getClassName()
@@ -1158,12 +1283,13 @@ class ReflectionAbstract(IReflectionAbstract):
1158
1283
 
1159
1284
  def getProtectedProperties(self) -> List:
1160
1285
  """
1161
- Get all protected properties of the instance.
1286
+ Get all protected properties from the abstract class.
1162
1287
 
1163
1288
  Returns
1164
1289
  -------
1165
1290
  List
1166
- List of protected property names and their values
1291
+ List of protected property names. Includes only properties that start
1292
+ with a single underscore but are not name-mangled private properties.
1167
1293
  """
1168
1294
  properties = []
1169
1295
  for name, prop in self.__abstract.__dict__.items():
@@ -1174,12 +1300,14 @@ class ReflectionAbstract(IReflectionAbstract):
1174
1300
 
1175
1301
  def getPrivateProperties(self) -> List:
1176
1302
  """
1177
- Get all private properties of the instance.
1303
+ Get all private properties from the abstract class.
1178
1304
 
1179
1305
  Returns
1180
1306
  -------
1181
1307
  List
1182
- List of private property names and their values
1308
+ List of private property names with class name prefixes removed for
1309
+ clarity. Includes only name-mangled properties that start with
1310
+ _ClassName.
1183
1311
  """
1184
1312
  properties = []
1185
1313
  for name, prop in self.__abstract.__dict__.items():
@@ -1190,17 +1318,17 @@ class ReflectionAbstract(IReflectionAbstract):
1190
1318
 
1191
1319
  def getPropertySignature(self, name: str) -> inspect.Signature:
1192
1320
  """
1193
- Get the signature of a property.
1321
+ Get the signature of a property's getter method.
1194
1322
 
1195
1323
  Parameters
1196
1324
  ----------
1197
1325
  name : str
1198
- The property name to get the signature for
1326
+ The property name to get the signature for.
1199
1327
 
1200
1328
  Returns
1201
1329
  -------
1202
1330
  inspect.Signature
1203
- The signature of the property
1331
+ The signature of the property's getter method.
1204
1332
 
1205
1333
  Raises
1206
1334
  ------
@@ -1223,17 +1351,17 @@ class ReflectionAbstract(IReflectionAbstract):
1223
1351
 
1224
1352
  def getPropertyDocstring(self, name: str) -> str:
1225
1353
  """
1226
- Get the docstring of a property.
1354
+ Get the docstring of a property's getter method.
1227
1355
 
1228
1356
  Parameters
1229
1357
  ----------
1230
1358
  name : str
1231
- The property name to get the docstring for
1359
+ The property name to get the docstring for.
1232
1360
 
1233
1361
  Returns
1234
1362
  -------
1235
- str
1236
- The docstring of the property
1363
+ str or None
1364
+ The docstring of the property's getter method if available, None otherwise.
1237
1365
 
1238
1366
  Raises
1239
1367
  ------
@@ -1256,32 +1384,37 @@ class ReflectionAbstract(IReflectionAbstract):
1256
1384
 
1257
1385
  def getConstructorDependencies(self) -> ClassDependency:
1258
1386
  """
1259
- Get the resolved and unresolved dependencies from the constructor of the instance's class.
1387
+ Get the resolved and unresolved dependencies from the constructor.
1260
1388
 
1261
1389
  Returns
1262
1390
  -------
1263
1391
  ClassDependency
1264
- A structured representation of the constructor dependencies, containing:
1265
- - resolved: Dictionary of resolved dependencies with their names and values.
1266
- - unresolved: List of unresolved dependencies (parameter names without default values or annotations).
1392
+ A structured representation of the constructor dependencies containing
1393
+ resolved dependencies (with names and values) and unresolved dependencies
1394
+ (parameter names without default values or annotations).
1267
1395
  """
1268
1396
  return ReflectDependencies(self.__abstract).getConstructorDependencies()
1269
1397
 
1270
1398
  def getMethodDependencies(self, method_name: str) -> MethodDependency:
1271
1399
  """
1272
- Get the resolved and unresolved dependencies from a method of the instance's class.
1400
+ Get the resolved and unresolved dependencies from a specific method.
1273
1401
 
1274
1402
  Parameters
1275
1403
  ----------
1276
1404
  method_name : str
1277
- The name of the method to inspect
1405
+ The name of the method to inspect for dependencies.
1278
1406
 
1279
1407
  Returns
1280
1408
  -------
1281
1409
  MethodDependency
1282
- A structured representation of the method dependencies, containing:
1283
- - resolved: Dictionary of resolved dependencies with their names and values.
1284
- - unresolved: List of unresolved dependencies (parameter names without default values or annotations).
1410
+ A structured representation of the method dependencies containing
1411
+ resolved dependencies (with names and values) and unresolved dependencies
1412
+ (parameter names without default values or annotations).
1413
+
1414
+ Raises
1415
+ ------
1416
+ ReflectionAttributeError
1417
+ If the specified method does not exist on the abstract class.
1285
1418
  """
1286
1419
 
1287
1420
  # Ensure the method name is a valid identifier