def test_dotted_name(self): # pylint: disable=g-bad-name class a(object): class b(object): class c(object): class d(object): def __init__(self, *args): pass # pylint: enable=g-bad-name e = {'f': 1} def example_fun(arg1=a.b.c.d, arg2=a.b.c.d(1, 2), arg3=e['f']): # pylint: disable=unused-argument pass sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_full_name='', func_type=signature.FuncType.FUNCTION) self.assertEqual( sig.arguments, ['arg1=a.b.c.d', 'arg2=a.b.c.d(1, 2)', 'arg3=e['f']'])
def test_type_annotations(self): # pylint: disable=unused-argument class TestMethodSig: def example_fun(self, x: List[str], z: int, a: Union[List[str], str, int] = None, b: str = 'test', *, y: bool = False, c: Callable[..., int], **kwargs) -> None: pass # pylint: enable=unused-argument sig = signature.generate_signature( TestMethodSig.example_fun, parser_config=self.parser_config, func_type=signature.FuncType.METHOD, ) expected = textwrap.dedent("""\ ( x: List[str], z: int, a: Union[List[str], str, int] = None, b: str = 'test', *, y: bool = False, c: Callable[..., int], **kwargs ) -> None""") self.assertEqual(expected, str(sig))
def test_vararg_before_kwargonly_consistent_order(self): def my_fun(*args, a=1, **kwargs): # pylint: disable=unused-argument pass sig = signature.generate_signature(my_fun, parser_config=self.parser_config) expected = '(\n *args, a=1, **kwargs\n)' self.assertEqual(expected, str(sig))
def _add_method( self, member_info: base_page.MemberInfo, defining_class: Optional[type], # pylint: disable=g-bare-generic ) -> None: """Adds a `MethodInfo` entry to the `methods` list. Args: member_info: a `base_page.MemberInfo` describing the method. defining_class: The `type` object where this method is defined. """ if defining_class is None: return # Omit methods defined by namedtuple. original_method = defining_class.__dict__[member_info.short_name] if (hasattr(original_method, '__module__') and (original_method.__module__ or '').startswith('namedtuple')): return # Some methods are often overridden without documentation. Because it's # obvious what they do, don't include them in the docs if there's no # docstring. if (not member_info.doc.brief.strip() and member_info.short_name in ['__del__', '__copy__']): return # If the current class py_object is a dataclass then use the class object # instead of the __init__ method object because __init__ is a # generated method on dataclasses (unless the definition used init=False) # and `api_generator.get_source.get_source` doesn't work on generated # methods (as the source file doesn't exist) which is required for # signature generation. if (dataclasses.is_dataclass(self.py_object) and member_info.short_name == '__init__' and self.py_object.__dataclass_params__.init): is_dataclass = True py_obj = self.py_object else: is_dataclass = False py_obj = member_info.py_object func_type = signature_lib.get_method_type(original_method, member_info.short_name, is_dataclass) signature = signature_lib.generate_signature(py_obj, self.parser_config, func_type=func_type) decorators = signature_lib.extract_decorators(member_info.py_object) defined_in = parser.get_defined_in(member_info.py_object, self.parser_config) method_info = MethodInfo.from_member_info(member_info, signature, decorators, defined_in) self._methods.append(method_info)
def test_class_vararg_before_kwargonly_consistent_order(self): class MyClass: def __init__(*args, a=1, **kwargs): # pylint: disable=no-method-argument pass sig = signature.generate_signature(MyClass, parser_config=self.parser_config) expected = '(\n *args, a=1, **kwargs\n)' self.assertEqual(expected, str(sig))
def test_dataclass_default_uses_ast_repr(self): @dataclasses.dataclass class MyClass: a: float = 1 / 9 sig = signature.generate_signature(MyClass, parser_config=self.parser_config) expected = '(\n a: float = (1 / 9)\n)' self.assertEqual(expected, str(sig))
def test_known_object(self): def example_fun(arg=self.known_object): # pylint: disable=unused-argument pass sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_full_name='', func_type=signature.FuncType.FUNCTION) self.assertEqual(sig.arguments, ['arg=location.of.object.in.api'])
def collect_docs(self): """Collect all information necessary to genertate the function page. Mainly this is details about the function signature. """ assert self.signature is None self._signature = signature_lib.generate_signature( self.py_object, self.parser_config, func_type=signature_lib.FuncType.FUNCTION, ) self._decorators = signature_lib.extract_decorators(self.py_object)
def test_dataclasses_type_annotations(self): sig = signature.generate_signature( ExampleDataclass, parser_config=self.parser_config, func_type=signature.FuncType.FUNCTION) expected = textwrap.dedent("""\ ( x: List[str], z: int, c: List[int] = dataclasses.field(default_factory=list), a: Union[List[str], str, int] = None, b: str = 'test', y: bool = False )""") self.assertEqual(expected, str(sig))
def collect_docs(self, parser_config): """Collect all information necessary to genertate the function page. Mainly this is details about the function signature. Args: parser_config: The config.ParserConfig for the module being documented. """ assert self.signature is None self._signature = signature_lib.generate_signature( self.py_object, parser_config, self.full_name, func_type=signature_lib.FuncType.FUNCTION, ) self._decorators = signature_lib.extract_decorators(self.py_object)
def test_known_object(self): def example_fun(arg=self.known_object): # pylint: disable=unused-argument pass self.parser_config.reference_resolver = ( self.parser_config.reference_resolver.with_prefix('/')) sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_type=signature.FuncType.FUNCTION) expected = textwrap.dedent("""\ ( arg=<a href="/m/submodule.md#known"><code>m.submodule.known</code></a> )""") self.assertEqual(expected, str(sig))
def test_dataclasses_type_annotations(self): sig = signature.generate_signature( ExampleDataclass, parser_config=self.parser_config, func_full_name='', func_type=signature.FuncType.FUNCTION) self.assertEqual(sig.arguments, [ 'x: List[str]', 'z: int', 'c: List[int] = <factory>', 'a: Union[List[str], str, int] = None', 'b: str = 'test'', 'y: bool = False', ]) self.assertEqual(sig.return_type, 'None') self.assertEqual(sig.arguments_typehint_exists, True)
def test_dataclass_inheritance_sees_parent(self): const = 3.14159 @dataclasses.dataclass class Parent: a: int = 60 * 60 b: float = 1 / 9 @dataclasses.dataclass class Child(Parent): b: float = 2 / 9 c: float = const sig = signature.generate_signature(Child, parser_config=self.parser_config) expected = textwrap.dedent("""\ ( a: int = (60 * 60), b: float = (2 / 9), c: float = const )""") self.assertEqual(expected, str(sig))
def test_literals(self): def example_fun( self, cls, a=5, b=5.0, c=None, d=True, e='hello', f=(1, (2, 3)), ): # pylint: disable=g-bad-name, unused-argument pass sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_full_name='', func_type=signature.FuncType.FUNCTION) self.assertEqual(sig.arguments, [ 'self', 'cls', 'a=5', 'b=5.0', 'c=None', 'd=True', 'e='hello'', 'f=(1, (2, 3))' ])
def test_compulsory_kwargs_without_defaults(self): def example_fun(x, z, a=True, b='test', *, c, y=None, d, **kwargs) -> bool: # pylint: disable=unused-argument return True sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_type=signature.FuncType.FUNCTION) self.assertEqual(list(sig.parameters.keys()), ['x', 'z', 'a', 'b', 'c', 'y', 'd', 'kwargs']) expected = textwrap.dedent("""\ ( x, z, a=True, b='test', *, c, y=None, d, **kwargs ) -> bool""") self.assertEqual(expected, str(sig))
def test_compulsory_kwargs_without_defaults_with_args(self): def example_fun(x, z, cls, *args, a=True, b='test', y=None, c, **kwargs): # pylint: disable=unused-argument return True sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_type=signature.FuncType.FUNCTION) self.assertEqual( list(sig.parameters.keys()), ['x', 'z', 'cls', 'args', 'a', 'b', 'y', 'c', 'kwargs']) self.assertEqual( str(sig), '(\n x, z, cls, *args, a=True, b='test', y=None, c, **kwargs\n)' )
def test_compulsory_kwargs_without_defaults_with_args(self): def example_fun(x, z, cls, *args, a=True, b='test', y=None, c, **kwargs): # pylint: disable=unused-argument return True sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_full_name='', func_type=signature.FuncType.FUNCTION) self.assertEqual(sig.arguments, [ 'x', 'z', 'cls', '*args', 'a=True', 'b='test'', 'y=None', 'c', '**kwargs' ]) self.assertEqual(sig.arguments_typehint_exists, False) self.assertEqual(sig.return_typehint_exists, False)
def test_literals(self): def example_fun( self, cls, a=5, b=5.0, c=None, d=True, e='hello', f=(1, (2, 3)), ): # pylint: disable=g-bad-name, unused-argument pass sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_type=signature.FuncType.FUNCTION) expected = textwrap.dedent("""\ ( self, cls, a=5, b=5.0, c=None, d=True, e='hello', f=(1, (2, 3)) )""") self.assertEqual(expected, str(sig))
def test_type_annotations(self): # pylint: disable=unused-argument class TestMethodSig: def example_fun(self, x: List[str], z: int, a: Union[List[str], str, int] = None, b: str = 'test', *, y: bool = False, c: Callable[..., int], **kwargs) -> None: pass # pylint: enable=unused-argument sig = signature.generate_signature( TestMethodSig.example_fun, parser_config=self.parser_config, func_full_name='', func_type=signature.FuncType.METHOD, ) self.assertEqual(sig.arguments, [ 'x: List[str]', 'z: int', 'a: Union[List[str], str, int] = None', 'b: str = 'test'', '*', 'y: bool = False', 'c: Callable[..., int]', '**kwargs', ]) self.assertEqual(sig.return_type, 'None') self.assertEqual(sig.arguments_typehint_exists, True) self.assertEqual(sig.return_typehint_exists, True)
def test_dotted_name(self): # pylint: disable=g-bad-name class a: class b: class c: class d: def __init__(self, *args): pass # pylint: enable=g-bad-name e = {'f': 1} def example_fun(arg1=a.b.c.d, arg2=a.b.c.d(1, 2), arg3=e['f']): # pylint: disable=unused-argument pass sig = signature.generate_signature( example_fun, parser_config=self.parser_config, func_type=signature.FuncType.FUNCTION) expected = ('(\n arg1=a.b.c.d, arg2=a.b.c.d(1, 2), ' 'arg3=e['f']\n)') self.assertEqual(expected, str(sig))