orionis 0.313.0__py3-none-any.whl → 0.314.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.
@@ -4,120 +4,497 @@ from orionis.container.exceptions.container_exception import OrionisContainerExc
4
4
  from orionis.container.exceptions.type_error_exception import OrionisContainerTypeError
5
5
  from orionis.services.introspection.abstract.reflection_abstract import ReflectionAbstract
6
6
  from orionis.services.introspection.concretes.reflection_concrete import ReflectionConcrete
7
-
7
+ from orionis.services.introspection.instances.reflection_instance import ReflectionInstance
8
+ from orionis.services.introspection.reflection import Reflection
8
9
 
9
10
  class Container:
10
11
 
11
- def bind(self, abstract: Callable[..., Any] = None, concrete: Callable[..., Any] = None, lifetime: str = Lifetime.TRANSIENT) -> None:
12
+ def __init__(self):
13
+ self.__transient = {}
14
+ self.__singleton = {}
15
+ self.__scoped = {}
16
+ self.__instance = {}
17
+
18
+ def __ensureAliasType(self, value: Any) -> None:
12
19
  """
13
- Binds an abstract type to a concrete implementation with a specified lifetime.
20
+ Ensures that the provided value is a valid alias of type str and does not contain invalid characters.
14
21
 
15
22
  Parameters
16
23
  ----------
17
- abstract : Callable[..., Any]
18
- The abstract base type or alias to be bound.
19
- concrete : Callable[..., Any]
20
- The concrete implementation to associate with the abstract type.
21
- lifetime : str, optional
22
- The lifetime of the service (default is 'transient').
24
+ value : Any
25
+ The value to check.
26
+
27
+ Raises
28
+ ------
29
+ OrionisContainerTypeError
30
+ If the value is not of type str or contains invalid characters.
31
+
32
+ Notes
33
+ -----
34
+ This method validates that a given value is a string and does not contain characters
35
+ that could cause errors when resolving dependencies (e.g., whitespace, special symbols).
23
36
  """
24
- pass
25
37
 
26
- def transient(self, abstract: Callable[..., Any], concrete: Callable[..., Any]) -> bool:
38
+ # Check if the value is a string
39
+ if not isinstance(value, str):
40
+ raise OrionisContainerTypeError(
41
+ f"Expected a string type for alias, but got {type(value).__name__} instead."
42
+ )
43
+
44
+ # Define a set of invalid characters for aliases
45
+ invalid_chars = set(' \t\n\r\x0b\x0c!@#$%^&*()[]{};:,/<>?\\|`~"\'')
46
+ if any(char in invalid_chars for char in value):
47
+ raise OrionisContainerTypeError(
48
+ f"Alias '{value}' contains invalid characters. "
49
+ "Aliases must not contain whitespace or special symbols."
50
+ )
51
+
52
+ def __ensureAbstractClass(self, abstract: Callable[..., Any], lifetime: str) -> None:
27
53
  """
28
- Registers a service with a transient lifetime.
54
+ Ensures that the provided abstract is an abstract class.
29
55
 
30
56
  Parameters
31
57
  ----------
32
58
  abstract : Callable[..., Any]
33
- The abstract base type or alias to be bound.
34
- concrete : Callable[..., Any]
35
- The concrete implementation to associate with the abstract type.
59
+ The class intended to represent the abstract type.
60
+ lifetime : str
61
+ The service lifetime descriptor, used for error messages.
62
+
63
+ Raises
64
+ ------
65
+ OrionisContainerTypeError
66
+ If the abstract class check fails.
36
67
  """
37
- # Ensure that abstract is an abstract class and concrete is a concrete class
38
68
  try:
39
69
  ReflectionAbstract.ensureIsAbstractClass(abstract)
70
+ except Exception as e:
71
+ raise OrionisContainerTypeError(
72
+ f"Unexpected error registering {lifetime} service: {e}"
73
+ ) from e
74
+
75
+ def __ensureConcreteClass(self, concrete: Callable[..., Any], lifetime: str) -> None:
76
+ """
77
+ Ensures that the provided concrete is a concrete (non-abstract) class.
78
+
79
+ Parameters
80
+ ----------
81
+ concrete : Callable[..., Any]
82
+ The class intended to represent the concrete implementation.
83
+ lifetime : str
84
+ The service lifetime descriptor, used for error messages.
85
+
86
+ Raises
87
+ ------
88
+ OrionisContainerTypeError
89
+ If the concrete class check fails.
90
+ """
91
+ try:
40
92
  ReflectionConcrete.ensureIsConcreteClass(concrete)
