def test_annotate_is_method(schema): """If is_method=True, the first argument ("self") should be ignored.""" s = mock.sentinel class SomeClass(object): @annotate(schema, is_method=True) def method(self, a, b, c=s.default_c, d=s.default_d): pass wrapped_method = get_wrapped(SomeClass.method) assert dict(wrapped_method._doctor_annotation) == { 'annotated_func': wrapped_method, 'func': wrapped_method, 'is_method': True, 'arg_names': ['self', 'a', 'b', 'c', 'd'], 'args_name': None, 'kwargs_name': None, 'default_values': (s.default_c, s.default_d), 'schema': schema, 'args_schema': { 'type': 'object', 'additionalProperties': True, 'properties': { 'a': {'$ref': '#/definitions/a'}, 'b': {'$ref': '#/definitions/b'}, 'c': {'$ref': '#/definitions/c'}, 'd': {'$ref': '#/definitions/d'} }, 'required': ['a', 'b'] }, 'result_schema': None }
def test_annotate_func_with_all_default_args(schema): """It should correctly handle a function with all optional arguments.""" s = mock.sentinel @annotate(schema) def func_with_default_args(a=s.default_a, b=s.default_b): pass wrapped_func = get_wrapped(func_with_default_args) assert dict(wrapped_func._doctor_annotation) == { 'annotated_func': wrapped_func, 'func': wrapped_func, 'is_method': False, 'arg_names': ['a', 'b'], 'args_name': None, 'kwargs_name': None, 'default_values': (s.default_a, s.default_b), 'schema': schema, 'args_schema': { 'type': 'object', 'additionalProperties': True, 'properties': { 'a': {'$ref': '#/definitions/a'}, 'b': {'$ref': '#/definitions/b'}, } }, 'result_schema': None }
def test_annotate_with_result(schema): """It should allow you to specify a result schema.""" s = mock.sentinel @annotate(schema, result='c') def func_with_result(a, b=s.default_b): pass wrapped_func = get_wrapped(func_with_result) assert dict(func_with_result._doctor_annotation) == { 'annotated_func': wrapped_func, 'func': wrapped_func, 'is_method': False, 'arg_names': ['a', 'b'], 'args_name': None, 'kwargs_name': None, 'default_values': (s.default_b,), 'schema': schema, 'args_schema': { 'type': 'object', 'additionalProperties': True, 'properties': { 'a': {'$ref': '#/definitions/a'}, 'b': {'$ref': '#/definitions/b'}, }, 'required': ['a'] }, 'result_schema': { '$ref': '#/definitions/c' } }
def test_annotate_func_with_default_args(schema): """It should treat arguments with default values as optional.""" s = mock.sentinel @annotate(schema) def func_with_default_args(a, b, c=s.default_c, d=s.default_d): pass wrapped_func = get_wrapped(func_with_default_args) assert dict(wrapped_func._doctor_annotation) == { 'annotated_func': wrapped_func, 'func': wrapped_func, 'is_method': False, 'arg_names': ['a', 'b', 'c', 'd'], 'args_name': None, 'kwargs_name': None, 'default_values': (s.default_c, s.default_d), 'schema': schema, 'args_schema': { 'type': 'object', 'additionalProperties': True, 'properties': { 'a': {'$ref': '#/definitions/a'}, 'b': {'$ref': '#/definitions/b'}, 'c': {'$ref': '#/definitions/c'}, 'd': {'$ref': '#/definitions/d'} }, 'required': ['a', 'b'] }, 'result_schema': None }
def test_annotate_func_with_args(schema): """It should treat positional arguments as required.""" @annotate(schema) def func_with_args(a, b): pass wrapped_func = get_wrapped(func_with_args) assert dict(wrapped_func._doctor_annotation) == { 'annotated_func': wrapped_func, 'func': wrapped_func, 'is_method': False, 'arg_names': ['a', 'b'], 'args_name': None, 'kwargs_name': None, 'default_values': None, 'schema': schema, 'args_schema': { 'type': 'object', 'additionalProperties': True, 'properties': { 'a': {'$ref': '#/definitions/a'}, 'b': {'$ref': '#/definitions/b'} }, 'required': ['a', 'b'] }, 'result_schema': None }
def test_annotate_args_list_required(schema): """It should allow you to pass a list of required args.""" @annotate(schema, args=['a', 'b', 'c'], required_args=['a', 'b']) def func(foo, bar='baz'): pass wrapped_func = get_wrapped(func) assert dict(wrapped_func._doctor_annotation) == { 'annotated_func': wrapped_func, 'func': wrapped_func, 'is_method': False, 'arg_names': ['foo', 'bar'], 'args_name': None, 'kwargs_name': None, 'default_values': ('baz',), 'schema': schema, 'args_schema': { 'type': 'object', 'additionalProperties': True, 'properties': { 'a': {'$ref': '#/definitions/a'}, 'b': {'$ref': '#/definitions/b'}, 'c': {'$ref': '#/definitions/c'} }, 'required': ['a', 'b'] }, 'result_schema': None }
def test_get_wrapped(): s = mock.sentinel @with_wraps def foo(func): @functools.wraps(func) def wrapper(results): results.append(s.foo) return func(results) return wrapper @with_wraps(arguments=True) def bar(): def decorator(func): @functools.wraps(func) def wrapper(results): results.append(s.bar) return func(results) return wrapper return decorator @foo @bar() @foo @bar() def baz(results): results.append(s.baz) return results assert baz([]) == [s.foo, s.bar, s.foo, s.bar, s.baz] wrapped = get_wrapped(baz) assert wrapped([]) == [s.baz] def qux(): pass assert get_wrapped(qux) == qux
def test_annotation_collect_properties(schema): @annotate(schema) def func(a, b, c=3, d=4): pass annotation = get_wrapped(func)._doctor_annotation collect_properties = annotation.collect_properties properties = collect_properties((1, 2), {}) assert properties == {'a': 1, 'b': 2} properties = collect_properties((1, 2, 3, 4), {}) assert properties == {'a': 1, 'b': 2, 'c': 3, 'd': 4} properties = collect_properties((1, 2), {'c': 3, 'd': 4}) assert properties == {'a': 1, 'b': 2, 'c': 3, 'd': 4} properties = collect_properties((1, 2), {'d': 3}) assert properties == {'a': 1, 'b': 2, 'd': 3}
def test_annotate(schema): @annotate(schema) def func(): pass wrapped_func = get_wrapped(func) assert dict(wrapped_func._doctor_annotation) == { 'annotated_func': wrapped_func, 'func': wrapped_func, 'is_method': False, 'arg_names': [], 'args_name': None, 'kwargs_name': None, 'default_values': None, 'schema': schema, 'args_schema': None, 'result_schema': None }
def test_annotation_collect_properties_method(schema): """It should strip self for things marked as a method.""" s = mock.sentinel @annotate(schema, is_method=True) def method(self, a, b, c=3, d=4): pass annotation = get_wrapped(method)._doctor_annotation collect_properties = annotation.collect_properties properties = collect_properties((s.self, 1, 2), {}) assert properties == {'a': 1, 'b': 2} properties = collect_properties((s.self, 1, 2, 3, 4), {}) assert properties == {'a': 1, 'b': 2, 'c': 3, 'd': 4} properties = collect_properties((s.self, 1, 2), {'c': 3, 'd': 4}) assert properties == {'a': 1, 'b': 2, 'c': 3, 'd': 4} properties = collect_properties((s.self, 1, 2), {'d': 3}) assert properties == {'a': 1, 'b': 2, 'd': 3}
def test_annotate_args_none(schema): """It should allow you to specify None to disable argument validation.""" @annotate(schema, args=None) def func(a, b): pass wrapped_func = get_wrapped(func) assert dict(wrapped_func._doctor_annotation) == { 'annotated_func': wrapped_func, 'func': wrapped_func, 'is_method': False, 'arg_names': ['a', 'b'], 'args_name': None, 'kwargs_name': None, 'default_values': None, 'schema': schema, 'args_schema': None, 'result_schema': None }
def test_annotate_with_callable(schema): s = mock.sentinel class SomeCallable(object): __name__ = 'SomeCallable' def __init__(self): pass def __call__(self, a, b, c=s.default_c, d=s.default_d): pass some_callable = annotate(schema)(SomeCallable()) wrapped_method = get_wrapped(some_callable) assert dict(wrapped_method._doctor_annotation) == { 'annotated_func': wrapped_method, 'func': getattr(SomeCallable.__call__, '__func__', SomeCallable.__call__), 'is_method': True, 'arg_names': ['self', 'a', 'b', 'c', 'd'], 'args_name': None, 'kwargs_name': None, 'default_values': (s.default_c, s.default_d), 'schema': schema, 'args_schema': { 'type': 'object', 'additionalProperties': True, 'properties': { 'a': {'$ref': '#/definitions/a'}, 'b': {'$ref': '#/definitions/b'}, 'c': {'$ref': '#/definitions/c'}, 'd': {'$ref': '#/definitions/d'} }, 'required': ['a', 'b'] }, 'result_schema': None }