Skip to main content

Super Simple Dependency Injector

Project description

b'# SSDI (Super Simple Dependency Injector)\r\n\r\nSSDI is an incredibly simple class that uses Python 3 type annotations to give simple dependency injection.\r\nIt provides an injector class that automatically resolves dependencies based on type.\r\nIt works with base classes and abstract base classes.\r\n\r\nIn case of multiple of the same type it will chose the first added type.\r\n\r\nIt is, as the name indicates, really a very simple injector!\r\n\r\n# Requirements\r\nAs the class uses type annotations, it is required to use Python 3.x+\r\n\r\nThere are further requirements to how you code your classes. This will be covered in usage and examples.\r\n\r\n# Installation\r\n## pip installation\r\n\r\npip install ssdi\r\n\r\nor\r\n\r\npython -m pip install ssdi\r\n\r\n\r\n# Usage\r\n\r\nThere are some simple requirements for using ssdi:\r\n\r\n* Type annotations must be used for parameters\r\n* Named parameters given must not be the same name as the classes to be injected\r\n* There cannot be more than one of a type in the injector\r\n * truth be told there can, but then only the first presented class will be used.\r\n\r\nBelow you see a simple example of using the Injector class.\r\nIt is shown that you can pass parameters and named parameters to the classes.\r\n\r\nFor a more real life example see the examples section of this document. \r\n\r\npython\r\nfrom ssdi import Injector\r\n\r\nclass BaseClass():\r\n def logic(self) -> None:\r\n print("BaseClass logic")\r\n pass\r\n\r\nclass ChildClass(BaseClass):\r\n def __init__(self, param: int)\r\n self.param = param\r\n\r\n def logic(self) -> None:\r\n super().logic()\r\n print("ChildClass logic: ", self.param)\r\n pass\r\n\r\nclass OtherClass():\r\n def __init__(self, param: int, some_class: BaseClass, named_param: str = "foo") -> None:\r\n self.some_class = some_class\r\n self.param = param\r\n self.named_param = named_param\r\n\r\n def logic(self) -> None:\r\n self.some_class.logic()\r\n print("OtherClass logic: ", self.param, self.named_param)\r\n\r\nif __name__ == "__main__":\r\n injector = Injector()\r\n\r\n injector.add(ChildClass, 123)\r\n injector.add(OtherClass, 456, named_param="bar")\r\n\r\n other_class = injector.get(OtherClass)\r\n other_class.logic()\r\n\r\n\r\ngives output:\r\n\r\n\r\nBaseClass logic\r\nChildClass logic 123\r\nOtherClass logic 456 bar\r\n\r\n\r\n# Examples\r\n## Logging classes\r\n\r\nImagine you have a larger application. For this you have implemented custom logging logic. For this you have a logging object that can be given an instance of various classes. To begin with you just log to stdout using print statements. \r\n\r\nThen after some months you find a need to log to a database. This will require new logic. \r\nNow instead of replacing all the instances of TestLogger - you instead use SSDI and simply need to replace it once - the place where you have given the injector your class. \r\nThe rest of the class instantiations - all your 100's of classes of business logic - will now automatically be instantiated with the new DatabaseLogger class instead, saving you time and reducing chances of bugs.\r\n\r\n\r\nFirst we have our loggers defined:\r\n\r\n\r\nFile logger.py\r\npython\r\nimport ABC\r\n\r\nclass Logger(ABC.abc):\r\n @abstractmethod\r\n def log(message: str) -> None:\r\n """ \r\n This functions implementation will log a message\r\n """\r\n pass\r\n\r\nclass TestLogger(Logger):\r\n def log(message: str) -> None:\r\n """\r\n This function logs to a debug interface, f.x. to stdout\r\n """\r\n print(message)\r\n\r\nclass DatabaseLogger(Logger):\r\n def log(message: str) -> None:\r\n """\r\n This function logs to a database\r\n """\r\n # Logic to log to database\r\n pass\r\n\r\n\r\n\r\n\r\nThen we have all our business logic:\r\n\r\nFile business.py\r\npython\r\nfrom logger import Logger\r\n\r\nclass BusinessLogicOne():\r\n def __init__(self, logger: Logger) -> None:\r\n self.logger = logger\r\n \r\n def logic(self):\r\n self.logger.log("Some log message")\r\n \r\nclass BusinessLogicTwo():\r\n def __init__(self, logger: Logger) -> None:\r\n self.logger = logger\r\n \r\n def logic(self):\r\n self.logger.log("Some log message")\r\n \r\nclass BusinessLogicN():\r\n def __init__(self, logger: Logger) -> None:\r\n self.logger = logger\r\n \r\n def logic(self):\r\n self.logger.log("Some log message")\r\n\r\n\r\nAnd then finally we have a class that uses SSDI. See here that no matter how many classes uses the logger class instantiation, we still only need to change it one place when we instead implement out database logger. See if you can change the code below to use the new logger - the promise is that it really is super simple.\r\n\r\nFile main.py\r\n\r\npython\r\nfrom ssdi import Injector\r\n\r\nfrom business import *\r\nfrom logger import *\r\n\r\nif __name__ == "__main__":\r\n injector = Injector()\r\n injector.add(BusinessLogicOne)\r\n injector.add(BusinessLogicTwo)\r\n injector.add(BusinessLogicN)\r\n injector.add(TestLogger)\r\n\r\n business_logic_one = injector.get(BusinessLogicOne)\r\n business_logic_one.logic()\r\n \r\n business_logic_two = injector.get(BusinessLogicTwo)\r\n business_logic_two.logic()\r\n \r\n business_logic_n = injector.get(BusinessLogicN)\r\n business_logic_n.logic()\r\n\r\n\r\n\r\n# Tests\r\nSeveral unit tests have been created. These are created to be tested using pytest. Please see the file test_injector.py on github () for all the tests.\r\n\r\n# Contact\r\nComment on github () or email to dadeerh91@gmail.com'

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ssdi-0.1.tar.gz (3.8 kB view hashes)

Uploaded Source

Built Distribution

ssdi-0.1-py3-none-any.whl (4.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page