41
93
  except Exception as e:
42
94
  raise OrionisContainerTypeError(
43
- f"Unexpected error registering transient service: {e}"
95
+ f"Unexpected error registering {lifetime} service: {e}"
44
96
  ) from e
45
97
 
46
- # Ensure that concrete does NOT inherit from abstract
98
+ def __ensureIsSubclass(self, abstract: Callable[..., Any], concrete: Callable[..., Any]) -> None:
99
+ """
100
+ Validates that the concrete class is a subclass of the provided abstract class.
101
+
102
+ Parameters
103
+ ----------
104
+ abstract : Callable[..., Any]
105
+ The abstract base class or interface.
106
+ concrete : Callable[..., Any]
107
+ The concrete implementation class to check.
108
+
109
+ Raises
110
+ ------
111
+ OrionisContainerException
112
+ If the concrete class is NOT a subclass of the abstract class.
113
+
114
+ Notes
115
+ -----
116
+ This method ensures that the concrete implementation inherits from the abstract class,
117
+ which is required for proper dependency injection and interface enforcement.
118
+ """
119
+ if not issubclass(concrete, abstract):
120
+ raise OrionisContainerException(
121
+ "The concrete class must inherit from the provided abstract class. "
122
+ "Please ensure that the concrete class is a subclass of the specified abstract class."
123
+ )
124
+
125
+ def __ensureIsNotSubclass(self, abstract: Callable[..., Any], concrete: Callable[..., Any]) -> None:
126
+ """
127
+ Validates that the concrete class is NOT a subclass of the provided abstract class.
128
+
129
+ Parameters
130
+ ----------
131
+ abstract : Callable[..., Any]
132
+ The abstract base class or interface.
133
+ concrete : Callable[..., Any]
134
+ The concrete implementation class to check.
135
+
136
+ Raises
137
+ ------
138
+ OrionisContainerException
139
+ If the concrete class IS a subclass of the abstract class.
140
+
141
+ Notes
142
+ -----
143
+ This method ensures that the concrete implementation does NOT inherit from the abstract class.
144
+ """
47
145
  if issubclass(concrete, abstract):
48
146
  raise OrionisContainerException(
49
- "Cannot register a concrete class that is a subclass of the provided abstract class. "
50
- "Please ensure that the concrete class does not inherit from the specified abstract class."
147
+ "The concrete class must NOT inherit from the provided abstract class. "
148
+ "Please ensure that the concrete class is not a subclass of the specified abstract class."
149
+ )
150
+
151
+ def __ensureInstance(self, instance: Any) -> None:
152
+ """
153
+ Ensures that the provided object is a valid instance.
154
+
155
+ Parameters
156
+ ----------
157
+ instance : Any
158
+ The object to be validated as an instance.
159
+
160
+ Raises
161
+ ------
162
+ OrionisContainerTypeError
163
+ If the provided object is not a valid instance.
164
+
165
+ Notes
166
+ -----
167
+ This method uses ReflectionInstance to verify that the given object
168
+ is a proper instance (not a class or abstract type). If the check fails,
169
+ an OrionisContainerTypeError is raised with a descriptive message.
170
+ """
171
+ try:
172
+ ReflectionInstance.ensureIsInstance(instance)
173
+ except Exception as e:
174
+ raise OrionisContainerTypeError(
175
+ f"Error registering instance: {e}"
176
+ ) from e
177
+
178
+ def __ensureImplementation(self, *, abstract: Callable[..., Any] = None, concrete: Callable[..., Any] = None, instance: Any = None) -> None:
179
+ """
180
+ Ensures that a concrete class or instance implements all abstract methods defined in an abstract class.
181
+
182
+ Parameters
183
+ ----------
184
+ abstract : Callable[..., Any]
185
+ The abstract class containing abstract methods.
186
+ concrete : Callable[..., Any], optional
187
+ The concrete class that should implement the abstract methods.
188
+ instance : Any, optional
189
+ The instance that should implement the abstract methods.
190
+
191
+ Raises
192
+ ------
193
+ OrionisContainerException
194
+ If the concrete class or instance does not implement all abstract methods defined in the abstract class.
195
+
196
+ Notes
197
+ -----
198
+ This method checks that all abstract methods in the given abstract class are implemented
199
+ in the provided concrete class or instance. If any methods are missing, an exception is raised with
200
+ details about the missing implementations.
201
+ """
202
+ if abstract is None:
203
+ raise OrionisContainerException("Abstract class must be provided for implementation check.")
204
+
205
+ abstract_methods = getattr(abstract, '__abstractmethods__', set())
206
+ if not abstract_methods:
207
+ raise OrionisContainerException(
208
+ f"The abstract class '{abstract.__name__}' does not define any abstract methods. "
209
+ "An abstract class must have at least one abstract method."
51
210
  )
