Skip to content

Commit 38801bf

Browse files
authored
Merge pull request #7 from runemalm/feature/next-release
Release version v1.0.0-alpha.9
2 parents 4e9ec29 + c256f5d commit 38801bf

File tree

14 files changed

+250
-42
lines changed

14 files changed

+250
-42
lines changed

README.md

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# py-dependency-injection
66

7-
A prototypical dependency injection library for Python.
7+
A dependency injection library for Python.
88

99
## Features
1010

@@ -83,46 +83,52 @@ You can find the source code for `py-dependency-injection` on [GitHub](https://g
8383

8484
## Release Notes
8585

86+
### [1.0.0-alpha.9](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.9) (2024-08-08)
87+
88+
- **Breaking Change**: Removed constructor injection when resolving dataclasses.
89+
- **Enhancement**: Added dependency container getter and setter for registrations. Also added new `RegistrationSerializer` class for for serializing and deserializing them. These additions provide a more flexible way to interact with the container's registrations.
90+
8691
### [1.0.0-alpha.8](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.8) (2024-06-07)
8792

88-
- Bug Fix: Fixed an issue in the dependency resolution logic where registered constructor arguments were not properly merged with automatically injected dependencies. This ensures that constructor arguments specified during registration are correctly combined with dependencies resolved by the container.
93+
- **Bug Fix**: Fixed an issue in the dependency resolution logic where registered constructor arguments were not properly merged with automatically injected dependencies. This ensures that constructor arguments specified during registration are correctly combined with dependencies resolved by the container.
94+
- **Documentation Update**: The documentation structure has been updated for better organization and ease of understanding.
8995

9096
### [1.0.0-alpha.7](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.7) (2024-03-24)
9197

92-
- Documentation Update: Updated the documentation to provide clearer instructions and more comprehensive examples.
93-
- Preparing for Beta Release: Made necessary adjustments and refinements in preparation for the upcoming first beta release.
98+
- **Documentation Update**: Updated the documentation to provide clearer instructions and more comprehensive examples.
99+
- **Preparing for Beta Release**: Made necessary adjustments and refinements in preparation for the upcoming first beta release.
94100

95101
### [1.0.0-alpha.6](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.6) (2024-03-23)
96102

97-
- Factory Registration: Added support for registering dependencies using factory functions for dynamic instantiation.
98-
- Instance Registration: Enabled registering existing instances as dependencies.
99-
- Tag-based Registration and Resolution: Introduced the ability to register and resolve dependencies using tags for flexible dependency management.
103+
- **Factory Registration**: Added support for registering dependencies using factory functions for dynamic instantiation.
104+
- **Instance Registration**: Enabled registering existing instances as dependencies.
105+
- **Tag-based Registration and Resolution**: Introduced the ability to register and resolve dependencies using tags for flexible dependency management.
100106

101107
### [1.0.0-alpha.5](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.5) (2024-03-03)
102108

103109
- **Critical Package Integrity Fix**: This release addresses a critical issue that affected the packaging of the Python library in all previous alpha releases (1.0.0-alpha.1 to 1.0.0-alpha.4). The problem involved missing source files in the distribution, rendering the library incomplete and non-functional. Users are strongly advised to upgrade to version 1.0.0-alpha.5 to ensure the correct functioning of the library. All previous alpha releases are affected by this issue.
104110

105111
### [1.0.0-alpha.4](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.4) (2024-03-02)
106112

107-
- Constructor Arguments: Support for constructor arguments added to dependency registration.
113+
- **Constructor Arguments**: Support for constructor arguments added to dependency registration.
108114

109115
### [1.0.0-alpha.3](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.3) (2024-03-02)
110116

111117
- **Breaking Change**: Starting from this version, the `@inject` decorator can only be used on static class methods and class methods. It can't be used on instance methods anymore.
112-
- Documentation Update: The documentation has been updated to reflect the new restriction on the usage of the decorator.
118+
- **Documentation Update**: The documentation has been updated to reflect the new restriction on the usage of the decorator.
113119

114120
### [1.0.0-alpha.2](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.2) (2024-02-27)
115121

116-
- Python Version Support: Added support for Python versions 3.7, 3.9, 3.10, 3.11, and 3.12.
117-
- New Feature: Method Injection with Decorator: Introduced a new feature allowing method injection using the @inject decorator. Dependencies can now be injected into an instance method, providing more flexibility in managing dependencies within class instance methods.
118-
- New Feature: Multiple Containers: Enhanced the library to support multiple containers. Users can now create and manage multiple dependency containers, enabling better organization and separation of dependencies for different components or modules.
119-
- Documentation Update: Expanded and improved the documentation to include details about the newly added method injection feature and additional usage examples. Users can refer to the latest documentation at readthedocs for comprehensive guidance.
122+
- **Python Version Support**: Added support for Python versions 3.7, 3.9, 3.10, 3.11, and 3.12.
123+
- **New Feature**: Method Injection with Decorator: Introduced a new feature allowing method injection using the @inject decorator. Dependencies can now be injected into an instance method, providing more flexibility in managing dependencies within class instance methods.
124+
- **New Feature**: Multiple Containers: Enhanced the library to support multiple containers. Users can now create and manage multiple dependency containers, enabling better organization and separation of dependencies for different components or modules.
125+
- **Documentation Update**: Expanded and improved the documentation to include details about the newly added method injection feature and additional usage examples. Users can refer to the latest documentation at readthedocs for comprehensive guidance.
120126

121127
### [1.0.0-alpha.1](https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.1) (2024-02-25)
122128

123-
- Initial alpha release.
124-
- Added Dependency Container: The library includes a dependency container for managing object dependencies.
125-
- Added Constructor Injection: Users can leverage constructor injection for cleaner and more modular code.
126-
- Added Dependency Scopes: Define and manage the lifecycle of dependencies with support for different scopes.
127-
- Basic Documentation: An initial set of documentation is provided, giving users an introduction to the library.
128-
- License: Released under the GPL 3 license.
129+
- **Initial alpha release**.
130+
- **Added Dependency Container**: The library includes a dependency container for managing object dependencies.
131+
- **Added Constructor Injection**: Users can leverage constructor injection for cleaner and more modular code.
132+
- **Added Dependency Scopes**: Define and manage the lifecycle of dependencies with support for different scopes.
133+
- **Basic Documentation**: An initial set of documentation is provided, giving users an introduction to the library.
134+
- **License**: Released under the GPL 3 license.

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
version = "1.0"
3636

3737
# The full version, including alpha/beta/rc tags
38-
release = "1.0.0-alpha.8"
38+
release = "1.0.0-alpha.9"
3939

4040

4141
# -- General configuration ---------------------------------------------------

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
py-dependency-injection
66
=======================
77

8-
A prototypical dependency injection library for Python.
8+
A dependency injection library for Python.
99

1010
Purpose
1111
-------

docs/releases.rst

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,32 @@
66
Version History
77
###############
88

9+
**1.0.0-alpha.9 (2024-08-08)**
10+
11+
- **Breaking Change**: Removed constructor injection when resolving dataclasses.
12+
- **Enhancement**: Added dependency container getter and setter for registrations. Also added new `RegistrationSerializer` class for for serializing and deserializing them. These additions provide a more flexible way to interact with the container's registrations.
13+
14+
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.9>`_
15+
916
**1.0.0-alpha.8 (2024-06-07)**
1017

1118
- **Bug Fix**: Fixed an issue in the dependency resolution logic where registered constructor arguments were not properly merged with automatically injected dependencies. This ensures that constructor arguments specified during registration are correctly combined with dependencies resolved by the container.
19+
- **Documentation Update**: The documentation structure has been updated for better organization and ease of understanding.
1220

1321
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.8>`_
1422

1523
**1.0.0-alpha.7 (2024-03-24)**
1624

17-
- Documentation Update: Updated the documentation to provide clearer instructions and more comprehensive examples.
18-
- Preparing for Beta Release: Made necessary adjustments and refinements in preparation for the upcoming first beta release.
25+
- **Documentation Update**: Updated the documentation to provide clearer instructions and more comprehensive examples.
26+
- **Preparing for Beta Release**: Made necessary adjustments and refinements in preparation for the upcoming first beta release.
1927

2028
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.7>`_
2129

2230
**1.0.0-alpha.6 (2024-03-23)**
2331

24-
- Factory Registration: Added support for registering dependencies using factory functions for dynamic instantiation.
25-
- Instance Registration: Enabled registering existing instances as dependencies.
26-
- Tag-based Registration and Resolution: Introduced the ability to register and resolve dependencies using tags for flexible dependency management.
32+
- **Factory Registration**: Added support for registering dependencies using factory functions for dynamic instantiation.
33+
- **Instance Registration**: Enabled registering existing instances as dependencies.
34+
- **Tag-based Registration and Resolution**: Introduced the ability to register and resolve dependencies using tags for flexible dependency management.
2735

2836
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.6>`_
2937

@@ -35,33 +43,33 @@ Version History
3543

3644
**1.0.0-alpha.4 (2024-03-02)**
3745

38-
- Constructor Arguments: Support for constructor arguments added to dependency registration.
46+
- **Constructor Arguments**: Support for constructor arguments added to dependency registration.
3947

4048
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.4>`_
4149

4250
**1.0.0-alpha.3 (2024-03-02)**
4351

4452
- **Breaking Change**: Starting from this version, the `@inject` decorator can only be used on static class methods and class methods. It can't be used on instance methods anymore.
45-
- Documentation Update: The documentation has been updated to reflect the new restriction on the usage of the decorator.
53+
- **Documentation Update**: The documentation has been updated to reflect the new restriction on the usage of the decorator.
4654

4755
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.3>`_
4856

4957
**1.0.0-alpha.2 (2024-02-27)**
5058

51-
- Python Version Support: Added support for Python versions 3.7, 3.9, 3.10, 3.11, and 3.12.
52-
- New Feature: Method Injection with Decorator: Introduced a new feature allowing method injection using the @inject decorator. Dependencies can now be injected into an instance method, providing more flexibility in managing dependencies within class instance methods.
53-
- New Feature: Multiple Containers: Enhanced the library to support multiple containers. Users can now create and manage multiple dependency containers, enabling better organization and separation of dependencies for different components or modules.
54-
- Documentation Update: Expanded and improved the documentation to include details about the newly added method injection feature and additional usage examples. Users can refer to the latest documentation at readthedocs for comprehensive guidance.
59+
- **Python Version Support**: Added support for Python versions 3.7, 3.9, 3.10, 3.11, and 3.12.
60+
- **New Feature**: Method Injection with Decorator: Introduced a new feature allowing method injection using the @inject decorator. Dependencies can now be injected into an instance method, providing more flexibility in managing dependencies within class instance methods.
61+
- **New Feature**: Multiple Containers: Enhanced the library to support multiple containers. Users can now create and manage multiple dependency containers, enabling better organization and separation of dependencies for different components or modules.
62+
- **Documentation Update**: Expanded and improved the documentation to include details about the newly added method injection feature and additional usage examples. Users can refer to the latest documentation at readthedocs for comprehensive guidance.
5563

5664
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.2>`_
5765

5866
**1.0.0-alpha.1 (2024-02-25)**
5967

60-
- Initial alpha release.
61-
- Added Dependency Container: The library includes a dependency container for managing object dependencies.
62-
- Added Constructor Injection: Users can leverage constructor injection for cleaner and more modular code.
63-
- Added Dependency Scopes: Define and manage the lifecycle of dependencies with support for different scopes.
64-
- Basic Documentation: An initial set of documentation is provided, giving users an introduction to the library.
65-
- License: Released under the GPL 3 license.
68+
- **Initial alpha release**.
69+
- **Added Dependency Container**: The library includes a dependency container for managing object dependencies.
70+
- **Added Constructor Injection**: Users can leverage constructor injection for cleaner and more modular code.
71+
- **Added Dependency Scopes**: Define and manage the lifecycle of dependencies with support for different scopes.
72+
- **Basic Documentation**: An initial set of documentation is provided, giving users an introduction to the library.
73+
- **License**: Released under the GPL 3 license.
6674

6775
`View release on GitHub <https://github.com/runemalm/py-dependency-injection/releases/tag/v1.0.0-alpha.1>`_

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
setup(
88
name="py-dependency-injection",
9-
version="1.0.0-alpha.8",
9+
version="1.0.0-alpha.9",
1010
author="David Runemalm, 2024",
1111
author_email="david.runemalm@gmail.com",
12-
description="A prototypical dependency injection library for Python.",
12+
description="A dependency injection library for Python.",
1313
long_description=long_description,
1414
long_description_content_type="text/markdown",
1515
url="https://github.com/runemalm/py-dependency-injection",

src/dependency_injection/container.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import inspect
2+
from dataclasses import is_dataclass
23

34
from typing import Any, Callable, Dict, List, Optional, TypeVar, Type
45

@@ -18,6 +19,7 @@ def __init__(self, name: str = None):
1819
self._registrations = {}
1920
self._singleton_instances = {}
2021
self._scoped_instances = {}
22+
self._has_resolved = False
2123

2224
@classmethod
2325
def get_instance(cls, name: str = None) -> Self:
@@ -29,6 +31,16 @@ def get_instance(cls, name: str = None) -> Self:
2931

3032
return cls._instances[(cls, name)]
3133

34+
def get_registrations(self) -> Dict[Type, Registration]:
35+
return self._registrations
36+
37+
def set_registrations(self, registrations) -> None:
38+
if self._has_resolved:
39+
raise Exception(
40+
"You can't set registrations after a dependency has been resolved."
41+
)
42+
self._registrations = registrations
43+
3244
def register_transient(
3345
self,
3446
dependency: Type,
@@ -98,6 +110,8 @@ def register_instance(
98110
self._singleton_instances[dependency] = instance
99111

100112
def resolve(self, dependency: Type, scope_name: str = DEFAULT_SCOPE_NAME) -> Type:
113+
self._has_resolved = True
114+
101115
if scope_name not in self._scoped_instances:
102116
self._scoped_instances[scope_name] = {}
103117

@@ -176,6 +190,9 @@ def _inject_dependencies(
176190
scope_name: str = None,
177191
constructor_args: Optional[Dict[str, Any]] = None,
178192
) -> Type:
193+
if is_dataclass(implementation):
194+
return implementation() # Do not inject into dataclasses
195+
179196
constructor = inspect.signature(implementation.__init__)
180197
params = constructor.parameters
181198

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pickle
2+
3+
from typing import Dict, Type
4+
5+
from dependency_injection.registration import Registration
6+
7+
8+
class RegistrationSerializer:
9+
@staticmethod
10+
def serialize(registrations) -> bytes:
11+
return pickle.dumps(registrations)
12+
13+
@staticmethod
14+
def deserialize(serialized_state) -> Dict[Type, Registration]:
15+
return pickle.loads(serialized_state)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from dependency_injection.container import DependencyContainer
2+
from dependency_injection.scope import Scope
3+
from unit_test.unit_test_case import UnitTestCase
4+
5+
6+
class TestGetRegistrations(UnitTestCase):
7+
def test_get_registrations_returns_empty_dict_initially(self):
8+
# arrange
9+
dependency_container = DependencyContainer.get_instance()
10+
11+
# act
12+
registrations = dependency_container.get_registrations()
13+
14+
# assert
15+
self.assertEqual(registrations, {})
16+
17+
def test_get_registrations_returns_correct_registrations(self):
18+
# arrange
19+
class Vehicle:
20+
pass
21+
22+
dependency_container = DependencyContainer.get_instance()
23+
dependency_container.register_transient(Vehicle)
24+
25+
# act
26+
registrations = dependency_container.get_registrations()
27+
28+
# assert
29+
self.assertIn(Vehicle, registrations)
30+
self.assertEqual(registrations[Vehicle].dependency, Vehicle)
31+
self.assertEqual(registrations[Vehicle].implementation, Vehicle)
32+
self.assertEqual(registrations[Vehicle].scope, Scope.TRANSIENT)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from dependency_injection.container import DependencyContainer
2+
from unit_test.unit_test_case import UnitTestCase
3+
4+
5+
class TestSetRegistrations(UnitTestCase):
6+
def test_set_registrations_before_first_resolution(self):
7+
# arrange
8+
class Vehicle:
9+
pass
10+
11+
dummy_container = DependencyContainer.get_instance("dummy_container")
12+
dummy_container.register_transient(Vehicle)
13+
new_registrations = dummy_container.get_registrations()
14+
15+
container = DependencyContainer.get_instance()
16+
17+
# act
18+
container.set_registrations(new_registrations) # no exception
19+
20+
def test_not_allowed_to_set_registrations_after_first_resolution(self):
21+
# arrange
22+
class Vehicle:
23+
pass
24+
25+
class Fruit:
26+
pass
27+
28+
dummy_container = DependencyContainer.get_instance("dummy_container")
29+
dummy_container.register_transient(Vehicle)
30+
new_registrations = dummy_container.get_registrations()
31+
32+
container = DependencyContainer.get_instance()
33+
container.register_transient(Fruit)
34+
container.resolve(Fruit)
35+
36+
# act & assert
37+
with self.assertRaises(Exception) as context:
38+
container.set_registrations(new_registrations)
39+
40+
self.assertIn(
41+
"You can't set registrations after a dependency has been resolved.",
42+
str(context.exception),
43+
)

tests/unit_test/container/resolve/test_resolve_with_alias.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
from unit_test.unit_test_case import UnitTestCase
44

5-
from unit_test.container.resolve.vehicle import Vehicle
6-
from unit_test.container.resolve.vehicle import Vehicle as VehicleAlias
5+
from unit_test.container.resolve.test_data.vehicle import Vehicle
6+
from unit_test.container.resolve.test_data.vehicle import Vehicle as VehicleAlias
77

88

99
class TestResolveWithAlias(UnitTestCase):

0 commit comments

Comments
 (0)