def test_Signature_keyword_only_arguments(): def func1(arg1, arg2, *, arg3=None, arg4=None): pass def func2(*, arg3, arg4): pass sig = inspect.Signature(func1).format_args() assert sig == '(arg1, arg2, *, arg3=None, arg4=None)' sig = inspect.Signature(func2).format_args() assert sig == '(*, arg3, arg4)'
def test_Signature_partial(): def fun(a, b, c=1, d=2): pass p = functools.partial(fun, 10, c=11) sig = inspect.Signature(p).format_args() assert sig == '(b, *, c=11, d=2)'
def format_args(self): # for instances, the relevant signature is the __call__ method's callmeth = self.get_attr(self.object, '__call__', None) if callmeth: sig = inspect.Signature(callmeth, bound_method=True, has_retval=True) return sig.format_args() return None
def test_Signature_partial(): def fun(a, b, c=1, d=2): pass p = functools.partial(fun, 10, c=11) sig = inspect.Signature(p).format_args() if sys.version_info < (3,): assert sig == '(b, d=2)' else: assert sig == '(b, *, c=11, d=2)'
def test_Signature(): # literals with pytest.raises(TypeError): inspect.Signature(1) with pytest.raises(TypeError): inspect.Signature('') # builitin classes with pytest.raises(TypeError): inspect.Signature(int) with pytest.raises(TypeError): inspect.Signature(str) # normal function def func(a, b, c=1, d=2, *e, **f): pass sig = inspect.Signature(func).format_args() assert sig == '(a, b, c=1, d=2, *e, **f)'
def test_Signature_methods(): class Foo: def meth1(self, arg1, **kwargs): pass @classmethod def meth2(cls, arg1, *args, **kwargs): pass @staticmethod def meth3(arg1, *args, **kwargs): pass @functools.wraps(Foo().meth1) def wrapped_bound_method(*args, **kwargs): pass # unbound method sig = inspect.Signature(Foo.meth1).format_args() assert sig == '(self, arg1, **kwargs)' sig = inspect.Signature(Foo.meth1, bound_method=True).format_args() assert sig == '(arg1, **kwargs)' # bound method sig = inspect.Signature(Foo().meth1).format_args() assert sig == '(arg1, **kwargs)' # class method sig = inspect.Signature(Foo.meth2).format_args() assert sig == '(arg1, *args, **kwargs)' sig = inspect.Signature(Foo().meth2).format_args() assert sig == '(arg1, *args, **kwargs)' # static method sig = inspect.Signature(Foo.meth3).format_args() assert sig == '(arg1, *args, **kwargs)' sig = inspect.Signature(Foo().meth3).format_args() assert sig == '(arg1, *args, **kwargs)' # wrapped bound method sig = inspect.Signature(wrapped_bound_method).format_args() if sys.version_info < (3, ): assert sig == '(*args, **kwargs)' elif sys.version_info < (3, 4, 4): assert sig == '(self, arg1, **kwargs)' else: assert sig == '(arg1, **kwargs)'
def test_Signature_partialmethod(): from functools import partialmethod class Foo: def meth1(self, arg1, arg2, arg3=None, arg4=None): pass def meth2(self, arg1, arg2): pass foo = partialmethod(meth1, 1, 2) bar = partialmethod(meth1, 1, arg3=3) baz = partialmethod(meth2, 1, 2) subject = Foo() sig = inspect.Signature(subject.foo).format_args() assert sig == '(arg3=None, arg4=None)' sig = inspect.Signature(subject.bar).format_args() assert sig == '(arg2, *, arg3=3, arg4=None)' sig = inspect.Signature(subject.baz).format_args() assert sig == '()'
def test_Signature_annotations(): from typing_test_data import (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, Node) # Class annotations sig = inspect.Signature(f0).format_args() assert sig == '(x: int, y: numbers.Integral) -> None' # Generic types with concrete parameters sig = inspect.Signature(f1).format_args() assert sig == '(x: List[int]) -> List[int]' # TypeVars and generic types with TypeVars sig = inspect.Signature(f2).format_args() assert sig == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]' # Union types sig = inspect.Signature(f3).format_args() assert sig == '(x: Union[str, numbers.Integral]) -> None' # Quoted annotations sig = inspect.Signature(f4).format_args() assert sig == '(x: str, y: str) -> None' # Keyword-only arguments sig = inspect.Signature(f5).format_args() assert sig == '(x: int, *, y: str, z: str) -> None' # Keyword-only arguments with varargs sig = inspect.Signature(f6).format_args() assert sig == '(x: int, *args, y: str, z: str) -> None' # Space around '=' for defaults sig = inspect.Signature(f7).format_args() assert sig == '(x: int = None, y: dict = {}) -> None' # Callable types sig = inspect.Signature(f8).format_args() assert sig == '(x: Callable[[int, str], int]) -> None' sig = inspect.Signature(f9).format_args() assert sig == '(x: Callable) -> None' # Tuple types sig = inspect.Signature(f10).format_args() assert sig == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None' # Instance annotations sig = inspect.Signature(f11).format_args() assert sig == '(x: CustomAnnotation, y: 123) -> None' # has_retval=False sig = inspect.Signature(f11, has_retval=False).format_args() assert sig == '(x: CustomAnnotation, y: 123)' # tuple with more than two items sig = inspect.Signature(f12).format_args() assert sig == '() -> Tuple[int, str, int]' # optional sig = inspect.Signature(f13).format_args() assert sig == '() -> Optional[str]' # Any sig = inspect.Signature(f14).format_args() assert sig == '() -> Any' # ForwardRef sig = inspect.Signature(f15).format_args() assert sig == '(x: Unknown, y: int) -> Any' # keyword only arguments (1) sig = inspect.Signature(f16).format_args() assert sig == '(arg1, arg2, *, arg3=None, arg4=None)' # keyword only arguments (2) sig = inspect.Signature(f17).format_args() assert sig == '(*, arg3, arg4)' # type hints by string sig = inspect.Signature(Node.children).format_args() if (3, 5, 0) <= sys.version_info < (3, 5, 3): assert sig == '(self) -> List[Node]' else: assert sig == '(self) -> List[typing_test_data.Node]' sig = inspect.Signature(Node.__init__).format_args() assert sig == '(self, parent: Optional[Node]) -> None'
def test_Signature_annotations(): from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11 # Class annotations sig = inspect.Signature(f0).format_args() assert sig == '(x: int, y: numbers.Integral) -> None' # Generic types with concrete parameters sig = inspect.Signature(f1).format_args() assert sig == '(x: typing.List[int]) -> typing.List[int]' # TypeVars and generic types with TypeVars sig = inspect.Signature(f2).format_args() assert sig == '(x: typing.List[T], y: typing.List[T_co], z: T) -> typing.List[T_contra]' # Union types sig = inspect.Signature(f3).format_args() assert sig == '(x: typing.Union[str, numbers.Integral]) -> None' # Quoted annotations sig = inspect.Signature(f4).format_args() assert sig == '(x: str, y: str) -> None' # Keyword-only arguments sig = inspect.Signature(f5).format_args() assert sig == '(x: int, *, y: str, z: str) -> None' # Keyword-only arguments with varargs sig = inspect.Signature(f6).format_args() assert sig == '(x: int, *args, y: str, z: str) -> None' # Space around '=' for defaults sig = inspect.Signature(f7).format_args() assert sig == '(x: int = None, y: dict = {}) -> None' # Callable types sig = inspect.Signature(f8).format_args() assert sig == '(x: typing.Callable[[int, str], int]) -> None' sig = inspect.Signature(f9).format_args() assert sig == '(x: typing.Callable) -> None' # Tuple types sig = inspect.Signature(f10).format_args() assert sig == '(x: typing.Tuple[int, str], y: typing.Tuple[int, ...]) -> None' # Instance annotations sig = inspect.Signature(f11).format_args() assert sig == '(x: CustomAnnotation, y: 123) -> None'
def command_doc(module): """ Document command classes """ mod = importlib.import_module(module) print(".. automodule:: {}".format(module)) config = Config() cls_str = """.. py:function:: {}{} {} .. rubric:: Available entries: {} .. rubric:: Available events: {} """ cmd_str = """.. py:function:: {}{} {} """ cls_str = inspect.cleandoc(cls_str) cmd_str = inspect.cleandoc(cmd_str) def indent_text(txt, num=4): return "\n".join((num * " ") + i for i in txt) def doc_process(docstr, obj, retval=True, indent=4, config=config, docstring=docstring, inspect=inspect, process_docstring=process_docstring, indent_text=indent_text): docstr = docstring.GoogleDocstring(inspect.cleandoc(docstr), config, obj=obj) docslines = str(docstr).splitlines() process_docstring(None, '', '', obj, config, docslines) if docslines: r = docslines.pop(0) # put rtype last if retval: docslines.append(r) # indent if indent: docstr = indent_text(docslines, indent) else: docstr = "\n".join(docslines) return docstr for name, obj in inspect.getmembers(mod, inspect.isclass): if not obj.__name__.startswith('_') and obj.__module__ == mod.__name__ and issubclass(obj, command.CoreCommand): if getattr(obj, 'main', False): objfunc = obj.main else: objfunc = obj.__init__ sig = sinspect.Signature(objfunc, bound_method=True) obj._get_commands() entries = [] events = [] e_objfunc = None for x, e in sorted(obj._entries.items()): esig = sinspect.Signature(objfunc) esig.signature = e.signature ex_local = {'happypanda': happypanda, 'collections': collections} ex_local.update(mod.__dict__) ex_local.update(globals()) exec("def e_objfunc{}:None".format(esig.signature), ex_local, ex_local) e_objfunc = ex_local['e_objfunc'] entries.append(" - {}".format(cmd_str.format(x, esig.format_args(), str(doc_process(e.__doc__, e_objfunc, False, indent=8))))) for x, e in sorted(obj._events.items()): esig = sinspect.Signature(objfunc) esig.signature = e.signature ex_local = {'happypanda': happypanda, 'collections': collections} ex_local.update(mod.__dict__) ex_local.update(globals()) exec("def e_objfunc{}:None".format(esig.signature), ex_local, ex_local) e_objfunc = ex_local['e_objfunc'] events.append(" - {}".format(cmd_str.format(x, esig.format_args(), str(doc_process(e.__doc__, e_objfunc, False, indent=8))))) retval = sig.signature.return_annotation sig.signature = sig.signature.replace(return_annotation=inspect.Signature.empty) docstr = doc_process(obj.__doc__, objfunc) print(cls_str.format(name, sig.format_args(), str(docstr), '\n'.join(entries), '\n'.join(events)))