52
211
 
212
+ target = concrete if concrete is not None else instance
213
+ if target is None:
214
+ raise OrionisContainerException("Either concrete class or instance must be provided for implementation check.")
215
+
216
+ target_class = target if Reflection.isClass(target) else target.__class__
217
+ target_name = target_class.__name__
218
+ abstract_name = abstract.__name__
219
+
220
+ not_implemented = []
221
+ for method in abstract_methods:
222
+ if not hasattr(target, str(method).replace(f"_{abstract_name}", f"_{target_name}")):
223
+ not_implemented.append(method)
224
+
225
+ if not_implemented:
226
+ formatted_methods = "\n • " + "\n • ".join(not_implemented)
227
+ raise OrionisContainerException(
228
+ f"'{target_name}' does not implement the following abstract methods defined in '{abstract_name}':{formatted_methods}\n"
229
+ "Please ensure that all abstract methods are implemented."
230
+ )
231
+
232
+ def transient(self, abstract: Callable[..., Any], concrete: Callable[..., Any], alias: str = None, enforce_decoupling: bool = False) -> bool:
233
+ """
234
+ Registers a service with a transient lifetime.
235
+
236
+ Parameters
237
+ ----------
238
+ abstract : Callable[..., Any]
239
+ The abstract base type or interface to be bound.
240
+ concrete : Callable[..., Any]
241
+ The concrete implementation to associate with the abstract type.
242
+ alias : str, optional
243
+ An alternative name to register the service under. If not provided, the abstract's class name is used.
244
+
245
+ Returns
246
+ -------
247
+ bool
248
+ True if the service was registered successfully.
249
+
250
+ Raises
251
+ ------
252
+ OrionisContainerTypeError
253
+ If the abstract or concrete class checks fail.
254
+ OrionisContainerException
255
+ If the concrete class inherits from the abstract class.
256
+
257
+ Notes
258
+ -----
259
+ Registers the given concrete implementation to the abstract type with a transient lifetime,
260
+ meaning a new instance will be created each time the service is requested. Optionally, an alias
261
+ can be provided for registration.
262
+ """
263
+
264
+ # Ensure that abstract is an abstract class
265
+ self.__ensureAbstractClass(abstract, Lifetime.TRANSIENT)
266
+
267
+ # Ensure that concrete is a concrete class
268
+ self.__ensureConcreteClass(concrete, Lifetime.TRANSIENT)
269
+
270
+ if enforce_decoupling:
271
+ # Ensure that concrete is NOT a subclass of abstract
272
+ self.__ensureIsNotSubclass(abstract, concrete)
273
+ else:
274
+ # Validate that concrete is a subclass of abstract
275
+ self.__ensureIsSubclass(abstract, concrete)
276
+
277
+ # Ensure implementation
278
+ self.__ensureImplementation(
279
+ abstract=abstract,
280
+ concrete=concrete
281
+ )
282
+
283
+ # Ensure that the alias is a valid string if provided
284
+ if alias:
285
+ self.__ensureAliasType(alias)
286
+
53
287
  # Register the service with transient lifetime
54
- self.bind(abstract, concrete, Lifetime.TRANSIENT)
288
+ self.__transient[abstract] = concrete
289
+
290
+ # If an alias is provided, register it as well
291
+ if alias:
292
+ self.__transient[alias] = concrete
293
+ elif hasattr(abstract, '__name__'):
294
+ alias = abstract.__name__
295
+ self.__transient[alias] = concrete
55
296
 
56
297
  # Return True to indicate successful registration
57
298
  return True
58
299
 
