Injectable Properties
Fetch dependencies via properties rather than constructor arguments.
Overview
This class allows you to specify dependencies by setting them as class properties instead of constructor arguments. This is common in clearskies as it helps make easily reusable classes - configuration can go in the constructor of the class, allowing the developer to directly instantiate it, and then the DI system will come by afterwards and provide the necessary dependencies.
After adding InjectableProperties as a parent of your class, you have two ways to specify your dependencies:
- By using the classes in the
clearskies.di.inject.*
module. - By directly attaching objects which also use the
InjectableProperties
class.
The following table shows the dependencies that can be injected as properties via the clearskies.di.inject module:
Class | Type | Result |
---|---|---|
clearskies.di.inject.ByClass | N/A | The specified class will be built |
clearskies.di.inject.ByName | N/A | The specified dependnecy name will be built |
clearskies.di.inject.Cursor | N/A | The PyMySQL cursor |
clearskies.di.inject.Di | N/A | The dependency injection container itself |
clearskies.di.inject.Environment | clearskies.Environment | The environment helper |
clearskies.di.inject.InputOutput | clearskies.input_outputs.InputOutput | The InputOutput object for the current request |
clearskies.di.inject.Now | datetime.datetime | The current time (no timezone) |
clearskies.di.inject.Requests | requests.Session | A requests session |
clearskies.di.inject.Utcnow | datetime.datetime | The current time (tzinfo=datetime.timezone.utc) |
Note: now/utcnow are not cached, so you’ll get the current time everytime you get a value out of the class property, unless a specific time has been set on the dependency injection container.
Here’s an example:
import clearskies
import time
import clearskies.decorators
class MyOtherThing(clearskies.di.InjectableProperties):
now = clearskies.di.inject.Now()
class ReusableClass(clearskies.Configurable, clearskies.di.InjectableProperties):
my_int = clearskies.configs.Integer(required=True)
some_number = clearskies.di.inject.ByName("some_number")
my_other_thing = clearskies.di.inject.ByClass(MyOtherThing)
@clearskies.decorators.parameters_to_properties
def __init__(self, my_int: int):
self.finalize_and_validate_configuration()
def my_value(self) -> int:
return self.my_int * self.some_number
class MyClass(clearskies.di.InjectableProperties):
reusable = ReusableClass(5)
class MyOtherClass(clearskies.di.InjectableProperties):
reusable = ReusableClass(10)
di = clearskies.di.Di(
bindings={
"some_number": 10,
}
)
my_class = di.build(MyClass)
print(my_class.reusable.my_value()) # prints 50
my_other_class = di.build(MyOtherClass)
print(my_other_class.reusable.my_value()) # prints 100
start = my_class.reusable.my_other_thing.now
time.sleep(1)
stop = my_class.reusable.my_other_thing.now
print((stop - start).seconds) # prints 1