diff --git a/README.md b/README.md index 48405078..64fccd82 100644 --- a/README.md +++ b/README.md @@ -7,430 +7,64 @@ Objects **Python catalogs of objects providers** -Example of objects catalog definition and usage: - ```python -""" -Concept example of objects catalogs. -""" +"""Concept example of Objects.""" from objects import AbstractCatalog -from objects.providers import Singleton, NewInstance -from objects.injections import InitArg, Attribute -import sqlite3 +from objects.providers import Singleton +from objects.providers import NewInstance - -# Some example classes. -class ObjectA(object): - def __init__(self, db): - self.db = db - - -class ObjectB(object): - def __init__(self, a, db): - self.a = a - self.db = db - - -# Catalog of objects providers. -class Catalog(AbstractCatalog): - """ - Objects catalog. - """ - - database = Singleton(sqlite3.Connection, - InitArg('database', ':memory:'), - Attribute('row_factory', sqlite3.Row)) - """ :type: (objects.Provider) -> sqlite3.Connection """ - - object_a = NewInstance(ObjectA, - InitArg('db', database)) - """ :type: (objects.Provider) -> ObjectA """ - - object_b = NewInstance(ObjectB, - InitArg('a', object_a), - InitArg('db', database)) - """ :type: (objects.Provider) -> ObjectB """ - - -# Catalog static provides. -a1, a2 = Catalog.object_a(), Catalog.object_a() -b1, b2 = Catalog.object_b(), Catalog.object_b() - -# Some asserts. -assert a1 is not a2 -assert b1 is not b2 -assert a1.db is a2.db is b1.db is b2.db is Catalog.database() - - -# Dependencies injection (The Python Way) into class. -class Consumer(object): - - dependencies = Catalog(Catalog.object_a, - Catalog.object_b) - - def test(self): - a1 = self.dependencies.object_a() - a2 = self.dependencies.object_a() - - b1 = self.dependencies.object_b() - b2 = self.dependencies.object_b() - - # Some asserts. - assert a1 is not a2 - assert b1 is not b2 - assert a1.db is a2.db is b1.db is b2.db - - try: - self.dependencies.database() - except AttributeError: - pass - else: - raise Exception('Database is not listed as a dependency') - -Consumer().test() - - -# Dependencies injection (The Python Way) into a callback. -def consumer_callback(dependencies=Catalog(Catalog.object_a, - Catalog.object_b)): - a1 = dependencies.object_a() - a2 = dependencies.object_a() - - b1 = dependencies.object_b() - b2 = dependencies.object_b() - - # Some asserts. - assert a1 is not a2 - assert b1 is not b2 - assert a1.db is a2.db is b1.db is b2.db - - try: - dependencies.database() - except AttributeError: - pass - else: - raise Exception('Database is not listed as a dependency') -``` - -Example of overriding object providers: - -```python -""" -Concept example of objects overrides. -""" - - -from objects import AbstractCatalog, overrides -from objects.providers import Singleton, NewInstance -from objects.injections import InitArg, Attribute - -import sqlite3 - - -# Some example class. -class ObjectA(object): - def __init__(self, db): - self.db = db - - -# Mock of example class. -class ObjectAMock(ObjectA): - pass - - -# Catalog of objects providers. -class Catalog(AbstractCatalog): - """ - Objects catalog. - """ - - database = Singleton(sqlite3.Connection, - InitArg('database', ':memory:'), - Attribute('row_factory', sqlite3.Row)) - """ :type: (objects.Provider) -> sqlite3.Connection """ - - object_a = NewInstance(ObjectA, - InitArg('db', database)) - """ :type: (objects.Provider) -> ObjectA """ - - -# Overriding Catalog by SandboxCatalog with some mocks. -@overrides(Catalog) -class SandboxCatalog(Catalog): - """ - Sandbox objects catalog with some mocks. - """ - - object_a = NewInstance(ObjectAMock, - InitArg('db', Catalog.database)) - """ :type: (objects.Provider) -> ObjectA """ - - -# Catalog static provides. -a1 = Catalog.object_a() -a2 = Catalog.object_a() - -# Some asserts. -assert isinstance(a1, ObjectAMock) -assert isinstance(a2, ObjectAMock) -assert a1 is not a2 -assert a1.db is a2.db is Catalog.database() -``` - -Example of objects catalog external dependency: - -```python -""" -Concept example of objects catalogs. -""" - -from objects import AbstractCatalog -from objects.providers import Singleton, NewInstance, ExternalDependency -from objects.injections import InitArg, Attribute - -import sqlite3 - - -# Some example classes. -class ObjectA(object): - def __init__(self, db): - self.db = db - - -class ObjectB(object): - def __init__(self, a, db): - self.a = a - self.db = db - - -# Catalog of objects providers. -class Catalog(AbstractCatalog): - """ - Objects catalog. - """ - - database = ExternalDependency(instance_of=sqlite3.Connection) - """ :type: (objects.Provider) -> sqlite3.Connection """ - - object_a = NewInstance(ObjectA, - InitArg('db', database)) - """ :type: (objects.Provider) -> ObjectA """ - - object_b = NewInstance(ObjectB, - InitArg('a', object_a), - InitArg('db', database)) - """ :type: (objects.Provider) -> ObjectB """ - - -# Satisfaction of external dependency. -Catalog.database.satisfy(Singleton(sqlite3.Connection, - InitArg('database', ':memory:'), - Attribute('row_factory', sqlite3.Row))) - -# Catalog static provides. -a1, a2 = Catalog.object_a(), Catalog.object_a() -b1, b2 = Catalog.object_b(), Catalog.object_b() - -# Some asserts. -assert a1 is not a2 -assert b1 is not b2 -assert a1.db is a2.db is b1.db is b2.db is Catalog.database() -``` - -Example of objects catalog with scoped provider: - -```python -""" -Scoped provider examples. -""" - -from objects import AbstractCatalog -from objects.providers import Singleton, Scoped -from objects.injections import InitArg, Attribute - -import sqlite3 - - -class ObjectA(object): - def __init__(self, db): - self.db = db - - -# Catalog of objects providers. -class Catalog(AbstractCatalog): - """ - Objects catalog. - """ - - database = Singleton(sqlite3.Connection, - InitArg('database', ':memory:'), - Attribute('row_factory', sqlite3.Row)) - """ :type: (objects.Provider) -> sqlite3.Connection """ - - object_a = Scoped(ObjectA, - InitArg('db', database)) - """ :type: (objects.Provider) -> ObjectA """ - - -# Making scope using `with` statement. -with Catalog.object_a as object_a_provider: - object_a1 = object_a_provider() - object_a2 = object_a_provider() - - assert object_a1 is object_a2 - assert object_a1.db is object_a2.db - -# Making another one scope using `with` statement. -with Catalog.object_a as object_a_provider: - object_a3 = object_a_provider() - object_a4 = object_a_provider() - - assert object_a3 is object_a4 - assert object_a3.db is object_a4.db - - assert (object_a1 is not object_a3) and \ - (object_a1 is not object_a4) - assert (object_a2 is not object_a3) and \ - (object_a2 is not object_a4) - - -# Making one more scope using provider methods. -Catalog.object_a.in_scope() - -object_a5 = Catalog.object_a() -object_a6 = Catalog.object_a() - -Catalog.object_a.out_of_scope() - -assert object_a5 is object_a6 -assert object_a5.db is object_a6.db - -assert (object_a1 is not object_a3) and \ - (object_a1 is not object_a4) and \ - (object_a1 is not object_a5) and \ - (object_a1 is not object_a6) -assert (object_a2 is not object_a3) and \ - (object_a2 is not object_a4) and \ - (object_a2 is not object_a5) and \ - (object_a2 is not object_a6) -``` - -Example of objects catalog with callable provider: - -```python -""" -Callable provider examples. -""" - -from objects import AbstractCatalog -from objects.providers import Singleton, Callable -from objects.injections import Injection, InitArg, Attribute - -import sqlite3 - - -# Some example function. -def consuming_function(arg, db): - return arg, db - - -# Catalog of objects providers. -class Catalog(AbstractCatalog): - """ - Objects catalog. - """ - - database = Singleton(sqlite3.Connection, - InitArg('database', ':memory:'), - Attribute('row_factory', sqlite3.Row)) - """ :type: (objects.Provider) -> sqlite3.Connection """ - - consuming_function = Callable(consuming_function, - Injection('db', database)) - """ :type: (objects.Provider) -> consuming_function """ - - -# Some calls. -arg1, db1 = Catalog.consuming_function(1) -arg2, db2 = Catalog.consuming_function(2) -arg3, db3 = Catalog.consuming_function(3) - -# Some asserts. -assert db1 is db2 is db3 -assert arg1 == 1 -assert arg2 == 2 -assert arg3 == 3 -``` - -Example of objects catalog with config provider: - -```python -""" -Config provider examples. -""" - -from objects import AbstractCatalog -from objects.providers import Config, NewInstance from objects.injections import InitArg +from objects.injections import Attribute + +import sqlite3 -# Some example class. class ObjectA(object): - def __init__(self, setting_one, setting_two, setting_three): - self.setting_one = setting_one - self.setting_two = setting_two - self.setting_three = setting_three + + """Example class ObjectA, that has dependency on database.""" + + def __init__(self, db): + """Initializer.""" + self.db = db + + +class ObjectB(object): + + """Example class ObjectB, that has dependencies on ObjectA and database.""" + + def __init__(self, a, db): + """Initializer.""" + self.a = a + self.db = db -# Catalog of objects providers. class Catalog(AbstractCatalog): - """ - Objects catalog. - """ - config = Config() - """ :type: (objects.Config) """ + """Catalog of objects providers.""" + + database = Singleton(sqlite3.Connection, + InitArg('database', ':memory:'), + Attribute('row_factory', sqlite3.Row)) + """:type: (objects.Provider) -> sqlite3.Connection""" object_a = NewInstance(ObjectA, - InitArg('setting_one', config.SETTING_ONE), - InitArg('setting_two', config.SETTING_TWO), - InitArg('setting_three', config.GLOBAL.SETTING_THREE)) - """ :type: (objects.Provider) -> ObjectA """ + InitArg('db', database)) + """:type: (objects.Provider) -> ObjectA""" + + object_b = NewInstance(ObjectB, + InitArg('a', object_a), + InitArg('db', database)) + """:type: (objects.Provider) -> ObjectB""" -# Setting config value and making some tests. -Catalog.config.update_from({ - 'SETTING_ONE': 1, - 'SETTING_TWO': 2, - 'GLOBAL': { - 'SETTING_THREE': 3 - } -}) +# Catalog static provides. +a1, a2 = Catalog.object_a(), Catalog.object_a() +b1, b2 = Catalog.object_b(), Catalog.object_b() -object_a1 = Catalog.object_a() - -assert object_a1.setting_one == 1 -assert object_a1.setting_two == 2 -assert object_a1.setting_three == 3 - -# Changing config value one more time and making some tests. -Catalog.config.update_from({ - 'SETTING_ONE': 11, - 'SETTING_TWO': 22, - 'GLOBAL': { - 'SETTING_THREE': 33 - } -}) - -object_a2 = Catalog.object_a() - -assert object_a2.setting_one == 11 -assert object_a2.setting_two == 22 -assert object_a2.setting_three == 33 - -assert object_a1.setting_one == 1 -assert object_a1.setting_two == 2 -assert object_a1.setting_three == 3 +# Some asserts. +assert a1 is not a2 +assert b1 is not b2 +assert a1.db is a2.db is b1.db is b2.db is Catalog.database() ``` diff --git a/examples/concept.py b/examples/concept.py index d3c4de5d..cb9353fb 100644 --- a/examples/concept.py +++ b/examples/concept.py @@ -1,4 +1,4 @@ -"""Concept example of objects catalogs.""" +"""Concept example of `Objects`.""" from objects import AbstractCatalog @@ -57,58 +57,3 @@ b1, b2 = Catalog.object_b(), Catalog.object_b() assert a1 is not a2 assert b1 is not b2 assert a1.db is a2.db is b1.db is b2.db is Catalog.database() - - -# Dependencies injection (The Python Way) into class. -class Consumer(object): - - """Example consumer class.""" - - dependencies = Catalog(Catalog.object_a, - Catalog.object_b) - - def example(self): - """Example method.""" - a1 = self.dependencies.object_a() - a2 = self.dependencies.object_a() - - b1 = self.dependencies.object_b() - b2 = self.dependencies.object_b() - - # Some asserts. - assert a1 is not a2 - assert b1 is not b2 - assert a1.db is a2.db is b1.db is b2.db - - try: - self.dependencies.database() - except AttributeError: - pass - else: - raise Exception('Database is not listed as a dependency') - - -Consumer().example() - - -# Dependencies injection (The Python Way) into a callback. -def consumer_callback(dependencies=Catalog(Catalog.object_a, - Catalog.object_b)): - """Example function.""" - a1 = dependencies.object_a() - a2 = dependencies.object_a() - - b1 = dependencies.object_b() - b2 = dependencies.object_b() - - # Some asserts. - assert a1 is not a2 - assert b1 is not b2 - assert a1.db is a2.db is b1.db is b2.db - - try: - dependencies.database() - except AttributeError: - pass - else: - raise Exception('Database is not listed as a dependency') diff --git a/examples/usage.py b/examples/usage.py new file mode 100644 index 00000000..2cc9bfa1 --- /dev/null +++ b/examples/usage.py @@ -0,0 +1,104 @@ +"""Concept example of objects catalogs.""" + +from objects import AbstractCatalog + +from objects.providers import Singleton +from objects.providers import NewInstance + +from objects.injections import InitArg +from objects.injections import Attribute + +import sqlite3 + + +class ObjectA(object): + + """Example class ObjectA, that has dependency on database.""" + + def __init__(self, db): + """Initializer.""" + self.db = db + + +class ObjectB(object): + + """Example class ObjectB, that has dependencies on ObjectA and database.""" + + def __init__(self, a, db): + """Initializer.""" + self.a = a + self.db = db + + +class Catalog(AbstractCatalog): + + """Catalog of objects providers.""" + + database = Singleton(sqlite3.Connection, + InitArg('database', ':memory:'), + Attribute('row_factory', sqlite3.Row)) + """:type: (objects.Provider) -> sqlite3.Connection""" + + object_a = NewInstance(ObjectA, + InitArg('db', database)) + """:type: (objects.Provider) -> ObjectA""" + + object_b = NewInstance(ObjectB, + InitArg('a', object_a), + InitArg('db', database)) + """:type: (objects.Provider) -> ObjectB""" + + +# Dependencies injection into class. +class Consumer(object): + + """Example consumer class.""" + + dependencies = Catalog(Catalog.object_a, + Catalog.object_b) + + def example(self): + """Example method.""" + a1 = self.dependencies.object_a() + a2 = self.dependencies.object_a() + + b1 = self.dependencies.object_b() + b2 = self.dependencies.object_b() + + # Some asserts. + assert a1 is not a2 + assert b1 is not b2 + assert a1.db is a2.db is b1.db is b2.db + + try: + self.dependencies.database() + except AttributeError: + pass + else: + raise Exception('Database is not listed as a dependency') + + +Consumer().example() + + +# Dependencies injection (The Python Way) into a callback. +def consumer_callback(dependencies=Catalog(Catalog.object_a, + Catalog.object_b)): + """Example function.""" + a1 = dependencies.object_a() + a2 = dependencies.object_a() + + b1 = dependencies.object_b() + b2 = dependencies.object_b() + + # Some asserts. + assert a1 is not a2 + assert b1 is not b2 + assert a1.db is a2.db is b1.db is b2.db + + try: + dependencies.database() + except AttributeError: + pass + else: + raise Exception('Database is not listed as a dependency')