59
- def singleton(self, abstract: Callable[..., Any], concrete: Callable[..., Any]) -> bool:
300
+ def singleton(self, abstract: Callable[..., Any], concrete: Callable[..., Any], alias: str = None, enforce_decoupling: bool = False) -> bool:
60
301
  """
61
302
  Registers a service with a singleton lifetime.
62
303
 
63
304
  Parameters
64
305
  ----------
65
306
  abstract : Callable[..., Any]
66
- The abstract base type or alias to be bound.
307
+ The abstract base type or interface to be bound.
67
308
  concrete : Callable[..., Any]
68
309
  The concrete implementation to associate with the abstract type.
310
+ alias : str, optional
311
+ An alternative name to register the service under. If not provided, the abstract's class name is used.
312
+
313
+ Returns
314
+ -------
315
+ bool
316
+ True if the service was registered successfully.
317
+
318
+ Raises
319
+ ------
320
+ OrionisContainerTypeError
321
+ If the abstract or concrete class checks fail.
322
+ OrionisContainerException
323
+ If the concrete class inherits from the abstract class.
324
+
325
+ Notes
326
+ -----
327
+ Registers the given concrete implementation to the abstract type with a singleton lifetime,
328
+ meaning a single instance will be created and shared. Optionally, an alias can be provided for registration.
69
329
  """
70
- # Ensure that abstract is an abstract class and concrete is a concrete class
71
- try:
72
- ReflectionAbstract.ensureIsAbstractClass(abstract)
73
- ReflectionConcrete.ensureIsConcreteClass(concrete)
74
- except Exception as e:
75
- raise OrionisContainerTypeError(
76
- f"Unexpected error registering singleton service: {e}"
77
- ) from e
78
330
 
79
- # Ensure that concrete does NOT inherit from abstract
80
- if issubclass(concrete, abstract):
81
- raise OrionisContainerException(
82
- "Cannot register a concrete class that is a subclass of the provided abstract class. "
83
- "Please ensure that the concrete class does not inherit from the specified abstract class."
84
- )
331
+ # Ensure that abstract is an abstract class
332
+ self.__ensureAbstractClass(abstract, Lifetime.SINGLETON)
333
+
334
+ # Ensure that concrete is a concrete class
335
+ self.__ensureConcreteClass(concrete, Lifetime.SINGLETON)
336
+
337
+ if enforce_decoupling:
338
+ # Ensure that concrete is NOT a subclass of abstract
339
+ self.__ensureIsNotSubclass(abstract, concrete)
340
+ else:
341
+ # Validate that concrete is a subclass of abstract
342
+ self.__ensureIsSubclass(abstract, concrete)
343
+
344
+ # Ensure implementation
345
+ self.__ensureImplementation(
346
+ abstract=abstract,
347
+ concrete=concrete
348
+ )
349
+
350
+ # Ensure that the alias is a valid string if provided
351
+ if alias:
352
+ self.__ensureAliasType(alias)
85
353
 
86
354
  # Register the service with singleton lifetime
87
- self.bind(abstract, concrete, Lifetime.SINGLETON)
355
+ self.__singleton[abstract] = concrete
356
+
357
+ # If an alias is provided, register it as well
358
+ if alias:
359
+ self.__singleton[alias] = concrete
360
+ elif hasattr(abstract, '__name__'):
361
+ alias = abstract.__name__
362
+ self.__singleton[alias] = concrete
88
363
 
89
364
  # Return True to indicate successful registration
90
365
  return True
91
366
 
92
- def scoped(self, abstract: Callable[..., Any], concrete: Callable[..., Any]) -> bool:
367
+ def scoped(self, abstract: Callable[..., Any], concrete: Callable[..., Any], alias: str = None, enforce_decoupling: bool = False) -> bool:
93
368
  """
94
369
  Registers a service with a scoped lifetime.
95
370
 
96
371
  Parameters
97
372
  ----------
98
373
  abstract : Callable[..., Any]
99
- The abstract base type or alias to be bound.
374
+ The abstract base type or interface to be bound.
100
375
  concrete : Callable[..., Any]
101
376
  The concrete implementation to associate with the abstract type.
377
+ alias : str, optional
378
+ An alternative name to register the service under. If not provided, the abstract's class name is used.
379
+
380
+ Returns
381
+ -------
382
+ bool
383
+ True if the service was registered successfully.
384
+
385
+ Raises
386
+ ------
387
+ OrionisContainerTypeError
388
+ If the abstract or concrete class checks fail.
389
+ OrionisContainerException
390
+ If the concrete class inherits from the abstract class.
391
+
392
+ Notes
393
+ -----
394
+ Registers the given concrete implementation to the abstract type with a scoped lifetime,
395
+ meaning a new instance will be created per scope. Optionally, an alias can be provided for registration.
102
396
  """
