orionis 0.405.0__py3-none-any.whl → 0.407.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.
- orionis/console/base/command.py +57 -50
- orionis/console/base/contracts/command.py +68 -0
- orionis/console/dynamic/contracts/progress_bar.py +3 -3
- orionis/console/dynamic/progress_bar.py +8 -8
- orionis/console/output/console.py +8 -2
- orionis/console/output/contracts/console.py +1 -1
- orionis/container/container.py +2 -2
- orionis/container/context/scope.py +4 -1
- orionis/container/contracts/service_provider.py +2 -2
- orionis/container/entities/binding.py +31 -44
- orionis/container/enums/lifetimes.py +22 -1
- orionis/container/facades/facade.py +1 -2
- orionis/container/providers/service_provider.py +2 -2
- orionis/foundation/application.py +542 -248
- orionis/foundation/config/app/entities/app.py +107 -90
- orionis/foundation/config/auth/entities/auth.py +4 -33
- orionis/foundation/config/cache/entities/cache.py +18 -41
- orionis/foundation/config/cache/entities/file.py +8 -35
- orionis/foundation/config/cache/entities/stores.py +17 -38
- orionis/foundation/config/cors/entities/cors.py +41 -54
- orionis/foundation/config/database/entities/connections.py +40 -56
- orionis/foundation/config/database/entities/database.py +11 -38
- orionis/foundation/config/database/entities/mysql.py +48 -76
- orionis/foundation/config/database/entities/oracle.py +30 -57
- orionis/foundation/config/database/entities/pgsql.py +45 -61
- orionis/foundation/config/database/entities/sqlite.py +26 -53
- orionis/foundation/config/filesystems/entitites/aws.py +28 -49
- orionis/foundation/config/filesystems/entitites/disks.py +27 -47
- orionis/foundation/config/filesystems/entitites/filesystems.py +15 -37
- orionis/foundation/config/filesystems/entitites/local.py +9 -35
- orionis/foundation/config/filesystems/entitites/public.py +14 -41
- orionis/foundation/config/logging/entities/channels.py +56 -86
- orionis/foundation/config/logging/entities/chunked.py +9 -9
- orionis/foundation/config/logging/entities/daily.py +8 -8
- orionis/foundation/config/logging/entities/hourly.py +6 -6
- orionis/foundation/config/logging/entities/logging.py +12 -18
- orionis/foundation/config/logging/entities/monthly.py +7 -7
- orionis/foundation/config/logging/entities/stack.py +5 -5
- orionis/foundation/config/logging/entities/weekly.py +6 -6
- orionis/foundation/config/mail/entities/file.py +9 -36
- orionis/foundation/config/mail/entities/mail.py +22 -40
- orionis/foundation/config/mail/entities/mailers.py +29 -44
- orionis/foundation/config/mail/entities/smtp.py +47 -48
- orionis/foundation/config/queue/entities/brokers.py +19 -41
- orionis/foundation/config/queue/entities/database.py +24 -46
- orionis/foundation/config/queue/entities/queue.py +28 -40
- orionis/foundation/config/roots/paths.py +272 -468
- orionis/foundation/config/session/entities/session.py +23 -53
- orionis/foundation/config/startup.py +165 -135
- orionis/foundation/config/testing/entities/testing.py +137 -122
- orionis/foundation/config/testing/enums/__init__.py +6 -2
- orionis/foundation/config/testing/enums/drivers.py +16 -0
- orionis/foundation/config/testing/enums/verbosity.py +18 -0
- orionis/foundation/contracts/application.py +152 -362
- orionis/foundation/providers/console_provider.py +24 -2
- orionis/foundation/providers/dumper_provider.py +24 -2
- orionis/foundation/providers/logger_provider.py +24 -2
- orionis/foundation/providers/path_resolver_provider.py +25 -2
- orionis/foundation/providers/progress_bar_provider.py +24 -2
- orionis/foundation/providers/testing_provider.py +39 -0
- orionis/foundation/providers/workers_provider.py +24 -2
- orionis/metadata/framework.py +1 -1
- orionis/services/asynchrony/contracts/coroutines.py +13 -5
- orionis/services/asynchrony/coroutines.py +33 -29
- orionis/services/asynchrony/exceptions/exception.py +9 -1
- orionis/services/environment/core/dot_env.py +46 -34
- orionis/services/environment/enums/__init__.py +0 -0
- orionis/services/environment/enums/cast_type.py +42 -0
- orionis/services/environment/helpers/functions.py +1 -2
- orionis/services/environment/key/__init__.py +0 -0
- orionis/services/environment/key/key_generator.py +37 -0
- orionis/services/environment/serializer/__init__.py +0 -0
- orionis/services/environment/serializer/values.py +21 -0
- orionis/services/environment/validators/__init__.py +0 -0
- orionis/services/environment/validators/key_name.py +46 -0
- orionis/services/environment/validators/types.py +45 -0
- orionis/services/system/contracts/imports.py +38 -18
- orionis/services/system/contracts/workers.py +29 -12
- orionis/services/system/imports.py +65 -25
- orionis/services/system/runtime/imports.py +18 -9
- orionis/services/system/workers.py +49 -16
- orionis/support/entities/__init__.py +0 -0
- orionis/support/entities/base.py +104 -0
- orionis/support/facades/testing.py +15 -0
- orionis/support/facades/workers.py +1 -1
- orionis/test/cases/asynchronous.py +0 -11
- orionis/test/cases/synchronous.py +0 -9
- orionis/test/contracts/dumper.py +11 -4
- orionis/test/contracts/kernel.py +5 -110
- orionis/test/contracts/logs.py +27 -65
- orionis/test/contracts/printer.py +16 -128
- orionis/test/contracts/test_result.py +100 -0
- orionis/test/contracts/unit_test.py +87 -150
- orionis/test/core/unit_test.py +608 -554
- orionis/test/entities/result.py +22 -2
- orionis/test/enums/__init__.py +0 -2
- orionis/test/enums/status.py +14 -9
- orionis/test/exceptions/config.py +9 -1
- orionis/test/exceptions/failure.py +34 -11
- orionis/test/exceptions/persistence.py +10 -2
- orionis/test/exceptions/runtime.py +9 -1
- orionis/test/exceptions/value.py +13 -1
- orionis/test/kernel.py +87 -289
- orionis/test/output/dumper.py +83 -18
- orionis/test/output/printer.py +399 -156
- orionis/test/records/logs.py +203 -82
- orionis/test/validators/__init__.py +33 -0
- orionis/test/validators/base_path.py +45 -0
- orionis/test/validators/execution_mode.py +45 -0
- orionis/test/validators/fail_fast.py +37 -0
- orionis/test/validators/folder_path.py +34 -0
- orionis/test/validators/module_name.py +31 -0
- orionis/test/validators/name_pattern.py +40 -0
- orionis/test/validators/pattern.py +36 -0
- orionis/test/validators/persistent.py +42 -0
- orionis/test/validators/persistent_driver.py +43 -0
- orionis/test/validators/print_result.py +37 -0
- orionis/test/validators/tags.py +37 -0
- orionis/test/validators/throw_exception.py +39 -0
- orionis/test/validators/verbosity.py +37 -0
- orionis/test/validators/web_report.py +35 -0
- orionis/test/validators/workers.py +31 -0
- orionis/test/view/render.py +48 -54
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/METADATA +1 -1
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/RECORD +170 -112
- tests/container/__init__.py +0 -0
- tests/container/context/__init__.py +0 -0
- tests/container/context/test_manager.py +27 -0
- tests/container/context/test_scope.py +23 -0
- tests/container/entities/__init__.py +0 -0
- tests/container/entities/test_binding.py +133 -0
- tests/container/enums/__init__.py +0 -0
- tests/container/enums/test_lifetimes.py +63 -0
- tests/container/facades/__init__.py +0 -0
- tests/container/facades/test_facade.py +61 -0
- tests/container/mocks/__init__.py +0 -0
- tests/container/mocks/mock_complex_classes.py +482 -0
- tests/container/mocks/mock_simple_classes.py +32 -0
- tests/container/providers/__init__.py +0 -0
- tests/container/providers/test_providers.py +48 -0
- tests/container/resolver/__init__.py +0 -0
- tests/container/resolver/test_resolver.py +55 -0
- tests/container/test_container.py +254 -0
- tests/container/test_singleton.py +98 -0
- tests/container/test_thread_safety.py +217 -0
- tests/container/validators/__init__.py +0 -0
- tests/container/validators/test_implements.py +140 -0
- tests/container/validators/test_is_abstract_class.py +99 -0
- tests/container/validators/test_is_callable.py +73 -0
- tests/container/validators/test_is_concrete_class.py +97 -0
- tests/container/validators/test_is_instance.py +105 -0
- tests/container/validators/test_is_not_subclass.py +117 -0
- tests/container/validators/test_is_subclass.py +115 -0
- tests/container/validators/test_is_valid_alias.py +113 -0
- tests/container/validators/test_lifetime.py +75 -0
- tests/example/test_example.py +2 -2
- tests/foundation/config/testing/test_foundation_config_testing.py +1 -1
- tests/metadata/test_metadata_framework.py +89 -24
- tests/metadata/test_metadata_package.py +55 -10
- tests/services/asynchrony/test_services_asynchrony_coroutine.py +52 -7
- tests/services/system/test_services_system_imports.py +119 -16
- tests/services/system/test_services_system_workers.py +71 -30
- tests/testing/test_testing_result.py +117 -117
- tests/testing/test_testing_unit.py +209 -209
- orionis/foundation/config/base.py +0 -112
- orionis/test/arguments/parser.py +0 -187
- orionis/test/contracts/parser.py +0 -43
- orionis/test/entities/arguments.py +0 -38
- orionis/test/enums/execution_mode.py +0 -16
- /orionis/{test/arguments → console/base/contracts}/__init__.py +0 -0
- /orionis/foundation/config/testing/enums/{test_mode.py → mode.py} +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/WHEEL +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/top_level.txt +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from orionis.container.validators.is_subclass import IsSubclass
|
|
3
|
+
from orionis.container.exceptions.exception import OrionisContainerException
|
|
4
|
+
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
5
|
+
|
|
6
|
+
class TestIsSubclass(AsyncTestCase):
|
|
7
|
+
"""
|
|
8
|
+
Test cases for the IsSubclass validator in orionis.container.validators.is_subclass.
|
|
9
|
+
|
|
10
|
+
Notes
|
|
11
|
+
-----
|
|
12
|
+
This test suite validates the functionality of the IsSubclass validator
|
|
13
|
+
which ensures that a concrete class is a subclass of an abstract class.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
async def testValidSubclass(self) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Test that validation passes when concrete class is a valid subclass.
|
|
19
|
+
"""
|
|
20
|
+
# Define test classes
|
|
21
|
+
class AbstractClass(ABC):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
class ConcreteClass(AbstractClass):
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
class SubConcreteClass(ConcreteClass):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
# These should not raise exceptions
|
|
31
|
+
IsSubclass(AbstractClass, ConcreteClass)
|
|
32
|
+
IsSubclass(AbstractClass, SubConcreteClass)
|
|
33
|
+
IsSubclass(ConcreteClass, SubConcreteClass)
|
|
34
|
+
|
|
35
|
+
async def testInvalidSubclass(self) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Test that validation fails when concrete class is not a subclass.
|
|
38
|
+
"""
|
|
39
|
+
# Define test classes
|
|
40
|
+
class AbstractClass1(ABC):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
class AbstractClass2(ABC):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
class ConcreteClass1(AbstractClass1):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
class ConcreteClass2(AbstractClass2):
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
# These should raise exceptions
|
|
53
|
+
with self.assertRaises(OrionisContainerException) as context:
|
|
54
|
+
IsSubclass(AbstractClass1, AbstractClass2)
|
|
55
|
+
self.assertIn("concrete class must inherit", str(context.exception))
|
|
56
|
+
|
|
57
|
+
with self.assertRaises(OrionisContainerException) as context:
|
|
58
|
+
IsSubclass(AbstractClass1, ConcreteClass2)
|
|
59
|
+
self.assertIn("concrete class must inherit", str(context.exception))
|
|
60
|
+
|
|
61
|
+
with self.assertRaises(OrionisContainerException) as context:
|
|
62
|
+
IsSubclass(ConcreteClass1, AbstractClass1)
|
|
63
|
+
self.assertIn("concrete class must inherit", str(context.exception))
|
|
64
|
+
|
|
65
|
+
async def testSameClass(self) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Test validation when abstract and concrete are the same class.
|
|
68
|
+
"""
|
|
69
|
+
class TestClass:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
# A class is considered a subclass of itself
|
|
73
|
+
IsSubclass(TestClass, TestClass)
|
|
74
|
+
|
|
75
|
+
async def testBuiltinTypes(self) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Test validation with built-in types.
|
|
78
|
+
"""
|
|
79
|
+
# Valid subclass relationships
|
|
80
|
+
IsSubclass(Exception, ValueError)
|
|
81
|
+
IsSubclass(BaseException, Exception)
|
|
82
|
+
|
|
83
|
+
# Invalid subclass relationships
|
|
84
|
+
with self.assertRaises(OrionisContainerException):
|
|
85
|
+
IsSubclass(ValueError, Exception)
|
|
86
|
+
|
|
87
|
+
with self.assertRaises(OrionisContainerException):
|
|
88
|
+
IsSubclass(int, str)
|
|
89
|
+
|
|
90
|
+
with self.assertRaises(OrionisContainerException):
|
|
91
|
+
IsSubclass(list, dict)
|
|
92
|
+
|
|
93
|
+
async def testNonClassArguments(self) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Test validation with non-class arguments which should raise TypeError.
|
|
96
|
+
"""
|
|
97
|
+
class TestClass:
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
# These should raise TypeError when passed to issubclass()
|
|
101
|
+
non_class_args = [
|
|
102
|
+
None,
|
|
103
|
+
123,
|
|
104
|
+
"string",
|
|
105
|
+
[],
|
|
106
|
+
{},
|
|
107
|
+
lambda x: x
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
for arg in non_class_args:
|
|
111
|
+
with self.assertRaises(TypeError):
|
|
112
|
+
IsSubclass(TestClass, arg)
|
|
113
|
+
|
|
114
|
+
with self.assertRaises(TypeError):
|
|
115
|
+
IsSubclass(arg, TestClass)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from orionis.container.validators.is_valid_alias import IsValidAlias
|
|
2
|
+
from orionis.container.exceptions.type import OrionisContainerTypeError
|
|
3
|
+
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
4
|
+
|
|
5
|
+
class TestIsValidAlias(AsyncTestCase):
|
|
6
|
+
"""
|
|
7
|
+
Test cases for the IsValidAlias validator in orionis.container.validators.is_valid_alias.
|
|
8
|
+
|
|
9
|
+
Notes
|
|
10
|
+
-----
|
|
11
|
+
This test suite validates the functionality of the IsValidAlias validator
|
|
12
|
+
which ensures that alias values are valid strings without invalid characters.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
async def testValidAliases(self) -> None:
|
|
16
|
+
"""
|
|
17
|
+
Test that validation passes when valid aliases are provided.
|
|
18
|
+
"""
|
|
19
|
+
valid_aliases = [
|
|
20
|
+
"valid",
|
|
21
|
+
"valid_alias",
|
|
22
|
+
"validAlias",
|
|
23
|
+
"valid123",
|
|
24
|
+
"valid_123",
|
|
25
|
+
"v",
|
|
26
|
+
"1",
|
|
27
|
+
"_",
|
|
28
|
+
"valid_alias_with_underscores",
|
|
29
|
+
"ValidAliasWithMixedCase",
|
|
30
|
+
"VALID_UPPERCASE_ALIAS"
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
for alias in valid_aliases:
|
|
34
|
+
IsValidAlias(alias)
|
|
35
|
+
|
|
36
|
+
async def testInvalidAliasTypes(self) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Test that validation fails when non-string types are provided.
|
|
39
|
+
"""
|
|
40
|
+
invalid_types = [
|
|
41
|
+
123,
|
|
42
|
+
3.14,
|
|
43
|
+
None,
|
|
44
|
+
True,
|
|
45
|
+
False,
|
|
46
|
+
[],
|
|
47
|
+
{},
|
|
48
|
+
(),
|
|
49
|
+
set()
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
for value in invalid_types:
|
|
53
|
+
with self.assertRaises(OrionisContainerTypeError) as context:
|
|
54
|
+
IsValidAlias(value)
|
|
55
|
+
|
|
56
|
+
async def testAliasWithInvalidCharacters(self) -> None:
|
|
57
|
+
"""
|
|
58
|
+
Test that validation fails when aliases contain invalid characters.
|
|
59
|
+
"""
|
|
60
|
+
invalid_aliases = [
|
|
61
|
+
"invalid alias", # space
|
|
62
|
+
"invalid\talias", # tab
|
|
63
|
+
"invalid\nalias", # newline
|
|
64
|
+
"invalid@alias", # special character
|
|
65
|
+
"invalid#alias", # special character
|
|
66
|
+
"invalid$alias", # special character
|
|
67
|
+
"invalid%alias", # special character
|
|
68
|
+
"invalid&alias", # special character
|
|
69
|
+
"invalid*alias", # special character
|
|
70
|
+
"invalid(alias)", # parentheses
|
|
71
|
+
"invalid[alias]", # brackets
|
|
72
|
+
"invalid{alias}", # braces
|
|
73
|
+
"invalid;alias", # semicolon
|
|
74
|
+
"invalid:alias", # colon
|
|
75
|
+
"invalid,alias", # comma
|
|
76
|
+
"invalid/alias", # slash
|
|
77
|
+
"invalid\\alias", # backslash
|
|
78
|
+
"invalid<alias>", # angle brackets
|
|
79
|
+
"invalid|alias", # pipe
|
|
80
|
+
"invalid`alias", # backtick
|
|
81
|
+
'invalid"alias', # double quote
|
|
82
|
+
"invalid'alias" # single quote
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
for alias in invalid_aliases:
|
|
86
|
+
with self.assertRaises(OrionisContainerTypeError) as context:
|
|
87
|
+
IsValidAlias(alias)
|
|
88
|
+
|
|
89
|
+
expected_msg_start = f"Alias '{alias}' contains invalid characters."
|
|
90
|
+
self.assertTrue(str(context.exception).startswith(expected_msg_start))
|
|
91
|
+
self.assertIn("Aliases must not contain whitespace or special symbols", str(context.exception))
|
|
92
|
+
|
|
93
|
+
async def testEmptyAlias(self) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Test that validation fails with an empty string.
|
|
96
|
+
"""
|
|
97
|
+
# Empty string should be rejected
|
|
98
|
+
with self.assertRaises(OrionisContainerTypeError) as context:
|
|
99
|
+
IsValidAlias("")
|
|
100
|
+
|
|
101
|
+
self.assertEqual(
|
|
102
|
+
str(context.exception),
|
|
103
|
+
"Alias cannot be None, empty, or whitespace only."
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Whitespace-only string should also be rejected
|
|
107
|
+
with self.assertRaises(OrionisContainerTypeError) as context:
|
|
108
|
+
IsValidAlias(" ")
|
|
109
|
+
|
|
110
|
+
self.assertEqual(
|
|
111
|
+
str(context.exception),
|
|
112
|
+
"Alias cannot be None, empty, or whitespace only."
|
|
113
|
+
)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from orionis.container.validators.lifetime import LifetimeValidator
|
|
2
|
+
from orionis.container.enums.lifetimes import Lifetime
|
|
3
|
+
from orionis.container.exceptions.type import OrionisContainerTypeError
|
|
4
|
+
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
5
|
+
|
|
6
|
+
class TestLifetimeValidator(AsyncTestCase):
|
|
7
|
+
"""
|
|
8
|
+
Test cases for the LifetimeValidator in orionis.container.validators.lifetime.
|
|
9
|
+
|
|
10
|
+
Notes
|
|
11
|
+
-----
|
|
12
|
+
This test suite validates the functionality of the LifetimeValidator
|
|
13
|
+
which ensures that lifetime values are correctly validated and converted.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
async def testValidLifetimeEnumValues(self) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Test that validation passes when Lifetime enum values are provided.
|
|
19
|
+
"""
|
|
20
|
+
self.assertEqual(LifetimeValidator(Lifetime.TRANSIENT), Lifetime.TRANSIENT)
|
|
21
|
+
self.assertEqual(LifetimeValidator(Lifetime.SINGLETON), Lifetime.SINGLETON)
|
|
22
|
+
self.assertEqual(LifetimeValidator(Lifetime.SCOPED), Lifetime.SCOPED)
|
|
23
|
+
|
|
24
|
+
async def testValidLifetimeStringValues(self) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Test that validation passes when valid string representations are provided.
|
|
27
|
+
"""
|
|
28
|
+
self.assertEqual(LifetimeValidator("TRANSIENT"), Lifetime.TRANSIENT)
|
|
29
|
+
self.assertEqual(LifetimeValidator("SINGLETON"), Lifetime.SINGLETON)
|
|
30
|
+
self.assertEqual(LifetimeValidator("SCOPED"), Lifetime.SCOPED)
|
|
31
|
+
|
|
32
|
+
# Test with lowercase and mixed case
|
|
33
|
+
self.assertEqual(LifetimeValidator("transient"), Lifetime.TRANSIENT)
|
|
34
|
+
self.assertEqual(LifetimeValidator("Singleton"), Lifetime.SINGLETON)
|
|
35
|
+
self.assertEqual(LifetimeValidator("scoped"), Lifetime.SCOPED)
|
|
36
|
+
|
|
37
|
+
# Test with extra whitespace
|
|
38
|
+
self.assertEqual(LifetimeValidator(" TRANSIENT "), Lifetime.TRANSIENT)
|
|
39
|
+
self.assertEqual(LifetimeValidator(" singleton "), Lifetime.SINGLETON)
|
|
40
|
+
|
|
41
|
+
async def testInvalidLifetimeStringValue(self) -> None:
|
|
42
|
+
"""
|
|
43
|
+
Test that validation fails when invalid string representations are provided.
|
|
44
|
+
"""
|
|
45
|
+
with self.assertRaises(OrionisContainerTypeError) as context:
|
|
46
|
+
LifetimeValidator("INVALID_LIFETIME")
|
|
47
|
+
|
|
48
|
+
self.assertIn("Invalid lifetime 'INVALID_LIFETIME'", str(context.exception))
|
|
49
|
+
self.assertIn("Valid options are:", str(context.exception))
|
|
50
|
+
self.assertIn("TRANSIENT", str(context.exception))
|
|
51
|
+
self.assertIn("SINGLETON", str(context.exception))
|
|
52
|
+
self.assertIn("SCOPED", str(context.exception))
|
|
53
|
+
|
|
54
|
+
async def testInvalidLifetimeType(self) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Test that validation fails when invalid types are provided.
|
|
57
|
+
"""
|
|
58
|
+
invalid_values = [
|
|
59
|
+
123,
|
|
60
|
+
3.14,
|
|
61
|
+
None,
|
|
62
|
+
True,
|
|
63
|
+
False,
|
|
64
|
+
[],
|
|
65
|
+
{},
|
|
66
|
+
(),
|
|
67
|
+
set()
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
for value in invalid_values:
|
|
71
|
+
with self.assertRaises(OrionisContainerTypeError) as context:
|
|
72
|
+
LifetimeValidator(value)
|
|
73
|
+
|
|
74
|
+
expected_msg = f"Lifetime must be of type str or Lifetime enum, got {type(value).__name__}."
|
|
75
|
+
self.assertEqual(str(context.exception), expected_msg)
|
tests/example/test_example.py
CHANGED
|
@@ -6,7 +6,7 @@ This module contains comprehensive test examples demonstrating the capabilities
|
|
|
6
6
|
of the Orionis testing framework, including both synchronous and asynchronous
|
|
7
7
|
testing patterns with dependency injection.
|
|
8
8
|
|
|
9
|
-
Examples
|
|
9
|
+
Examples:
|
|
10
10
|
--------
|
|
11
11
|
Run synchronous tests:
|
|
12
12
|
>>> from tests.example.test_example import TestSynchronousExample
|
|
@@ -20,7 +20,7 @@ Examples
|
|
|
20
20
|
>>> await test.asyncSetUp()
|
|
21
21
|
>>> await test.testAsyncBasicOperations()
|
|
22
22
|
|
|
23
|
-
Notes
|
|
23
|
+
Notes:
|
|
24
24
|
-----
|
|
25
25
|
These examples showcase:
|
|
26
26
|
- Dependency injection patterns
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from orionis.foundation.config.testing.entities.testing import Testing
|
|
2
|
+
from orionis.foundation.config.testing.enums.mode import ExecutionMode
|
|
2
3
|
from orionis.foundation.exceptions import OrionisIntegrityException
|
|
3
|
-
from orionis.test.enums.execution_mode import ExecutionMode
|
|
4
4
|
from orionis.test.cases.asynchronous import AsyncTestCase
|
|
5
5
|
|
|
6
6
|
class TestFoundationConfigTesting(AsyncTestCase):
|
|
@@ -13,89 +13,154 @@ class TestMetadataFramework(AsyncTestCase):
|
|
|
13
13
|
|
|
14
14
|
async def testConstantsExistAndAreStr(self):
|
|
15
15
|
"""
|
|
16
|
-
|
|
16
|
+
Validate that all metadata constants exist and are of type `str`.
|
|
17
|
+
|
|
18
|
+
This test iterates over a predefined list of metadata constants and checks
|
|
19
|
+
that each constant is present and its type is `str`.
|
|
17
20
|
|
|
18
21
|
Raises
|
|
19
22
|
------
|
|
20
23
|
AssertionError
|
|
21
24
|
If any constant is not a string.
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
None
|
|
29
|
+
This method does not return any value.
|
|
22
30
|
"""
|
|
31
|
+
|
|
32
|
+
# Check each metadata constant for type str
|
|
23
33
|
for const in [
|
|
24
34
|
NAME, VERSION, AUTHOR, AUTHOR_EMAIL, DESCRIPTION,
|
|
25
35
|
SKELETON, FRAMEWORK, DOCS, API, PYTHON_REQUIRES
|
|
26
36
|
]:
|
|
27
|
-
|
|
37
|
+
self.assertIsInstance(const, str)
|
|
28
38
|
|
|
29
39
|
async def testClassifiersStructure(self):
|
|
30
40
|
"""
|
|
31
|
-
|
|
41
|
+
Ensure that `CLASSIFIERS` is a list of tuples containing strings.
|
|
42
|
+
|
|
43
|
+
This test verifies the structure of the `CLASSIFIERS` constant, ensuring
|
|
44
|
+
it is a list where each element is a tuple, and each tuple contains only strings.
|
|
32
45
|
|
|
33
46
|
Raises
|
|
34
47
|
------
|
|
35
48
|
AssertionError
|
|
36
49
|
If `CLASSIFIERS` is not a list of tuples of strings.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
None
|
|
54
|
+
This method does not return any value.
|
|
37
55
|
"""
|
|
38
|
-
|
|
56
|
+
|
|
57
|
+
# Confirm CLASSIFIERS is a list
|
|
58
|
+
self.assertIsInstance(CLASSIFIERS, list)
|
|
59
|
+
|
|
60
|
+
# Check each item in CLASSIFIERS for tuple of strings
|
|
39
61
|
for item in CLASSIFIERS:
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
self.assertIsInstance(item, tuple)
|
|
63
|
+
self.assertTrue(all(isinstance(part, str) for part in item))
|
|
42
64
|
|
|
43
65
|
async def testGetClassifiers(self):
|
|
44
66
|
"""
|
|
45
|
-
|
|
67
|
+
Verify that `get_classifiers` returns a list of classifier strings.
|
|
68
|
+
|
|
69
|
+
This test calls the `get_classifiers` utility function and checks that
|
|
70
|
+
the returned value is a list of strings, each representing a classifier.
|
|
46
71
|
|
|
47
72
|
Raises
|
|
48
73
|
------
|
|
49
74
|
AssertionError
|
|
50
75
|
If the returned value is not a list of strings containing '::'.
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
None
|
|
80
|
+
This method does not return any value.
|
|
51
81
|
"""
|
|
82
|
+
|
|
83
|
+
# Retrieve classifiers and validate their format
|
|
52
84
|
classifiers = get_classifiers()
|
|
53
|
-
|
|
85
|
+
self.assertIsInstance(classifiers, list)
|
|
54
86
|
for c in classifiers:
|
|
55
|
-
|
|
56
|
-
|
|
87
|
+
self.assertIsInstance(c, str)
|
|
88
|
+
self.assertTrue(" :: " in c or len(c.split(" :: ")) > 1)
|
|
57
89
|
|
|
58
90
|
async def testKeywords(self):
|
|
59
91
|
"""
|
|
60
|
-
|
|
92
|
+
Check that `KEYWORDS` is a list of strings and contains required keywords.
|
|
93
|
+
|
|
94
|
+
This test ensures that the `KEYWORDS` constant is a list of strings and
|
|
95
|
+
verifies the presence of specific keywords relevant to the framework.
|
|
61
96
|
|
|
62
97
|
Raises
|
|
63
98
|
------
|
|
64
99
|
AssertionError
|
|
65
100
|
If `KEYWORDS` is not a list of strings or required keywords are missing.
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
None
|
|
105
|
+
This method does not return any value.
|
|
66
106
|
"""
|
|
67
|
-
|
|
107
|
+
|
|
108
|
+
# Confirm KEYWORDS is a list of strings
|
|
109
|
+
self.assertIsInstance(KEYWORDS, list)
|
|
68
110
|
for kw in KEYWORDS:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
111
|
+
self.assertIsInstance(kw, str)
|
|
112
|
+
|
|
113
|
+
# Check for required keywords
|
|
114
|
+
self.assertIn("orionis", KEYWORDS)
|
|
115
|
+
self.assertIn("framework", KEYWORDS)
|
|
72
116
|
|
|
73
117
|
async def testRequiresStructure(self):
|
|
74
118
|
"""
|
|
75
|
-
|
|
119
|
+
Validate that `REQUIRES` is a list of 2-element tuples of strings.
|
|
120
|
+
|
|
121
|
+
This test checks the structure of the `REQUIRES` constant, ensuring it is
|
|
122
|
+
a list where each element is a tuple of length 2, and both elements are strings.
|
|
76
123
|
|
|
77
124
|
Raises
|
|
78
125
|
------
|
|
79
126
|
AssertionError
|
|
80
127
|
If `REQUIRES` is not a list of 2-element tuples of strings.
|
|
128
|
+
|
|
129
|
+
Returns
|
|
130
|
+
-------
|
|
131
|
+
None
|
|
132
|
+
This method does not return any value.
|
|
81
133
|
"""
|
|
82
|
-
|
|
134
|
+
|
|
135
|
+
# Confirm REQUIRES is a list of 2-element tuples of strings
|
|
136
|
+
self.assertIsInstance(REQUIRES, list)
|
|
83
137
|
for req in REQUIRES:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
138
|
+
self.assertIsInstance(req, tuple)
|
|
139
|
+
self.assertEqual(len(req), 2)
|
|
140
|
+
self.assertTrue(all(isinstance(part, str) for part in req))
|
|
87
141
|
|
|
88
142
|
async def testGetRequires(self):
|
|
89
143
|
"""
|
|
90
|
-
|
|
144
|
+
Ensure that `get_requires` returns a list of requirement strings.
|
|
145
|
+
|
|
146
|
+
This test calls the `get_requires` utility function and checks that the
|
|
147
|
+
returned value is a list of strings, each representing a requirement and
|
|
148
|
+
containing the '>=' version specifier.
|
|
91
149
|
|
|
92
150
|
Raises
|
|
93
151
|
------
|
|
94
152
|
AssertionError
|
|
95
153
|
If the returned value is not a list of strings containing '>='.
|
|
154
|
+
|
|
155
|
+
Returns
|
|
156
|
+
-------
|
|
157
|
+
None
|
|
158
|
+
This method does not return any value.
|
|
96
159
|
"""
|
|
160
|
+
|
|
161
|
+
# Retrieve requirements and validate their format
|
|
97
162
|
requires = get_requires()
|
|
98
|
-
|
|
163
|
+
self.assertIsInstance(requires, list)
|
|
99
164
|
for req in requires:
|
|
100
|
-
|
|
101
|
-
|
|
165
|
+
self.assertIsInstance(req, str)
|
|
166
|
+
self.assertIn(">=", req)
|
|
@@ -6,89 +6,134 @@ class TestPypiPackageApi(AsyncTestCase):
|
|
|
6
6
|
@patch("orionis.metadata.package.PypiPackageApi")
|
|
7
7
|
async def testGetName(self, MockPypiPackageApi):
|
|
8
8
|
"""
|
|
9
|
-
|
|
9
|
+
Tests the `getName` method of the `PypiPackageApi` class.
|
|
10
|
+
|
|
11
|
+
This test verifies that the mocked `getName` method returns the expected package name.
|
|
10
12
|
|
|
11
13
|
Parameters
|
|
12
14
|
----------
|
|
13
15
|
MockPypiPackageApi : MagicMock
|
|
14
|
-
Mocked PypiPackageApi class.
|
|
16
|
+
Mocked `PypiPackageApi` class.
|
|
15
17
|
|
|
16
18
|
Returns
|
|
17
19
|
-------
|
|
18
20
|
None
|
|
21
|
+
This method does not return anything. It asserts the expected behavior.
|
|
19
22
|
"""
|
|
23
|
+
|
|
24
|
+
# Get the mocked API instance
|
|
20
25
|
api = MockPypiPackageApi.return_value
|
|
26
|
+
|
|
27
|
+
# Set the return value for getName
|
|
21
28
|
api.getName.return_value = "orionis"
|
|
29
|
+
|
|
30
|
+
# Assert that getName returns the expected value
|
|
22
31
|
self.assertEqual(api.getName(), "orionis")
|
|
23
32
|
|
|
24
33
|
@patch("orionis.metadata.package.PypiPackageApi")
|
|
25
34
|
async def testGetAuthor(self, MockPypiPackageApi):
|
|
26
35
|
"""
|
|
27
|
-
|
|
36
|
+
Tests the `getAuthor` method of the `PypiPackageApi` class.
|
|
37
|
+
|
|
38
|
+
This test checks that the mocked `getAuthor` method returns the correct author name.
|
|
28
39
|
|
|
29
40
|
Parameters
|
|
30
41
|
----------
|
|
31
42
|
MockPypiPackageApi : MagicMock
|
|
32
|
-
Mocked PypiPackageApi class.
|
|
43
|
+
Mocked `PypiPackageApi` class.
|
|
33
44
|
|
|
34
45
|
Returns
|
|
35
46
|
-------
|
|
36
47
|
None
|
|
48
|
+
This method does not return anything. It asserts the expected behavior.
|
|
37
49
|
"""
|
|
50
|
+
|
|
51
|
+
# Get the mocked API instance
|
|
38
52
|
api = MockPypiPackageApi.return_value
|
|
53
|
+
|
|
54
|
+
# Set the return value for getAuthor
|
|
39
55
|
api.getAuthor.return_value = "Raul Mauricio Uñate Castro"
|
|
56
|
+
|
|
57
|
+
# Assert that getAuthor returns the expected value
|
|
40
58
|
self.assertEqual(api.getAuthor(), "Raul Mauricio Uñate Castro")
|
|
41
59
|
|
|
42
60
|
@patch("orionis.metadata.package.PypiPackageApi")
|
|
43
61
|
async def testGetAuthorEmail(self, MockPypiPackageApi):
|
|
44
62
|
"""
|
|
45
|
-
|
|
63
|
+
Tests the `getAuthorEmail` method of the `PypiPackageApi` class.
|
|
64
|
+
|
|
65
|
+
This test ensures that the mocked `getAuthorEmail` method returns the correct author email address.
|
|
46
66
|
|
|
47
67
|
Parameters
|
|
48
68
|
----------
|
|
49
69
|
MockPypiPackageApi : MagicMock
|
|
50
|
-
Mocked PypiPackageApi class.
|
|
70
|
+
Mocked `PypiPackageApi` class.
|
|
51
71
|
|
|
52
72
|
Returns
|
|
53
73
|
-------
|
|
54
74
|
None
|
|
75
|
+
This method does not return anything. It asserts the expected behavior.
|
|
55
76
|
"""
|
|
77
|
+
|
|
78
|
+
# Get the mocked API instance
|
|
56
79
|
api = MockPypiPackageApi.return_value
|
|
80
|
+
|
|
81
|
+
# Set the return value for getAuthorEmail
|
|
57
82
|
api.getAuthorEmail.return_value = "raulmauriciounate@gmail.com"
|
|
83
|
+
|
|
84
|
+
# Assert that getAuthorEmail returns the expected value
|
|
58
85
|
self.assertEqual(api.getAuthorEmail(), "raulmauriciounate@gmail.com")
|
|
59
86
|
|
|
60
87
|
@patch("orionis.metadata.package.PypiPackageApi")
|
|
61
88
|
async def testGetDescription(self, MockPypiPackageApi):
|
|
62
89
|
"""
|
|
63
|
-
|
|
90
|
+
Tests the `getDescription` method of the `PypiPackageApi` class.
|
|
91
|
+
|
|
92
|
+
This test verifies that the mocked `getDescription` method returns the expected package description.
|
|
64
93
|
|
|
65
94
|
Parameters
|
|
66
95
|
----------
|
|
67
96
|
MockPypiPackageApi : MagicMock
|
|
68
|
-
Mocked PypiPackageApi class.
|
|
97
|
+
Mocked `PypiPackageApi` class.
|
|
69
98
|
|
|
70
99
|
Returns
|
|
71
100
|
-------
|
|
72
101
|
None
|
|
102
|
+
This method does not return anything. It asserts the expected behavior.
|
|
73
103
|
"""
|
|
104
|
+
|
|
105
|
+
# Get the mocked API instance
|
|
74
106
|
api = MockPypiPackageApi.return_value
|
|
107
|
+
|
|
108
|
+
# Set the return value for getDescription
|
|
75
109
|
api.getDescription.return_value = "Orionis Framework – Elegant, Fast, and Powerful."
|
|
110
|
+
|
|
111
|
+
# Assert that getDescription returns the expected value
|
|
76
112
|
self.assertEqual(api.getDescription(), "Orionis Framework – Elegant, Fast, and Powerful.")
|
|
77
113
|
|
|
78
114
|
@patch("orionis.metadata.package.PypiPackageApi")
|
|
79
115
|
async def testGetPythonVersion(self, MockPypiPackageApi):
|
|
80
116
|
"""
|
|
81
|
-
|
|
117
|
+
Tests the `getPythonVersion` method of the `PypiPackageApi` class.
|
|
118
|
+
|
|
119
|
+
This test checks that the mocked `getPythonVersion` method returns the correct Python version requirement.
|
|
82
120
|
|
|
83
121
|
Parameters
|
|
84
122
|
----------
|
|
85
123
|
MockPypiPackageApi : MagicMock
|
|
86
|
-
Mocked PypiPackageApi class.
|
|
124
|
+
Mocked `PypiPackageApi` class.
|
|
87
125
|
|
|
88
126
|
Returns
|
|
89
127
|
-------
|
|
90
128
|
None
|
|
129
|
+
This method does not return anything. It asserts the expected behavior.
|
|
91
130
|
"""
|
|
131
|
+
|
|
132
|
+
# Get the mocked API instance
|
|
92
133
|
api = MockPypiPackageApi.return_value
|
|
134
|
+
|
|
135
|
+
# Set the return value for getPythonVersion
|
|
93
136
|
api.getPythonVersion.return_value = ">=3.12"
|
|
137
|
+
|
|
138
|
+
# Assert that getPythonVersion returns the expected value
|
|
94
139
|
self.assertEqual(api.getPythonVersion(), ">=3.12")
|