def test_class_decoration(verbose=False): """Test class decoration.""" from pydeco.utils.parser import CONFIG CONFIG['N_DISPATCH'] = None unregister_all() global logs logs = [] # instantiate the class instance = MyClass() assert repr(instance) == 'MyClass(cnt_dec_1=0, cnt_dec_1=0)' # run methods instance.method_1() instance.method_2() instance.method_3() assert instance.cnt_dec_1 == 0 and instance.cnt_dec_2 == 0 # decorate methods MyClass_deco = MethodsDecorator( mapping={ Decorator1(name='decorator_1'): ['method_1', 'method_2'], Decorator2(name='decorator_2'): 'method_1' })(MyClass) # instantiate the class instance = MyClass_deco() assert repr(instance) == 'Wrapped(MyClass)(cnt_dec_1=0, cnt_dec_1=0)' # run methods instance.method_1() instance.method_2() instance.method_3() assert repr(instance) == 'Wrapped(MyClass)(cnt_dec_1=2, cnt_dec_1=1)' assert instance.cnt_dec_1 == 2 and instance.cnt_dec_2 == 1 # decorate methods with pytest.raises(ValueError, match='Input class has not method "method_4"'): MyClass_deco = MethodsDecorator( mapping={ Decorator1(name='decorator_1'): ['method_1', 'method_2'], Decorator2(name='decorator_2'): ['method_1', 'method_4'] })(MyClass) unregister_all()
def test_is_wrapped(): """Test `is_wrapped` function.""" unregister_all() # instantiate the base class instance = MyClass() # decorate methods MyClass_deco = MethodsDecorator( mapping={ Decorator1(name='decorator_1'): ['method_1', 'method_2'], Decorator2(name='decorator_2'): 'method_1' })(MyClass) # instantiate the wrapped class instance_2 = MyClass_deco() # list of objects to check objs = ['string', {'a': 1}, None, 3, list, dict, int, str, Decorator] # check that hereabove objects (instances and classes) are not wrapped for obj in objs: assert not is_wrapped(obj) # check that :class:`MyClass` is not wrapped assert not is_wrapped(MyClass) # check that :class:`MyClass` instance `instance` is not wrapped assert not is_wrapped(instance) # check that :class:`MyClass_deco` is wrapped assert is_wrapped(MyClass_deco) # check that :class:`MyClass_deco` instance `instance_2` is wrapped assert is_wrapped(instance_2)
def test_parallelizing(copy, n_iter, n_jobs=1, verbose=True): """Test parallelizing.""" from pydeco.utils.parser import CONFIG CONFIG['N_DISPATCH'] = n_iter + 1 unregister_all() global logs logs = [] # store number of iterations for each process global iter_process iter_process = dict() # decorate methods of base class MyClass_deco = MethodsDecorator( mapping={ Decorator1(name='decorator_1'): ['method_1', 'method_2'], Decorator2(name='decorator_2'): 'method_1' })(MyClass) # instantiate the decorated class instance = MyClass_deco() # create a "reference" instance instance_ref = deepcopy(instance) if verbose: print('Before deepcopy...\n' + '-' * 18) for inst in [instance, instance_ref]: print('Instance: {} (id={})'.format(inst, id(inst))) print('Mapping:') print(inst._decorator_mapping) print('Decorators') for deco_name, deco in inst.decorators.items(): print('\t Decorator: {}'.format(deco)) print('\n') # run parallel jobs if verbose: print('Parallelizing: {} iterations distributed on {} jobs'.format( n_iter, n_jobs)) backend = 'multiprocessing' if copy else 'threading' with Parallel(n_jobs=n_jobs, verbose=verbose, pre_dispatch='all', backend=backend) as parallel: res = parallel( delayed(myfunc)(i, deepcopy(instance), copy=copy, verbose=verbose, iter_process=iter_process) for i in range(n_iter)) unregister_all()
def test_wrapped_class(): """Test `wrapped_class` function.""" # instantiate the base class instance = MyClass() assert wrapped_class(instance) is MyClass # decorate methods MyClass_deco = MethodsDecorator( mapping={ Decorator1(name='decorator_1'): ['method_1', 'method_2'], Decorator2(name='decorator_2'): 'method_1' })(MyClass) # instantiate the wrapped class instance_2 = MyClass_deco() assert wrapped_class(instance_2) is MyClass
def test_pickling(dcopy, verbose=True): """Test pickling.""" from pydeco.utils.parser import CONFIG CONFIG['N_DISPATCH'] = 1 unregister_all() global logs logs = [] # decorate methods of base class MyClass_deco = MethodsDecorator( mapping={ Decorator1(name='decorator_1'): ['method_1', 'method_2'], Decorator2(name='decorator_2'): 'method_1' })(MyClass) # instantiate the decorated class instance = MyClass_deco() if verbose: print('Before pickling...\n' + '-' * 18) for inst in [instance]: print('Instance: {} (id={})'.format(inst, id(inst))) print('Mapping:') print(inst._decorator_mapping) print('Decorators') for deco_name, deco in inst.decorators.items(): print('\t Decorator: {}'.format(deco)) print('\n') instance_ = deepcopy(instance) if dcopy else instance # Save instance as a pickle object tmp = pkl.dumps(instance_) # Load pickled module instance_2 = pkl.loads(tmp) if verbose: print('After pickling...\n' + '-' * 17) for inst in [instance, instance_2]: print('Instance: {} (id={})'.format(inst, id(inst))) print('Mapping:') print(inst._decorator_mapping) print('Decorators') for deco_name, deco in inst.decorators.items(): print('\t Decorator: {}'.format(deco)) print('\n') # check that `instance` and `instance_2` are distinct objects assert instance is not instance_2 # check that decorators of `instance` and `instance_2` are distinct objects for (deco1_name, deco1), (deco2_name, deco2) in zip(instance.decorators.items(), instance_2.decorators.items()): assert deco1 is not deco2 assert instance.cnt_dec_1 == 0 and instance.cnt_dec_2 == 0 assert instance_2.cnt_dec_1 == 0 and instance_2.cnt_dec_2 == 0 # run methods for `instance` # run methods instance_2.method_1() instance_2.method_2() instance_2.method_3() new_classname = 'Wrapped2(MyClass)' if dcopy else 'Wrapped(MyClass)' for j, entry in enumerate(logs): assert entry[new_classname] == id(instance_2) if j == 0: assert (entry['Decorator2'] == id( instance_.decorators['Decorator2'])) elif j == 1: assert (entry['Decorator1'] == id( instance_.decorators['Decorator1'])) elif j == 2: assert (entry['Decorator1'] == id( instance_.decorators['Decorator1'])) # check that internal variables of `instance`' have changed but not of # `instance_2` assert instance.cnt_dec_1 == 0 and instance.cnt_dec_2 == 0 assert instance_2.cnt_dec_1 == 2 and instance_2.cnt_dec_2 == 1 # run methods instance.method_1() instance.method_2() instance.method_3() for j, entry in enumerate(logs): if j < 3: assert entry[new_classname] == id(instance_2) if j == 0: assert (entry['Decorator2'] == id( instance_.decorators['Decorator2'])) elif j == 1: assert (entry['Decorator1'] == id( instance_.decorators['Decorator1'])) elif j == 2: assert (entry['Decorator1'] == id( instance_.decorators['Decorator1'])) else: assert entry['Wrapped(MyClass)'] == id(instance) if j == 3: assert (entry['Decorator2'] == id( instance.decorators['Decorator2'])) elif j == 4: assert (entry['Decorator1'] == id( instance.decorators['Decorator1'])) elif j == 5: assert (entry['Decorator1'] == id( instance.decorators['Decorator1'])) assert instance.cnt_dec_1 == 2 and instance.cnt_dec_2 == 1 assert instance_2.cnt_dec_1 == 2 and instance_2.cnt_dec_2 == 1 unregister_all()
def test_class_registration(n_dispatch): """Test class registration.""" # instantiate the base class unregister_all() from pydeco.utils.parser import CONFIG CONFIG['N_DISPATCH'] = n_dispatch registered_wrappers = get_registered_wrappers_classnames() assert len(registered_wrappers) == 0 with pytest.raises(ValueError, match='No assigned wrapper found.'): unassigned_wrappers = get_unassigned_wrappers_classnames('MyClass') instance = MyClass() # decorate methods MyClass_deco = MethodsDecorator( mapping={ Decorator1(name='decorator_1'): ['method_1', 'method_2'], Decorator2(name='decorator_2'): 'method_1' })(MyClass) registered_wrappers = get_registered_wrappers_classnames() assert len(registered_wrappers) == n_dispatch + 1 unassigned_wrappers = get_unassigned_wrappers_classnames('MyClass') assert len(unassigned_wrappers) == n_dispatch + 1 # instantiate the wrapped class instance_2 = MyClass_deco() registered_wrappers = get_registered_wrappers_classnames() assert len(registered_wrappers) == n_dispatch + 1 if n_dispatch == 0: with pytest.raises(ValueError, match='No assigned wrapper found.'): unassigned_wrappers = get_unassigned_wrappers_classnames('MyClass') else: unassigned_wrappers = get_unassigned_wrappers_classnames('MyClass') assert len(unassigned_wrappers) == n_dispatch assert 'Wrapped(MyClass)' not in unassigned_wrappers from copy import deepcopy # create a copy of "instance_2" if n_dispatch == 0: with pytest.raises(ValueError, match='No assigned wrapper found.'): instance_3 = deepcopy(instance_2) else: instance_3 = deepcopy(instance_2) registered_wrappers = get_registered_wrappers_classnames() assert len(registered_wrappers) == n_dispatch + 1 if n_dispatch != 0: unassigned_wrappers = get_unassigned_wrappers_classnames('MyClass') assert len(unassigned_wrappers) == n_dispatch - 1 assert 'Wrapped(MyClass)' not in unassigned_wrappers assert 'Wrapped2(MyClass)' not in unassigned_wrappers # Unregistering "instance_2" unregister(instance_2.__class__) registered_wrappers = get_registered_wrappers_classnames() assert len(registered_wrappers) == n_dispatch assert 'Wrapped(MyClass)' not in registered_wrappers if n_dispatch != 0: unassigned_wrappers = get_unassigned_wrappers_classnames('MyClass') assert len(unassigned_wrappers) == n_dispatch - 1 assert 'Wrapped(MyClass)' not in unassigned_wrappers assert 'Wrapped2(MyClass)' not in unassigned_wrappers
# Test # Without custom decorators # ----------------------------------------------------------------------------- # instantiate the class instance = MyClass() # run methods instance.method_1() instance.method_2() instance.method_3() # With custom decorators for the respective methods # ----------------------------------------------------------------------------- # decorate the class MyClass_deco = MethodsDecorator( mapping={ Decorator1(): ['method_1', 'method_2'], Decorator2(): ['method_1', 'method_3'] })(MyClass) # instantiate the class instance = MyClass_deco() # run methods instance.method_1() instance.method_2() instance.method_3()