def test_all(self): self.assertSigsEqual( s('one, two, /, three, four, *five, six, seven, **eight'), apply_params( s(''), [p('one, /'), p('two, /')], [p('three'), p('four')], p('*five'), OrderedDict((('six', p('*, six')), ('seven', p('*, seven')))), p('**eight')))
def embed(use_varargs=True, use_varkwargs=True, *signatures): """Embeds a signature within another's ``*args`` and ``**kwargs`` parameters, as if a function with the outer signature called a function with the inner signature with just ``f(*args, **kwargs)``. :param inspect.Signature signatures: The signatures to embed within one-another, outermost first. :param bool use_varargs: Make use of the ``*args``-like parameter. :param bool use_varkwargs: Make use of the ``*kwargs``-like parameter. :returns: a `inspect.Signature` object :raises: `IncompatibleSignatures` :: >>> from sigtools import signatures, support >>> print(signatures.embed( ... support.s('one, *args, **kwargs'), ... support.s('two, *args, kw, **kwargs'), ... support.s('last'), ... )) (one, two, last, *, kw) >>> # use signatures.mask() to remove self-like parameters >>> print(signatures.embed( ... support.s('self, *args, **kwargs'), ... signatures.mask( ... support.s('self, *args, keyword, **kwargs'), 1), ... )) (self, *args, keyword, **kwargs) """ assert signatures ret = sort_params(signatures[0]) for i, sig in enumerate(signatures[1:], 1): try: ret = _embed(ret, sort_params(sig), use_varargs, use_varkwargs) except ValueError: raise IncompatibleSignatures(sig, signatures[:i]) return apply_params(signatures[0], *ret)
def merge(*signatures): """Tries to compute a signature for which a valid call would also validate the given signatures. It guarantees any call that conforms to the merged signature will conform to all the given signatures. However, some calls that don't conform to the merged signature may actually work on all the given ones regardless. :param inspect.Signature signatures: The signatures to merge together. :returns: a `inspect.Signature` object :raises: `IncompatibleSignatures` :: >>> from sigtools import signatures, support >>> print(signatures.merge( ... support.s('one, two, *args, **kwargs'), ... support.s('one, two, three, *, alpha, **kwargs'), ... support.s('one, *args, beta, **kwargs') ... )) (one, two, three, *, alpha, beta, **kwargs) The resulting signature does not necessarily validate all ways of conforming to the underlying signatures:: >>> from sigtools import signatures >>> from inspect import signature >>> >>> def left(alpha, *args, **kwargs): ... return alpha ... >>> def right(beta, *args, **kwargs): ... return beta ... >>> sig_left = signature(left) >>> sig_right = signature(right) >>> sig_merged = signatures.merge(sig_left, sig_right) >>> >>> print(sig_merged) (alpha, /, *args, **kwargs) >>> >>> kwargs = {'alpha': 'a', 'beta': 'b'} >>> left(**kwargs), right(**kwargs) # both functions accept the call ('a', 'b') >>> >>> sig_merged.bind(**kwargs) # the merged signature doesn't Traceback (most recent call last): File "<input>", line 1, in <module> File "/usr/lib64/python3.4/inspect.py", line 2642, in bind return args[0]._bind(args[1:], kwargs) File "/usr/lib64/python3.4/inspect.py", line 2542, in _bind raise TypeError(msg) from None TypeError: 'alpha' parameter is positional only, but was passed as a keyword """ assert signatures, "Expected at least one signature" ret = sort_params(signatures[0]) for i, sig in enumerate(signatures[1:], 1): sorted_params = sort_params(sig) try: ret = _merge(ret, sorted_params) except ValueError: raise IncompatibleSignatures(sig, signatures[:i]) return apply_params(signatures[0], *ret)
def test_roundtrip(self): sig_str = 'one, two, /, three, four, *five, six, seven, **eight' sig = s(sig_str) self.assertEqual(apply_params(s(''), *sort_params(sig)), sig)
def test_empty(self): self.assertSigsEqual(s(''), apply_params(s(''), [], [], None, {}, None))