103
- # Ensure that abstract is an abstract class and concrete is a concrete class
104
- try:
105
- ReflectionAbstract.ensureIsAbstractClass(abstract)
106
- ReflectionConcrete.ensureIsConcreteClass(concrete)
107
- except Exception as e:
108
- raise OrionisContainerTypeError(
109
- f"Unexpected error registering scoped service: {e}"
110
- ) from e
111
397
 
112
- # Ensure that concrete does NOT inherit from abstract
113
- if issubclass(concrete, abstract):
114
- raise OrionisContainerException(
115
- "Cannot register a concrete class that is a subclass of the provided abstract class. "
116
- "Please ensure that the concrete class does not inherit from the specified abstract class."
117
- )
398
+ # Ensure that abstract is an abstract class
399
+ self.__ensureAbstractClass(abstract, Lifetime.SCOPED)
400
+
401
+ # Ensure that concrete is a concrete class
402
+ self.__ensureConcreteClass(concrete, Lifetime.SCOPED)
403
+
404
+ if enforce_decoupling:
405
+ # Ensure that concrete is NOT a subclass of abstract
406
+ self.__ensureIsNotSubclass(abstract, concrete)
407
+ else:
408
+ # Validate that concrete is a subclass of abstract
409
+ self.__ensureIsSubclass(abstract, concrete)
410
+
411
+ # Ensure implementation
412
+ self.__ensureImplementation(
413
+ abstract=abstract,
414
+ concrete=concrete
415
+ )
416
+
417
+ # Ensure that the alias is a valid string if provided
418
+ if alias:
419
+ self.__ensureAliasType(alias)
118
420
 
119
421
  # Register the service with scoped lifetime
120
- self.bind(abstract, concrete, Lifetime.SCOPED)
422
+ self.__scoped[abstract] = concrete
423
+
424
+ # If an alias is provided, register it as well
425
+ if alias:
426
+ self.__scoped[alias] = concrete
427
+ elif hasattr(abstract, '__name__'):
428
+ alias = abstract.__name__
429
+ self.__scoped[alias] = concrete
121
430
 
122
431
  # Return True to indicate successful registration
123
- return True
432
+ return True
433
+
434
+ def instance(self, abstract: Callable[..., Any], instance: Any, alias: str = None, enforce_decoupling: bool = False) -> bool:
435
+ """
436
+ Registers an instance of a class or interface in the container.
437
+ Parameters
438
+ ----------
439
+ abstract : Callable[..., Any]
440
+ The abstract class or interface to associate with the instance.
441
+ instance : Any
442
+ The concrete instance to register.
443
+ alias : str, optional
444
+ An optional alias to register the instance under. If not provided,
445
+ the abstract's `__name__` attribute will be used as the alias if available.
446
+ Returns
447
+ -------
448
+ bool
449
+ True if the instance was successfully registered.
450
+ Raises
451
+ ------
452
+ TypeError
453
+ If `abstract` is not an abstract class or if `alias` is not a valid string.
454
+ ValueError
455
+ If `instance` is not a valid instance of `abstract`.
456
+ Notes
457
+ -----
458
+ This method ensures that the abstract is a valid abstract class, the instance
459
+ is valid, and the alias (if provided) is a valid string. The instance is then
460
+ registered in the container under both the abstract and the alias.
461
+ """
462
+
463
+ # Ensure that the abstract is an abstract class
464
+ self.__ensureAbstractClass(abstract, f"Instance {Lifetime.SINGLETON}")
465
+
466
+ # Ensure that the instance is a valid instance
467
+ self.__ensureInstance(instance)
468
+
469
+ if enforce_decoupling:
470
+ # Ensure that instance is NOT a subclass of abstract
471
+ self.__ensureIsNotSubclass(abstract, instance.__class__)
472
+ else:
473
+ # Validate that instance is a subclass of abstract
474
+ self.__ensureIsSubclass(abstract, instance.__class__)
475
+
476
+ # Ensure implementation
477
+ self.__ensureImplementation(
478
+ abstract=abstract,
479
+ instance=instance
480
+ )
481
+
482
+ # Ensure that the alias is a valid string if provided
483
+ if alias:
484
+ self.__ensureAliasType(alias)
485
+
486
+ # Register the instance with the abstract type
487
+ self.__instance[abstract] = instance
488
+
489
+ # If an alias is provided, register it as well
490
+ if alias:
491
+ self.__instance[alias] = instance
492
+ elif hasattr(abstract, '__name__'):
493
+ alias = abstract.__name__
494
+ self.__instance[alias] = instance
495
+
496
+ # Return True to indicate successful registration
497
+ return True
498
+
499
+ def bind(self, concrete_instance_or_function, lifetime: str = Lifetime.TRANSIENT, alias: str = None) -> None:
500
+ pass
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.313.0"
8
+ VERSION = "0.314.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -12,35 +12,103 @@ from orionis.services.introspection.contracts.reflection_instance import IReflec
12
12
 
