2019-08-09 05:12:31 +03:00
import pytest
from awxkit . utils import filter_by_class
2019-08-12 23:41:31 +03:00
from awxkit . utils . toposort import CircularDependencyError
2019-08-09 05:12:31 +03:00
from awxkit . api . mixins import has_create
class MockHasCreate ( has_create . HasCreate ) :
connection = None
def __str__ ( self ) :
return " instance of {0.__class__.__name__} ( {1} ) " . format ( self , hex ( id ( self ) ) )
def __init__ ( self , * a , * * kw ) :
self . cleaned = False
super ( MockHasCreate , self ) . __init__ ( )
def silent_cleanup ( self ) :
self . cleaned = True
class A ( MockHasCreate ) :
def create ( self , * * kw ) :
return self
class B ( MockHasCreate ) :
optional_dependencies = [ A ]
def create ( self , a = None , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( a , A ) ) )
return self
class C ( MockHasCreate ) :
dependencies = [ A , B ]
def create ( self , a = A , b = B , * * kw ) :
self . create_and_update_dependencies ( b , a )
return self
class D ( MockHasCreate ) :
dependencies = [ A ]
optional_dependencies = [ B ]
def create ( self , a = A , b = None , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( a , A ) , ( b , B ) ) )
return self
class E ( MockHasCreate ) :
dependencies = [ D , C ]
def create ( self , c = C , d = D , * * kw ) :
self . create_and_update_dependencies ( d , c )
return self
class F ( MockHasCreate ) :
dependencies = [ B ]
optional_dependencies = [ E ]
def create ( self , b = B , e = None , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( b , B ) , ( e , E ) ) )
return self
class G ( MockHasCreate ) :
dependencies = [ D ]
optional_dependencies = [ F , E ]
def create ( self , d = D , f = None , e = None , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( d , D ) , ( f , F ) , ( e , E ) ) )
return self
class H ( MockHasCreate ) :
optional_dependencies = [ E , A ]
def create ( self , a = None , e = None , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( a , A ) , ( e , E ) ) )
return self
class MultipleWordClassName ( MockHasCreate ) :
def create ( self , * * kw ) :
return self
class AnotherMultipleWordClassName ( MockHasCreate ) :
optional_dependencies = [ MultipleWordClassName ]
def create ( self , multiple_word_class_name = None , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( multiple_word_class_name , MultipleWordClassName ) ) )
return self
def test_dependency_graph_single_page ( ) :
""" confirms that `dependency_graph(Base)` will return a dependency graph
consisting of only dependencies and dependencies of dependencies ( if any )
"""
desired = { }
desired [ G ] = set ( [ D ] )
desired [ D ] = set ( [ A ] )
desired [ A ] = set ( )
assert has_create . dependency_graph ( G ) == desired
def test_dependency_graph_page_with_optional ( ) :
""" confirms that `dependency_graph(Base, OptionalBase)` will return a dependency
graph consisting of only dependencies and dependencies of dependencies ( if any )
with the exception that the OptionalBase and its dependencies are included as well .
"""
desired = { }
desired [ G ] = set ( [ D ] )
desired [ E ] = set ( [ D , C ] )
desired [ C ] = set ( [ A , B ] )
desired [ D ] = set ( [ A ] )
desired [ B ] = set ( )
desired [ A ] = set ( )
assert has_create . dependency_graph ( G , E ) == desired
def test_dependency_graph_page_with_additionals ( ) :
""" confirms that `dependency_graph(Base, AdditionalBaseOne, AdditionalBaseTwo)`
will return a dependency graph consisting of only dependencies and dependencies
of dependencies ( if any ) with the exception that the AdditionalBases
are treated as a dependencies of Base ( when they aren ' t) and their dependencies
are included as well .
"""
desired = { }
desired [ E ] = set ( [ D , C ] )
desired [ D ] = set ( [ A ] )
desired [ C ] = set ( [ A , B ] )
desired [ F ] = set ( [ B ] )
desired [ G ] = set ( [ D ] )
desired [ A ] = set ( )
desired [ B ] = set ( )
assert has_create . dependency_graph ( E , F , G ) == desired
def test_optional_dependency_graph_single_page ( ) :
""" confirms that has_create._optional_dependency_graph(Base) returns a complete dependency tree
including all optional_dependencies
"""
desired = { }
desired [ H ] = set ( [ E , A ] )
desired [ E ] = set ( [ D , C ] )
desired [ D ] = set ( [ A , B ] )
desired [ C ] = set ( [ A , B ] )
desired [ B ] = set ( [ A ] )
desired [ A ] = set ( )
assert has_create . optional_dependency_graph ( H ) == desired
def test_optional_dependency_graph_with_additional ( ) :
""" confirms that has_create._optional_dependency_graph(Base) returns a complete dependency tree
including all optional_dependencies with the AdditionalBases treated as a dependencies
of Base ( when they aren ' t) and their dependencies and optional_dependencies included as well.
"""
desired = { }
desired [ F ] = set ( [ B , E ] )
desired [ H ] = set ( [ E , A ] )
desired [ E ] = set ( [ D , C ] )
desired [ D ] = set ( [ A , B ] )
desired [ C ] = set ( [ A , B ] )
desired [ B ] = set ( [ A ] )
desired [ A ] = set ( )
assert has_create . optional_dependency_graph ( F , H , A ) == desired
def test_creation_order ( ) :
""" confirms that `has_create.creation_order()` returns a valid creation order in the desired list of sets format """
dependency_graph = dict ( eight = set ( [ ' seven ' , ' six ' ] ) ,
seven = set ( [ ' five ' ] ) ,
six = set ( ) ,
five = set ( [ ' two ' , ' one ' ] ) ,
four = set ( [ ' one ' ] ) ,
three = set ( [ ' two ' ] ) ,
two = set ( [ ' one ' ] ) ,
one = set ( ) )
desired = [ set ( [ ' one ' , ' six ' ] ) ,
set ( [ ' two ' , ' four ' ] ) ,
set ( [ ' three ' , ' five ' ] ) ,
set ( [ ' seven ' ] ) ,
set ( [ ' eight ' ] ) ]
assert has_create . creation_order ( dependency_graph ) == desired
def test_creation_order_with_loop ( ) :
""" confirms that `has_create.creation_order()` raises toposort.CircularDependencyError when evaluating
a cyclic dependency graph
"""
dependency_graph = dict ( eight = set ( [ ' seven ' , ' six ' ] ) ,
seven = set ( [ ' five ' ] ) ,
six = set ( ) ,
five = set ( [ ' two ' , ' one ' ] ) ,
four = set ( [ ' one ' ] ) ,
three = set ( [ ' two ' ] ) ,
two = set ( [ ' one ' ] ) ,
one = set ( [ ' eight ' ] ) )
with pytest . raises ( CircularDependencyError ) :
assert has_create . creation_order ( dependency_graph )
class One ( MockHasCreate ) :
pass
class Two ( MockHasCreate ) :
dependencies = [ One ]
class Three ( MockHasCreate ) :
dependencies = [ Two , One ]
class Four ( MockHasCreate ) :
optional_dependencies = [ Two ]
class Five ( MockHasCreate ) :
dependencies = [ Two ]
optional_dependencies = [ One ]
class IsntAHasCreate ( object ) :
pass
class Six ( MockHasCreate , IsntAHasCreate ) :
dependencies = [ Two ]
class Seven ( MockHasCreate ) :
dependencies = [ IsntAHasCreate ]
def test_separate_async_optionals_none_exist ( ) :
""" confirms that when creation group classes have no async optional dependencies the order is unchanged """
order = has_create . creation_order ( has_create . optional_dependency_graph ( Three , Two , One ) )
assert has_create . separate_async_optionals ( order ) == order
def test_separate_async_optionals_two_exist ( ) :
""" confirms that when two creation group classes have async dependencies
the class that has shared item as a dependency occurs first in a separate creation group
"""
order = has_create . creation_order ( has_create . optional_dependency_graph ( Four , Three , Two ) )
assert has_create . separate_async_optionals ( order ) == [ set ( [ One ] ) , set ( [ Two ] ) , set ( [ Three ] ) , set ( [ Four ] ) ]
def test_separate_async_optionals_three_exist ( ) :
""" confirms that when three creation group classes have async dependencies
the class that has shared item as a dependency occurs first in a separate creation group
"""
order = has_create . creation_order ( has_create . optional_dependency_graph ( Five , Four , Three ) )
assert has_create . separate_async_optionals ( order ) == [ set ( [ One ] ) , set ( [ Two ] ) , set ( [ Three ] ) ,
set ( [ Five ] ) , set ( [ Four ] ) ]
def test_separate_async_optionals_not_has_create ( ) :
""" confirms that when a dependency isn ' t a HasCreate has_create.separate_aysnc_optionals doesn ' t
unnecessarily move it from the initial creation group
"""
order = has_create . creation_order ( has_create . optional_dependency_graph ( Seven , Six ) )
assert has_create . separate_async_optionals ( order ) == [ set ( [ One , IsntAHasCreate ] ) , set ( [ Two , Seven ] ) , set ( [ Six ] ) ]
def test_page_creation_order_single_page ( ) :
""" confirms that `has_create.page_creation_order()` returns a valid creation order """
desired = [ set ( [ A ] ) , set ( [ D ] ) , set ( [ G ] ) ]
assert has_create . page_creation_order ( G ) == desired
def test_page_creation_order_optionals_provided ( ) :
""" confirms that `has_create.page_creation_order()` returns a valid creation order
when optional_dependencies are included
"""
desired = [ set ( [ A ] ) , set ( [ B ] ) , set ( [ C ] ) , set ( [ D ] ) , set ( [ E ] ) , set ( [ H ] ) ]
assert has_create . page_creation_order ( H , A , E ) == desired
def test_page_creation_order_additionals_provided ( ) :
""" confirms that `has_create.page_creation_order()` returns a valid creation order
when additional pages are included
"""
desired = [ set ( [ A ] ) , set ( [ B ] ) , set ( [ D ] ) , set ( [ F , H ] ) , set ( [ G ] ) ]
assert has_create . page_creation_order ( F , H , G ) == desired
def test_all_instantiated_dependencies_single_page ( ) :
f = F ( ) . create ( )
b = f . _dependency_store [ B ]
desired = set ( [ b , f ] )
assert set ( has_create . all_instantiated_dependencies ( f , A , B , C , D , E , F , G , H ) ) == desired
def test_all_instantiated_dependencies_single_page_are_ordered ( ) :
f = F ( ) . create ( )
b = f . _dependency_store [ B ]
desired = [ b , f ]
assert has_create . all_instantiated_dependencies ( f , A , B , C , D , E , F , G , H ) == desired
def test_all_instantiated_dependencies_optionals ( ) :
a = A ( ) . create ( )
b = B ( ) . create ( a = a )
c = C ( ) . create ( a = a , b = b )
d = D ( ) . create ( a = a , b = b )
e = E ( ) . create ( c = c , d = d )
h = H ( ) . create ( a = a , e = e )
desired = set ( [ a , b , c , d , e , h ] )
assert set ( has_create . all_instantiated_dependencies ( h , A , B , C , D , E , F , G , H ) ) == desired
def test_all_instantiated_dependencies_optionals_are_ordered ( ) :
a = A ( ) . create ( )
b = B ( ) . create ( a = a )
c = C ( ) . create ( a = a , b = b )
d = D ( ) . create ( a = a , b = b )
e = E ( ) . create ( c = c , d = d )
h = H ( ) . create ( a = a , e = e )
desired = [ a , b , c , d , e , h ]
assert has_create . all_instantiated_dependencies ( h , A , B , C , D , E , F , G , H ) == desired
def test_dependency_resolution_complete ( ) :
h = H ( ) . create ( a = True , e = True )
a = h . _dependency_store [ A ]
e = h . _dependency_store [ E ]
c = e . _dependency_store [ C ]
d = e . _dependency_store [ D ]
b = c . _dependency_store [ B ]
for item in ( h , a , e , d , c , b ) :
if item . _dependency_store :
assert all ( item . _dependency_store . values ( )
) , " {0} missing dependency: {0._dependency_store} " . format ( item )
assert a == b . _dependency_store [ A ] , " Duplicate dependency detected "
assert a == c . _dependency_store [ A ] , " Duplicate dependency detected "
assert a == d . _dependency_store [ A ] , " Duplicate dependency detected "
assert b == c . _dependency_store [ B ] , " Duplicate dependency detected "
assert b == d . _dependency_store [ B ] , " Duplicate dependency detected "
def test_ds_mapping ( ) :
h = H ( ) . create ( a = True , e = True )
a = h . _dependency_store [ A ]
e = h . _dependency_store [ E ]
c = e . _dependency_store [ C ]
d = e . _dependency_store [ D ]
b = c . _dependency_store [ B ]
assert a == h . ds . a
assert e == h . ds . e
assert c == e . ds . c
assert d == e . ds . d
assert b == c . ds . b
def test_ds_multiple_word_class_and_attribute_name ( ) :
amwcn = AnotherMultipleWordClassName ( ) . create ( multiple_word_class_name = True )
mwcn = amwcn . _dependency_store [ MultipleWordClassName ]
assert amwcn . ds . multiple_word_class_name == mwcn
def test_ds_missing_dependency ( ) :
a = A ( ) . create ( )
with pytest . raises ( AttributeError ) :
a . ds . b
def test_teardown_calls_silent_cleanup ( ) :
g = G ( ) . create ( f = True , e = True )
f = g . _dependency_store [ F ]
e = g . _dependency_store [ E ]
b = f . _dependency_store [ B ]
d = e . _dependency_store [ D ]
c = e . _dependency_store [ C ]
a = c . _dependency_store [ A ]
instances = [ g , f , e , b , d , c , a ]
for instance in instances :
assert not instance . cleaned
g . teardown ( )
for instance in instances :
assert instance . cleaned
def test_teardown_dependency_store_cleared ( ) :
g = G ( ) . create ( f = True , e = True )
f = g . _dependency_store [ F ]
e = g . _dependency_store [ E ]
b = f . _dependency_store [ B ]
d = e . _dependency_store [ D ]
c = e . _dependency_store [ C ]
a = c . _dependency_store [ A ]
g . teardown ( )
assert not g . _dependency_store [ F ]
assert not g . _dependency_store [ E ]
assert not f . _dependency_store [ B ]
assert not e . _dependency_store [ D ]
assert not e . _dependency_store [ C ]
assert not c . _dependency_store [ A ]
def test_idempotent_teardown_dependency_store_cleared ( ) :
g = G ( ) . create ( f = True , e = True )
f = g . _dependency_store [ F ]
e = g . _dependency_store [ E ]
b = f . _dependency_store [ B ]
d = e . _dependency_store [ D ]
c = e . _dependency_store [ C ]
a = c . _dependency_store [ A ]
for item in ( g , f , e , b , d , c , a ) :
item . teardown ( )
item . teardown ( )
assert not g . _dependency_store [ F ]
assert not g . _dependency_store [ E ]
assert not f . _dependency_store [ B ]
assert not e . _dependency_store [ D ]
assert not e . _dependency_store [ C ]
assert not c . _dependency_store [ A ]
def test_teardown_ds_cleared ( ) :
g = G ( ) . create ( f = True , e = True )
f = g . _dependency_store [ F ]
e = g . _dependency_store [ E ]
b = f . _dependency_store [ B ]
d = e . _dependency_store [ D ]
c = e . _dependency_store [ C ]
a = c . _dependency_store [ A ]
g . teardown ( )
for former_dep in ( ' f ' , ' e ' ) :
with pytest . raises ( AttributeError ) :
getattr ( g . ds , former_dep )
with pytest . raises ( AttributeError ) :
getattr ( f . ds , ' b ' )
for former_dep in ( ' d ' , ' c ' ) :
with pytest . raises ( AttributeError ) :
getattr ( e . ds , former_dep )
with pytest . raises ( AttributeError ) :
getattr ( c . ds , ' a ' )
class OneWithArgs ( MockHasCreate ) :
def create ( self , * * kw ) :
self . kw = kw
return self
class TwoWithArgs ( MockHasCreate ) :
dependencies = [ OneWithArgs ]
def create ( self , one_with_args = OneWithArgs , * * kw ) :
if not one_with_args and kw . pop ( ' make_one_with_args ' , False ) :
one_with_args = ( OneWithArgs , dict ( a = ' a ' , b = ' b ' , c = ' c ' ) )
self . create_and_update_dependencies ( one_with_args )
self . kw = kw
return self
class ThreeWithArgs ( MockHasCreate ) :
dependencies = [ OneWithArgs ]
optional_dependencies = [ TwoWithArgs ]
def create ( self , one_with_args = OneWithArgs , two_with_args = None , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( one_with_args , OneWithArgs ) ,
( two_with_args , TwoWithArgs ) ) )
self . kw = kw
return self
class FourWithArgs ( MockHasCreate ) :
dependencies = [ TwoWithArgs , ThreeWithArgs ]
def create ( self , two_with_args = TwoWithArgs , three_with_args = ThreeWithArgs , * * kw ) :
self . create_and_update_dependencies ( * filter_by_class ( ( two_with_args , TwoWithArgs ) ,
( three_with_args , ThreeWithArgs ) ) )
self . kw = kw
return self
def test_single_kwargs_class_in_create_and_update_dependencies ( ) :
two_wa = TwoWithArgs ( ) . create ( one_with_args = False , make_one_with_args = True , two_with_args_kw_arg = 123 )
assert isinstance ( two_wa . ds . one_with_args , OneWithArgs )
assert two_wa . ds . one_with_args . kw == dict ( a = ' a ' , b = ' b ' , c = ' c ' )
assert two_wa . kw == dict ( two_with_args_kw_arg = 123 )
def test_no_tuple_for_class_arg_causes_shared_dependencies_staggered ( ) :
three_wo = ThreeWithArgs ( ) . create ( two_with_args = True )
assert isinstance ( three_wo . ds . one_with_args , OneWithArgs )
assert isinstance ( three_wo . ds . two_with_args , TwoWithArgs )
assert isinstance ( three_wo . ds . two_with_args . ds . one_with_args , OneWithArgs )
assert three_wo . ds . one_with_args == three_wo . ds . two_with_args . ds . one_with_args
def test_no_tuple_for_class_arg_causes_shared_dependencies_nested_staggering ( ) :
four_wo = FourWithArgs ( ) . create ( )
assert isinstance ( four_wo . ds . two_with_args , TwoWithArgs )
assert isinstance ( four_wo . ds . three_with_args , ThreeWithArgs )
assert isinstance ( four_wo . ds . two_with_args . ds . one_with_args , OneWithArgs )
assert isinstance ( four_wo . ds . three_with_args . ds . one_with_args , OneWithArgs )
assert isinstance ( four_wo . ds . three_with_args . ds . two_with_args , TwoWithArgs )
assert four_wo . ds . two_with_args . ds . one_with_args == four_wo . ds . three_with_args . ds . one_with_args
assert four_wo . ds . two_with_args == four_wo . ds . three_with_args . ds . two_with_args
def test_tuple_for_class_arg_causes_unshared_dependencies_when_downstream ( ) :
""" Confirms that provided arg-tuple for dependency type is applied instead of chained dependency """
three_wa = ThreeWithArgs ( ) . create ( two_with_args = ( TwoWithArgs , dict ( one_with_args = False ,
make_one_with_args = True ,
two_with_args_kw_arg = 234 ) ) ,
three_with_args_kw_arg = 345 )
assert isinstance ( three_wa . ds . one_with_args , OneWithArgs )
assert isinstance ( three_wa . ds . two_with_args , TwoWithArgs )
assert isinstance ( three_wa . ds . two_with_args . ds . one_with_args , OneWithArgs )
assert three_wa . ds . one_with_args != three_wa . ds . two_with_args . ds . one_with_args
assert three_wa . ds . one_with_args . kw == dict ( )
assert three_wa . ds . two_with_args . kw == dict ( two_with_args_kw_arg = 234 )
assert three_wa . ds . two_with_args . ds . one_with_args . kw == dict ( a = ' a ' , b = ' b ' , c = ' c ' )
assert three_wa . kw == dict ( three_with_args_kw_arg = 345 )
def test_tuples_for_class_arg_cause_unshared_dependencies_when_downstream ( ) :
""" Confirms that provided arg-tuple for dependency type is applied instead of chained dependency """
four_wa = FourWithArgs ( ) . create ( two_with_args = ( TwoWithArgs , dict ( one_with_args = False ,
make_one_with_args = True ,
two_with_args_kw_arg = 456 ) ) ,
# No shared dependencies with four_wa.ds.two_with_args
three_with_args = ( ThreeWithArgs , dict ( one_with_args = ( OneWithArgs , { } ) ,
two_with_args = False ) ) ,
four_with_args_kw = 567 )
assert isinstance ( four_wa . ds . two_with_args , TwoWithArgs )
assert isinstance ( four_wa . ds . three_with_args , ThreeWithArgs )
assert isinstance ( four_wa . ds . two_with_args . ds . one_with_args , OneWithArgs )
assert isinstance ( four_wa . ds . three_with_args . ds . one_with_args , OneWithArgs )
assert four_wa . ds . three_with_args . ds . one_with_args != four_wa . ds . two_with_args . ds . one_with_args
with pytest . raises ( AttributeError ) :
four_wa . ds . three_with_args . ds . two_with_args
assert four_wa . kw == dict ( four_with_args_kw = 567 )
class NotHasCreate ( object ) :
pass
class MixinUserA ( MockHasCreate , NotHasCreate ) :
def create ( self , * * kw ) :
return self
class MixinUserB ( MockHasCreate , NotHasCreate ) :
def create ( self , * * kw ) :
return self
class MixinUserC ( MixinUserB ) :
def create ( self , * * kw ) :
return self
class MixinUserD ( MixinUserC ) :
def create ( self , * * kw ) :
return self
class NotHasCreateDependencyHolder ( MockHasCreate ) :
dependencies = [ NotHasCreate ]
def create ( self , not_has_create = MixinUserA ) :
self . create_and_update_dependencies ( not_has_create )
return self
def test_not_has_create_default_dependency ( ) :
""" Confirms that HasCreates that claim non-HasCreates as dependencies claim them by correct kwarg
class name in _dependency_store
"""
dep_holder = NotHasCreateDependencyHolder ( ) . create ( )
assert isinstance ( dep_holder . ds . not_has_create , MixinUserA )
def test_not_has_create_passed_dependency ( ) :
""" Confirms that passed non-HasCreate subclasses are sourced as dependency """
dep = MixinUserB ( ) . create ( )
assert isinstance ( dep , MixinUserB )
dep_holder = NotHasCreateDependencyHolder ( ) . create ( not_has_create = dep )
assert dep_holder . ds . not_has_create == dep
class HasCreateParentDependencyHolder ( MockHasCreate ) :
dependencies = [ MixinUserB ]
def create ( self , mixin_user_b = MixinUserC ) :
self . create_and_update_dependencies ( mixin_user_b )
return self
def test_has_create_stored_as_parent_dependency ( ) :
""" Confirms that HasCreate subclasses are sourced as their parent """
dep = MixinUserC ( ) . create ( )
assert isinstance ( dep , MixinUserC )
assert isinstance ( dep , MixinUserB )
dep_holder = HasCreateParentDependencyHolder ( ) . create ( mixin_user_b = dep )
assert dep_holder . ds . mixin_user_b == dep
class DynamicallyDeclaresNotHasCreateDependency ( MockHasCreate ) :
dependencies = [ NotHasCreate ]
def create ( self , not_has_create = MixinUserA ) :
dynamic_dependency = dict ( mixinusera = MixinUserA ,
mixinuserb = MixinUserB ,
mixinuserc = MixinUserC )
self . create_and_update_dependencies ( dynamic_dependency [ not_has_create ] )
return self
@pytest.mark.parametrize ( ' dependency,dependency_class ' ,
[ ( ' mixinusera ' , MixinUserA ) ,
( ' mixinuserb ' , MixinUserB ) ,
( ' mixinuserc ' , MixinUserC ) ] )
def test_subclass_or_parent_dynamic_not_has_create_dependency_declaration ( dependency , dependency_class ) :
""" Confirms that dependencies that dynamically declare dependencies subclassed from not HasCreate
are properly linked
"""
dep_holder = DynamicallyDeclaresNotHasCreateDependency ( ) . create ( dependency )
assert dep_holder . ds . not_has_create . __class__ == dependency_class
class DynamicallyDeclaresHasCreateDependency ( MockHasCreate ) :
dependencies = [ MixinUserB ]
def create ( self , mixin_user_b = MixinUserB ) :
dynamic_dependency = dict ( mixinuserb = MixinUserB ,
mixinuserc = MixinUserC ,
mixinuserd = MixinUserD )
self . create_and_update_dependencies ( dynamic_dependency [ mixin_user_b ] )
return self
@pytest.mark.parametrize ( ' dependency,dependency_class ' ,
[ ( ' mixinuserb ' , MixinUserB ) ,
( ' mixinuserc ' , MixinUserC ) ,
( ' mixinuserd ' , MixinUserD ) ] )
def test_subclass_or_parent_dynamic_has_create_dependency_declaration ( dependency , dependency_class ) :
""" Confirms that dependencies that dynamically declare dependencies subclassed from not HasCreate
are properly linked
"""
dep_holder = DynamicallyDeclaresHasCreateDependency ( ) . create ( dependency )
assert dep_holder . ds . mixin_user_b . __class__ == dependency_class