Merge pull request #5 from rmk135/scoped_provider

Adding scoped provider with examples
This commit is contained in:
Roman 2015-01-28 00:27:13 +02:00
commit 2c449e9820
6 changed files with 207 additions and 0 deletions

View File

@ -14,6 +14,7 @@ Concept example of objects catalogs.
from objects import AbstractCatalog from objects import AbstractCatalog
from objects.providers import Singleton, NewInstance from objects.providers import Singleton, NewInstance
from objects.injections import InitArg, Attribute from objects.injections import InitArg, Attribute
import sqlite3 import sqlite3
@ -121,6 +122,7 @@ Concept example of objects overrides.
from objects import AbstractCatalog, overrides from objects import AbstractCatalog, overrides
from objects.providers import Singleton, NewInstance from objects.providers import Singleton, NewInstance
from objects.injections import InitArg, Attribute from objects.injections import InitArg, Attribute
import sqlite3 import sqlite3
@ -183,6 +185,7 @@ Concept example of objects catalogs.
from objects import AbstractCatalog from objects import AbstractCatalog
from objects.providers import Singleton, NewInstance, ExternalDependency from objects.providers import Singleton, NewInstance, ExternalDependency
from objects.injections import InitArg, Attribute from objects.injections import InitArg, Attribute
import sqlite3 import sqlite3
@ -231,3 +234,79 @@ assert a1 is not a2
assert b1 is not b2 assert b1 is not b2
assert a1.db is a2.db is b1.db is b2.db is Catalog.database() 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()
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)
```

View File

@ -5,6 +5,7 @@ Concept example of objects catalogs.
from objects import AbstractCatalog from objects import AbstractCatalog
from objects.providers import Singleton, NewInstance from objects.providers import Singleton, NewInstance
from objects.injections import InitArg, Attribute from objects.injections import InitArg, Attribute
import sqlite3 import sqlite3

View File

@ -5,6 +5,7 @@ Concept example of objects catalogs.
from objects import AbstractCatalog from objects import AbstractCatalog
from objects.providers import Singleton, NewInstance, ExternalDependency from objects.providers import Singleton, NewInstance, ExternalDependency
from objects.injections import InitArg, Attribute from objects.injections import InitArg, Attribute
import sqlite3 import sqlite3

View File

@ -6,6 +6,7 @@ Concept example of objects overrides.
from objects import AbstractCatalog, overrides from objects import AbstractCatalog, overrides
from objects.providers import Singleton, NewInstance from objects.providers import Singleton, NewInstance
from objects.injections import InitArg, Attribute from objects.injections import InitArg, Attribute
import sqlite3 import sqlite3

View File

@ -0,0 +1,71 @@
"""
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()
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)

View File

@ -108,6 +108,60 @@ class Singleton(NewInstance):
self.instance = super(Singleton, self).__call__(*args, **kwargs) self.instance = super(Singleton, self).__call__(*args, **kwargs)
return self.instance return self.instance
def _reset_instance(self):
"""
Resets instance.
"""
self.instance = None
class Scoped(Singleton):
"""
Scoped provider will create instance once for every scope and return it on every call.
"""
def __init__(self, *args, **kwargs):
"""
Initializer.
"""
self.is_in_scope = None
super(Scoped, self).__init__(*args, **kwargs)
def in_scope(self):
"""
Sets provider in "in scope" state.
"""
self.is_in_scope = True
self._reset_instance()
def out_of_scope(self):
"""
Sets provider in "out of scope" state.
"""
self.is_in_scope = False
self._reset_instance()
def __call__(self, *args, **kwargs):
"""
Returns provided instance.
"""
if not self.is_in_scope:
raise RuntimeError('Trying to provide {} while provider is not in scope'.format(self.provides))
return super(Scoped, self).__call__(*args, **kwargs)
def __enter__(self):
"""
With __enter__() implementation. Makes provider to be in scope.
"""
self.in_scope()
return self
def __exit__(self, *_):
"""
With __exit__() implementation. Makes provider to be out of scope.
"""
self.out_of_scope()
class ExternalDependency(Provider): class ExternalDependency(Provider):
""" """