13
13
  class ReflectionInstance(IReflectionInstance):
14
14
 
15
- def __init__(self, instance: Any) -> None:
15
+ @staticmethod
16
+ def isInstance(instance: Any) -> bool:
16
17
  """
17
- Initialize the ReflectionInstance with a given object instance.
18
+ Check if the given object is a valid instance according to ReflectionInstance rules.
18
19
 
19
20
  Parameters
20
21
  ----------
21
22
  instance : Any
22
- The object instance to be reflected upon.
23
+ The object to check.
24
+
25
+ Returns
26
+ -------
27
+ bool
28
+ True if the object is a valid instance, False otherwise.
29
+
30
+ Notes
31
+ -----
32
+ This method catches and handles exceptions internally; it does not raise.
33
+ """
34
+ try:
35
+ return ReflectionInstance.ensureIsInstance(instance)
36
+ except (ReflectionTypeError, ReflectionValueError):
37
+ return False
38
+
39
+ @staticmethod
40
+ def ensureIsInstance(instance: Any) -> bool:
41
+ """
42
+ Validate that the provided object is a proper instance of a user-defined class.
43
+
44
+ Parameters
45
+ ----------
46
+ instance : Any
47
+ The object to validate.
48
+
49
+ Returns
50
+ -------
51
+ bool
52
+ True if the instance passes all checks.
23
53
 
24
54
  Raises
25
55
  ------
26
56
  ReflectionTypeError
27
- If the provided instance is not a valid object instance.
57
+ If the input is not a valid object instance.
28
58
  ReflectionValueError
29
- If the instance belongs to a built-in, abstract base class, or '__main__' module.
59
+ If the instance belongs to a disallowed module ('builtins', 'abc') or originates from '__main__'.
60
+
61
+ Notes
62
+ -----
63
+ This method performs the following checks:
64
+ 1. Ensures the input is an object instance (not a class/type).
65
+ 2. Disallows instances of types defined in the 'builtins' or 'abc' modules.
66
+ 3. Disallows instances originating from the '__main__' module, requiring importable module origins.
30
67
  """
68
+
69
+ # Ensure the provided instance is a valid object instance
31
70
  if not (isinstance(instance, object) and not isinstance(instance, type)):
32
71
  raise ReflectionTypeError(
33
72
  f"Expected an object instance, got {type(instance).__name__!r}: {instance!r}"
34
73
  )
74
+
75
+ # Check if the instance belongs to a built-in or abstract base class
35
76
  module = type(instance).__module__
36
77
  if module in {'builtins', 'abc'}:
37
78
  raise ReflectionValueError(
38
79
  f"Instance of type '{type(instance).__name__}' belongs to disallowed module '{module}'."
39
80
  )
81
+
82
+ # Check if the instance originates from '__main__'
40
83
  if module == '__main__':
41
84
  raise ReflectionValueError(
42
85
  "Instance originates from '__main__'; please provide an instance from an importable module."
43
86
  )
87
+
88
+ # If all checks pass, return True
89
+ return True
90
+
91
+ def __init__(self, instance: Any) -> None:
92
+ """
93
+ Initialize the ReflectionInstance with a given object instance.
94
+
95
+ Parameters
96
+ ----------
97
+ instance : Any
98
+ The object instance to be reflected upon.
99
+
100
+ Raises
101
+ ------
102
+ ReflectionTypeError
103
+ If the provided instance is not a valid object instance.
104
+ ReflectionValueError
105
+ If the instance belongs to a built-in, abstract base class, or '__main__' module.
106
+ """
107
+
108
+ # Ensure the instance is valid
109
+ ReflectionInstance.ensureIsInstance(instance)
110
+
111
+ # Store the instance for reflection
44
112
  self._instance = instance
45
113
 
46
114
  def getInstance(self) -> Any: