Copying providers with sys stream injections (#211)

* Add fix + tests

* Update changelog
This commit is contained in:
Roman Mogylatov 2018-12-22 20:37:53 +02:00 committed by GitHub
parent dc85b2e981
commit f4f773be5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 609 additions and 314 deletions

View File

@ -7,6 +7,11 @@ that were made in every particular version.
From version 0.7.6 *Dependency Injector* framework strictly From version 0.7.6 *Dependency Injector* framework strictly
follows `Semantic versioning`_ follows `Semantic versioning`_
Development version
-------------------
- Fix issue with copying providers that have system streams injections
(``sys.stdin``, ``sys.stdout`` and ``sys.stderr``).
3.14.2 3.14.2
------ ------
- Set Cython ``language_level=2``. - Set Cython ``language_level=2``.

File diff suppressed because it is too large Load Diff

View File

@ -2075,4 +2075,19 @@ cpdef str represent_provider(object provider, object provides):
cpdef object deepcopy(object instance, dict memo=None): cpdef object deepcopy(object instance, dict memo=None):
"""Return full copy of provider or container with providers.""" """Return full copy of provider or container with providers."""
if memo is None:
memo = dict()
__add_sys_streams(memo)
return copy.deepcopy(instance, memo) return copy.deepcopy(instance, memo)
def __add_sys_streams(memo):
"""Add system streams to memo dictionary.
This helps to avoid copying of system streams while making a deepcopy of
objects graph.
"""
memo[id(sys.stdin)] = sys.stdin
memo[id(sys.stdout)] = sys.stdout
memo[id(sys.stderr)] = sys.stderr

View File

@ -1,5 +1,7 @@
"""Dependency injector callable providers unit tests.""" """Dependency injector callable providers unit tests."""
import sys
import unittest2 as unittest import unittest2 as unittest
from dependency_injector import ( from dependency_injector import (
@ -167,6 +169,18 @@ class CallableTests(unittest.TestCase):
self.assertIsNot(object_provider, object_provider_copy) self.assertIsNot(object_provider, object_provider_copy)
self.assertIsInstance(object_provider_copy, providers.Object) self.assertIsInstance(object_provider_copy, providers.Object)
def test_deepcopy_with_sys_streams(self):
provider = providers.Callable(_example)
provider.add_args(sys.stdin)
provider.add_kwargs(a2=sys.stdout)
provider_copy = providers.deepcopy(provider)
self.assertIsNot(provider, provider_copy)
self.assertIsInstance(provider_copy, providers.Callable)
self.assertIs(provider.args[0], sys.stdin)
self.assertIs(provider.kwargs['a2'], sys.stdout)
def test_repr(self): def test_repr(self):
provider = providers.Callable(_example) provider = providers.Callable(_example)

View File

@ -1,5 +1,7 @@
"""Dependency injector factory providers unit tests.""" """Dependency injector factory providers unit tests."""
import sys
import unittest2 as unittest import unittest2 as unittest
from dependency_injector import ( from dependency_injector import (
@ -321,6 +323,20 @@ class FactoryTests(unittest.TestCase):
self.assertIsNot(object_provider, object_provider_copy) self.assertIsNot(object_provider, object_provider_copy)
self.assertIsInstance(object_provider_copy, providers.Object) self.assertIsInstance(object_provider_copy, providers.Object)
def test_deepcopy_with_sys_streams(self):
provider = providers.Factory(Example)
provider.add_args(sys.stdin)
provider.add_kwargs(a2=sys.stdout)
provider.add_attributes(a3=sys.stderr)
provider_copy = providers.deepcopy(provider)
self.assertIsNot(provider, provider_copy)
self.assertIsInstance(provider_copy, providers.Factory)
self.assertIs(provider.args[0], sys.stdin)
self.assertIs(provider.kwargs['a2'], sys.stdout)
self.assertIs(provider.attributes['a3'], sys.stderr)
def test_repr(self): def test_repr(self):
provider = providers.Factory(Example) provider = providers.Factory(Example)

View File

@ -1,5 +1,7 @@
"""Dependency injector singleton providers unit tests.""" """Dependency injector singleton providers unit tests."""
import sys
import unittest2 as unittest import unittest2 as unittest
from dependency_injector import ( from dependency_injector import (
@ -322,6 +324,20 @@ class _BaseSingletonTestCase(object):
self.assertIsNot(object_provider, object_provider_copy) self.assertIsNot(object_provider, object_provider_copy)
self.assertIsInstance(object_provider_copy, providers.Object) self.assertIsInstance(object_provider_copy, providers.Object)
def test_deepcopy_with_sys_streams(self):
provider = providers.Singleton(Example)
provider.add_args(sys.stdin)
provider.add_kwargs(a2=sys.stdout)
provider.add_attributes(a3=sys.stderr)
provider_copy = providers.deepcopy(provider)
self.assertIsNot(provider, provider_copy)
self.assertIsInstance(provider_copy, providers.Singleton)
self.assertIs(provider.args[0], sys.stdin)
self.assertIs(provider.kwargs['a2'], sys.stdout)
self.assertIs(provider.attributes['a3'], sys.stderr)
def test_reset(self): def test_reset(self):
provider = self.singleton_cls(object) provider = self.singleton_cls(object)