@@ -12,6 +12,8 @@ A simple Python dependency injection framework.
1212
1313** This project is under active development. The following example does not represent the final state for the project.**
1414
15+ ### Dependency Injection
16+
1517The injection framework is configured to inject any default values for method arguments that are instances
1618of ` providers.Provider ` .
1719
@@ -21,7 +23,7 @@ arguments at runtime.
2123All dependency injection is lazily evaluated so providers are only evaluated when a method is called. This approach is
2224optimal as it reduces necessary computation for expensive services and reduces
2325
24- ### Decorator Injection
26+ #### Decorator Injection
2527
2628With this approach you can automatically inject functions at load time using the ` @wiring.injected ` decorator.
2729
@@ -30,7 +32,7 @@ from pif import wiring, providers
3032
3133
3234@wiring.injected # <- automatically injects providers.Provider default arguments!
33- def my_function (a : str = providers.Singleton [str ](lambda : " hello world" )):
35+ def my_function (a : str = providers.Factory [str ](lambda : " hello world" )):
3436 return a
3537
3638
@@ -46,7 +48,7 @@ With this approach you can wire all methods in the specified modules.
4648from pif import wiring, providers
4749
4850
49- def my_function (a : str = providers.Singleton [str ](lambda : " hello world" )):
51+ def my_function (a : str = providers.Factory [str ](lambda : " hello world" )):
5052 return a
5153
5254
@@ -56,6 +58,65 @@ if __name__ == "__main__":
5658 assert " hello world" == my_function()
5759```
5860
61+ ### Overriding
62+
63+ This package provides a simple mechanism to override providers. This can be very useful when it comes to mocking
64+ services for testing or dynamically patching application behavior based on application configuration.
65+
66+ #### Standard Overriding
67+
68+ If you want to patch a value all you need to do is call ` .override() ` on the provider in question.
69+
70+ ``` python
71+ from pif import wiring, providers
72+
73+ StringProvider = providers.Factory[str ](lambda : " hello world" )
74+
75+
76+ @wiring.injected
77+ def my_function (a : str = StringProvider):
78+ return a
79+
80+
81+ if __name__ == " __main__" :
82+ assert " hello world" == my_function()
83+
84+ override = StringProvider.override(providers.Factory[str ](lambda : " overridden_1" ))
85+
86+ assert " overridden_1"
87+ ```
88+
89+ ### Context Managers
90+
91+ If you want more control around the override lifecycles then you may use the ` Override ` context manager.
92+
93+ ``` python
94+ from pif import wiring, providers
95+
96+ StringProvider = providers.Factory[str ](lambda : " hello world" )
97+
98+
99+ @wiring.injected
100+ def my_function (a : str = StringProvider):
101+ return a
102+
103+
104+ if __name__ == " __main__" :
105+ assert " hello world" == my_function()
106+
107+ OverrideProvider = providers.Factory[str ](lambda : " overridden_1" )
108+
109+ with StringProvider.override(OverrideProvider):
110+ assert " overridden_1" == my_function()
111+
112+ with OverrideProvider.override(providers.Factory[str ](" overridden_2" )):
113+ assert " overridden_2" == my_function() # You can even stack overrides!!
114+
115+ assert " overridden_1" == my_function()
116+
117+ assert " hello world" == my_function()
118+ ```
119+
59120## Authors
60121
61122| [ ![ Zac Scott] ( https://avatars.githubusercontent.com/u/38968222?s=128&v=4 )] ( https://github.com/scottzach1 ) |
0 commit comments