_signatures.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. """Function signature objects for callables.
  2. Back port of Python 3.3's function signature tools from the inspect module,
  3. modified to be compatible with Python 2.7 and 3.2+.
  4. """
  5. #-----------------------------------------------------------------------------
  6. # Python 3.3 stdlib inspect.py is public domain
  7. #
  8. # Backports Copyright (C) 2013 Aaron Iles
  9. # Used under Apache License Version 2.0
  10. #
  11. # Further Changes are Copyright (C) 2013 The IPython Development Team
  12. #
  13. # Distributed under the terms of the BSD License. The full license is in
  14. # the file COPYING, distributed as part of this software.
  15. #-----------------------------------------------------------------------------
  16. from __future__ import absolute_import, division, print_function
  17. import itertools
  18. import functools
  19. import re
  20. import types
  21. import inspect
  22. # patch for single-file
  23. # we don't support 2.6, so we can just import OrderedDict
  24. from collections import OrderedDict
  25. __version__ = '0.3'
  26. # end patch
  27. __all__ = ['BoundArguments', 'Parameter', 'Signature', 'signature']
  28. _WrapperDescriptor = type(type.__call__)
  29. _MethodWrapper = type(all.__call__)
  30. _NonUserDefinedCallables = (_WrapperDescriptor,
  31. _MethodWrapper,
  32. types.BuiltinFunctionType)
  33. def formatannotation(annotation, base_module=None):
  34. if isinstance(annotation, type):
  35. if annotation.__module__ in ('builtins', '__builtin__', base_module):
  36. return annotation.__name__
  37. return annotation.__module__+'.'+annotation.__name__
  38. return repr(annotation)
  39. def _get_user_defined_method(cls, method_name, *nested):
  40. try:
  41. if cls is type:
  42. return
  43. meth = getattr(cls, method_name)
  44. for name in nested:
  45. meth = getattr(meth, name, meth)
  46. except AttributeError:
  47. return
  48. else:
  49. if not isinstance(meth, _NonUserDefinedCallables):
  50. # Once '__signature__' will be added to 'C'-level
  51. # callables, this check won't be necessary
  52. return meth
  53. def signature(obj):
  54. '''Get a signature object for the passed callable.'''
  55. if not callable(obj):
  56. raise TypeError('{0!r} is not a callable object'.format(obj))
  57. if inspect.ismethod(obj):
  58. if obj.__self__ is None:
  59. # Unbound method - treat it as a function (no distinction in Py 3)
  60. obj = obj.__func__
  61. else:
  62. # Bound method: trim off the first parameter (typically self or cls)
  63. sig = signature(obj.__func__)
  64. return sig.replace(parameters=tuple(sig.parameters.values())[1:])
  65. try:
  66. sig = obj.__signature__
  67. except AttributeError:
  68. pass
  69. else:
  70. if sig is not None:
  71. return sig
  72. try:
  73. # Was this function wrapped by a decorator?
  74. wrapped = obj.__wrapped__
  75. except AttributeError:
  76. pass
  77. else:
  78. return signature(wrapped)
  79. if inspect.isfunction(obj):
  80. return Signature.from_function(obj)
  81. if isinstance(obj, functools.partial):
  82. sig = signature(obj.func)
  83. new_params = OrderedDict(sig.parameters.items())
  84. partial_args = obj.args or ()
  85. partial_keywords = obj.keywords or {}
  86. try:
  87. ba = sig.bind_partial(*partial_args, **partial_keywords)
  88. except TypeError as ex:
  89. msg = 'partial object {0!r} has incorrect arguments'.format(obj)
  90. raise ValueError(msg)
  91. for arg_name, arg_value in ba.arguments.items():
  92. param = new_params[arg_name]
  93. if arg_name in partial_keywords:
  94. # We set a new default value, because the following code
  95. # is correct:
  96. #
  97. # >>> def foo(a): print(a)
  98. # >>> print(partial(partial(foo, a=10), a=20)())
  99. # 20
  100. # >>> print(partial(partial(foo, a=10), a=20)(a=30))
  101. # 30
  102. #
  103. # So, with 'partial' objects, passing a keyword argument is
  104. # like setting a new default value for the corresponding
  105. # parameter
  106. #
  107. # We also mark this parameter with '_partial_kwarg'
  108. # flag. Later, in '_bind', the 'default' value of this
  109. # parameter will be added to 'kwargs', to simulate
  110. # the 'functools.partial' real call.
  111. new_params[arg_name] = param.replace(default=arg_value,
  112. _partial_kwarg=True)
  113. elif (param.kind not in (_VAR_KEYWORD, _VAR_POSITIONAL) and
  114. not param._partial_kwarg):
  115. new_params.pop(arg_name)
  116. return sig.replace(parameters=new_params.values())
  117. sig = None
  118. if isinstance(obj, type):
  119. # obj is a class or a metaclass
  120. # First, let's see if it has an overloaded __call__ defined
  121. # in its metaclass
  122. call = _get_user_defined_method(type(obj), '__call__')
  123. if call is not None:
  124. sig = signature(call)
  125. else:
  126. # Now we check if the 'obj' class has a '__new__' method
  127. new = _get_user_defined_method(obj, '__new__')
  128. if new is not None:
  129. sig = signature(new)
  130. else:
  131. # Finally, we should have at least __init__ implemented
  132. init = _get_user_defined_method(obj, '__init__')
  133. if init is not None:
  134. sig = signature(init)
  135. elif not isinstance(obj, _NonUserDefinedCallables):
  136. # An object with __call__
  137. # We also check that the 'obj' is not an instance of
  138. # _WrapperDescriptor or _MethodWrapper to avoid
  139. # infinite recursion (and even potential segfault)
  140. call = _get_user_defined_method(type(obj), '__call__', 'im_func')
  141. if call is not None:
  142. sig = signature(call)
  143. if sig is not None:
  144. return sig
  145. if isinstance(obj, types.BuiltinFunctionType):
  146. # Raise a nicer error message for builtins
  147. msg = 'no signature found for builtin function {0!r}'.format(obj)
  148. raise ValueError(msg)
  149. raise ValueError('callable {0!r} is not supported by signature'.format(obj))
  150. class _void(object):
  151. '''A private marker - used in Parameter & Signature'''
  152. class _empty(object):
  153. pass
  154. class _ParameterKind(int):
  155. def __new__(self, *args, **kwargs):
  156. obj = int.__new__(self, *args)
  157. obj._name = kwargs['name']
  158. return obj
  159. def __str__(self):
  160. return self._name
  161. def __repr__(self):
  162. return '<_ParameterKind: {0!r}>'.format(self._name)
  163. _POSITIONAL_ONLY = _ParameterKind(0, name='POSITIONAL_ONLY')
  164. _POSITIONAL_OR_KEYWORD = _ParameterKind(1, name='POSITIONAL_OR_KEYWORD')
  165. _VAR_POSITIONAL = _ParameterKind(2, name='VAR_POSITIONAL')
  166. _KEYWORD_ONLY = _ParameterKind(3, name='KEYWORD_ONLY')
  167. _VAR_KEYWORD = _ParameterKind(4, name='VAR_KEYWORD')
  168. class Parameter(object):
  169. '''Represents a parameter in a function signature.
  170. Has the following public attributes:
  171. * name : str
  172. The name of the parameter as a string.
  173. * default : object
  174. The default value for the parameter if specified. If the
  175. parameter has no default value, this attribute is not set.
  176. * annotation
  177. The annotation for the parameter if specified. If the
  178. parameter has no annotation, this attribute is not set.
  179. * kind : str
  180. Describes how argument values are bound to the parameter.
  181. Possible values: `Parameter.POSITIONAL_ONLY`,
  182. `Parameter.POSITIONAL_OR_KEYWORD`, `Parameter.VAR_POSITIONAL`,
  183. `Parameter.KEYWORD_ONLY`, `Parameter.VAR_KEYWORD`.
  184. '''
  185. __slots__ = ('_name', '_kind', '_default', '_annotation', '_partial_kwarg')
  186. POSITIONAL_ONLY = _POSITIONAL_ONLY
  187. POSITIONAL_OR_KEYWORD = _POSITIONAL_OR_KEYWORD
  188. VAR_POSITIONAL = _VAR_POSITIONAL
  189. KEYWORD_ONLY = _KEYWORD_ONLY
  190. VAR_KEYWORD = _VAR_KEYWORD
  191. empty = _empty
  192. def __init__(self, name, kind, default=_empty, annotation=_empty,
  193. _partial_kwarg=False):
  194. if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD,
  195. _VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD):
  196. raise ValueError("invalid value for 'Parameter.kind' attribute")
  197. self._kind = kind
  198. if default is not _empty:
  199. if kind in (_VAR_POSITIONAL, _VAR_KEYWORD):
  200. msg = '{0} parameters cannot have default values'.format(kind)
  201. raise ValueError(msg)
  202. self._default = default
  203. self._annotation = annotation
  204. if name is None:
  205. if kind != _POSITIONAL_ONLY:
  206. raise ValueError("None is not a valid name for a "
  207. "non-positional-only parameter")
  208. self._name = name
  209. else:
  210. name = str(name)
  211. if kind != _POSITIONAL_ONLY and not re.match(r'[a-z_]\w*$', name, re.I):
  212. msg = '{0!r} is not a valid parameter name'.format(name)
  213. raise ValueError(msg)
  214. self._name = name
  215. self._partial_kwarg = _partial_kwarg
  216. @property
  217. def name(self):
  218. return self._name
  219. @property
  220. def default(self):
  221. return self._default
  222. @property
  223. def annotation(self):
  224. return self._annotation
  225. @property
  226. def kind(self):
  227. return self._kind
  228. def replace(self, name=_void, kind=_void, annotation=_void,
  229. default=_void, _partial_kwarg=_void):
  230. '''Creates a customized copy of the Parameter.'''
  231. if name is _void:
  232. name = self._name
  233. if kind is _void:
  234. kind = self._kind
  235. if annotation is _void:
  236. annotation = self._annotation
  237. if default is _void:
  238. default = self._default
  239. if _partial_kwarg is _void:
  240. _partial_kwarg = self._partial_kwarg
  241. return type(self)(name, kind, default=default, annotation=annotation,
  242. _partial_kwarg=_partial_kwarg)
  243. def __str__(self):
  244. kind = self.kind
  245. formatted = self._name
  246. if kind == _POSITIONAL_ONLY:
  247. if formatted is None:
  248. formatted = ''
  249. formatted = '<{0}>'.format(formatted)
  250. # Add annotation and default value
  251. if self._annotation is not _empty:
  252. formatted = '{0}:{1}'.format(formatted,
  253. formatannotation(self._annotation))
  254. if self._default is not _empty:
  255. formatted = '{0}={1}'.format(formatted, repr(self._default))
  256. if kind == _VAR_POSITIONAL:
  257. formatted = '*' + formatted
  258. elif kind == _VAR_KEYWORD:
  259. formatted = '**' + formatted
  260. return formatted
  261. def __repr__(self):
  262. return '<{0} at {1:#x} {2!r}>'.format(self.__class__.__name__,
  263. id(self), self.name)
  264. def __hash__(self):
  265. msg = "unhashable type: '{0}'".format(self.__class__.__name__)
  266. raise TypeError(msg)
  267. def __eq__(self, other):
  268. return (issubclass(other.__class__, Parameter) and
  269. self._name == other._name and
  270. self._kind == other._kind and
  271. self._default == other._default and
  272. self._annotation == other._annotation)
  273. def __ne__(self, other):
  274. return not self.__eq__(other)
  275. class BoundArguments(object):
  276. '''Result of :meth:`Signature.bind` call. Holds the mapping of arguments
  277. to the function's parameters.
  278. Has the following public attributes:
  279. arguments : :class:`collections.OrderedDict`
  280. An ordered mutable mapping of parameters' names to arguments' values.
  281. Does not contain arguments' default values.
  282. signature : :class:`Signature`
  283. The Signature object that created this instance.
  284. args : tuple
  285. Tuple of positional arguments values.
  286. kwargs : dict
  287. Dict of keyword arguments values.
  288. '''
  289. def __init__(self, signature, arguments):
  290. self.arguments = arguments
  291. self._signature = signature
  292. @property
  293. def signature(self):
  294. return self._signature
  295. @property
  296. def args(self):
  297. args = []
  298. for param_name, param in self._signature.parameters.items():
  299. if (param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY) or
  300. param._partial_kwarg):
  301. # Keyword arguments mapped by 'functools.partial'
  302. # (Parameter._partial_kwarg is True) are mapped
  303. # in 'BoundArguments.kwargs', along with VAR_KEYWORD &
  304. # KEYWORD_ONLY
  305. break
  306. try:
  307. arg = self.arguments[param_name]
  308. except KeyError:
  309. # We're done here. Other arguments
  310. # will be mapped in 'BoundArguments.kwargs'
  311. break
  312. else:
  313. if param.kind == _VAR_POSITIONAL:
  314. # *args
  315. args.extend(arg)
  316. else:
  317. # plain argument
  318. args.append(arg)
  319. return tuple(args)
  320. @property
  321. def kwargs(self):
  322. kwargs = {}
  323. kwargs_started = False
  324. for param_name, param in self._signature.parameters.items():
  325. if not kwargs_started:
  326. if (param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY) or
  327. param._partial_kwarg):
  328. kwargs_started = True
  329. else:
  330. if param_name not in self.arguments:
  331. kwargs_started = True
  332. continue
  333. if not kwargs_started:
  334. continue
  335. try:
  336. arg = self.arguments[param_name]
  337. except KeyError:
  338. pass
  339. else:
  340. if param.kind == _VAR_KEYWORD:
  341. # **kwargs
  342. kwargs.update(arg)
  343. else:
  344. # plain keyword argument
  345. kwargs[param_name] = arg
  346. return kwargs
  347. def __hash__(self):
  348. msg = "unhashable type: '{0}'".format(self.__class__.__name__)
  349. raise TypeError(msg)
  350. def __eq__(self, other):
  351. return (issubclass(other.__class__, BoundArguments) and
  352. self.signature == other.signature and
  353. self.arguments == other.arguments)
  354. def __ne__(self, other):
  355. return not self.__eq__(other)
  356. class Signature(object):
  357. '''A Signature object represents the overall signature of a function.
  358. It stores a Parameter object for each parameter accepted by the
  359. function, as well as information specific to the function itself.
  360. A Signature object has the following public attributes:
  361. parameters : :class:`collections.OrderedDict`
  362. An ordered mapping of parameters' names to the corresponding
  363. Parameter objects (keyword-only arguments are in the same order
  364. as listed in `code.co_varnames`).
  365. return_annotation
  366. The annotation for the return type of the function if specified.
  367. If the function has no annotation for its return type, this
  368. attribute is not set.
  369. '''
  370. __slots__ = ('_return_annotation', '_parameters')
  371. _parameter_cls = Parameter
  372. _bound_arguments_cls = BoundArguments
  373. empty = _empty
  374. def __init__(self, parameters=None, return_annotation=_empty,
  375. __validate_parameters__=True):
  376. '''Constructs Signature from the given list of Parameter
  377. objects and 'return_annotation'. All arguments are optional.
  378. '''
  379. if parameters is None:
  380. params = OrderedDict()
  381. else:
  382. if __validate_parameters__:
  383. params = OrderedDict()
  384. top_kind = _POSITIONAL_ONLY
  385. for idx, param in enumerate(parameters):
  386. kind = param.kind
  387. if kind < top_kind:
  388. msg = 'wrong parameter order: {0} before {1}'
  389. msg = msg.format(top_kind, param.kind)
  390. raise ValueError(msg)
  391. else:
  392. top_kind = kind
  393. name = param.name
  394. if name is None:
  395. name = str(idx)
  396. param = param.replace(name=name)
  397. if name in params:
  398. msg = 'duplicate parameter name: {0!r}'.format(name)
  399. raise ValueError(msg)
  400. params[name] = param
  401. else:
  402. params = OrderedDict(((param.name, param)
  403. for param in parameters))
  404. self._parameters = params
  405. self._return_annotation = return_annotation
  406. @classmethod
  407. def from_function(cls, func):
  408. '''Constructs Signature for the given python function'''
  409. if not inspect.isfunction(func):
  410. raise TypeError('{0!r} is not a Python function'.format(func))
  411. Parameter = cls._parameter_cls
  412. # Parameter information.
  413. func_code = func.__code__
  414. pos_count = func_code.co_argcount
  415. arg_names = func_code.co_varnames
  416. positional = tuple(arg_names[:pos_count])
  417. keyword_only_count = getattr(func_code, 'co_kwonlyargcount', 0)
  418. keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)]
  419. annotations = getattr(func, '__annotations__', {})
  420. defaults = func.__defaults__
  421. kwdefaults = getattr(func, '__kwdefaults__', None)
  422. if defaults:
  423. pos_default_count = len(defaults)
  424. else:
  425. pos_default_count = 0
  426. parameters = []
  427. # Non-keyword-only parameters w/o defaults.
  428. non_default_count = pos_count - pos_default_count
  429. for name in positional[:non_default_count]:
  430. annotation = annotations.get(name, _empty)
  431. parameters.append(Parameter(name, annotation=annotation,
  432. kind=_POSITIONAL_OR_KEYWORD))
  433. # ... w/ defaults.
  434. for offset, name in enumerate(positional[non_default_count:]):
  435. annotation = annotations.get(name, _empty)
  436. parameters.append(Parameter(name, annotation=annotation,
  437. kind=_POSITIONAL_OR_KEYWORD,
  438. default=defaults[offset]))
  439. # *args
  440. if func_code.co_flags & 0x04:
  441. name = arg_names[pos_count + keyword_only_count]
  442. annotation = annotations.get(name, _empty)
  443. parameters.append(Parameter(name, annotation=annotation,
  444. kind=_VAR_POSITIONAL))
  445. # Keyword-only parameters.
  446. for name in keyword_only:
  447. default = _empty
  448. if kwdefaults is not None:
  449. default = kwdefaults.get(name, _empty)
  450. annotation = annotations.get(name, _empty)
  451. parameters.append(Parameter(name, annotation=annotation,
  452. kind=_KEYWORD_ONLY,
  453. default=default))
  454. # **kwargs
  455. if func_code.co_flags & 0x08:
  456. index = pos_count + keyword_only_count
  457. if func_code.co_flags & 0x04:
  458. index += 1
  459. name = arg_names[index]
  460. annotation = annotations.get(name, _empty)
  461. parameters.append(Parameter(name, annotation=annotation,
  462. kind=_VAR_KEYWORD))
  463. return cls(parameters,
  464. return_annotation=annotations.get('return', _empty),
  465. __validate_parameters__=False)
  466. @property
  467. def parameters(self):
  468. try:
  469. return types.MappingProxyType(self._parameters)
  470. except AttributeError:
  471. return OrderedDict(self._parameters.items())
  472. @property
  473. def return_annotation(self):
  474. return self._return_annotation
  475. def replace(self, parameters=_void, return_annotation=_void):
  476. '''Creates a customized copy of the Signature.
  477. Pass 'parameters' and/or 'return_annotation' arguments
  478. to override them in the new copy.
  479. '''
  480. if parameters is _void:
  481. parameters = self.parameters.values()
  482. if return_annotation is _void:
  483. return_annotation = self._return_annotation
  484. return type(self)(parameters,
  485. return_annotation=return_annotation)
  486. def __hash__(self):
  487. msg = "unhashable type: '{0}'".format(self.__class__.__name__)
  488. raise TypeError(msg)
  489. def __eq__(self, other):
  490. if (not issubclass(type(other), Signature) or
  491. self.return_annotation != other.return_annotation or
  492. len(self.parameters) != len(other.parameters)):
  493. return False
  494. other_positions = dict((param, idx)
  495. for idx, param in enumerate(other.parameters.keys()))
  496. for idx, (param_name, param) in enumerate(self.parameters.items()):
  497. if param.kind == _KEYWORD_ONLY:
  498. try:
  499. other_param = other.parameters[param_name]
  500. except KeyError:
  501. return False
  502. else:
  503. if param != other_param:
  504. return False
  505. else:
  506. try:
  507. other_idx = other_positions[param_name]
  508. except KeyError:
  509. return False
  510. else:
  511. if (idx != other_idx or
  512. param != other.parameters[param_name]):
  513. return False
  514. return True
  515. def __ne__(self, other):
  516. return not self.__eq__(other)
  517. def _bind(self, args, kwargs, partial=False):
  518. '''Private method. Don't use directly.'''
  519. arguments = OrderedDict()
  520. parameters = iter(self.parameters.values())
  521. parameters_ex = ()
  522. arg_vals = iter(args)
  523. if partial:
  524. # Support for binding arguments to 'functools.partial' objects.
  525. # See 'functools.partial' case in 'signature()' implementation
  526. # for details.
  527. for param_name, param in self.parameters.items():
  528. if (param._partial_kwarg and param_name not in kwargs):
  529. # Simulating 'functools.partial' behavior
  530. kwargs[param_name] = param.default
  531. while True:
  532. # Let's iterate through the positional arguments and corresponding
  533. # parameters
  534. try:
  535. arg_val = next(arg_vals)
  536. except StopIteration:
  537. # No more positional arguments
  538. try:
  539. param = next(parameters)
  540. except StopIteration:
  541. # No more parameters. That's it. Just need to check that
  542. # we have no `kwargs` after this while loop
  543. break
  544. else:
  545. if param.kind == _VAR_POSITIONAL:
  546. # That's OK, just empty *args. Let's start parsing
  547. # kwargs
  548. break
  549. elif param.name in kwargs:
  550. if param.kind == _POSITIONAL_ONLY:
  551. msg = '{arg!r} parameter is positional only, ' \
  552. 'but was passed as a keyword'
  553. msg = msg.format(arg=param.name)
  554. raise TypeError(msg)
  555. parameters_ex = (param,)
  556. break
  557. elif (param.kind == _VAR_KEYWORD or
  558. param.default is not _empty):
  559. # That's fine too - we have a default value for this
  560. # parameter. So, lets start parsing `kwargs`, starting
  561. # with the current parameter
  562. parameters_ex = (param,)
  563. break
  564. else:
  565. if partial:
  566. parameters_ex = (param,)
  567. break
  568. else:
  569. msg = '{arg!r} parameter lacking default value'
  570. msg = msg.format(arg=param.name)
  571. raise TypeError(msg)
  572. else:
  573. # We have a positional argument to process
  574. try:
  575. param = next(parameters)
  576. except StopIteration:
  577. raise TypeError('too many positional arguments')
  578. else:
  579. if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY):
  580. # Looks like we have no parameter for this positional
  581. # argument
  582. raise TypeError('too many positional arguments')
  583. if param.kind == _VAR_POSITIONAL:
  584. # We have an '*args'-like argument, let's fill it with
  585. # all positional arguments we have left and move on to
  586. # the next phase
  587. values = [arg_val]
  588. values.extend(arg_vals)
  589. arguments[param.name] = tuple(values)
  590. break
  591. if param.name in kwargs:
  592. raise TypeError('multiple values for argument '
  593. '{arg!r}'.format(arg=param.name))
  594. arguments[param.name] = arg_val
  595. # Now, we iterate through the remaining parameters to process
  596. # keyword arguments
  597. kwargs_param = None
  598. for param in itertools.chain(parameters_ex, parameters):
  599. if param.kind == _POSITIONAL_ONLY:
  600. # This should never happen in case of a properly built
  601. # Signature object (but let's have this check here
  602. # to ensure correct behaviour just in case)
  603. raise TypeError('{arg!r} parameter is positional only, '
  604. 'but was passed as a keyword'. \
  605. format(arg=param.name))
  606. if param.kind == _VAR_KEYWORD:
  607. # Memorize that we have a '**kwargs'-like parameter
  608. kwargs_param = param
  609. continue
  610. param_name = param.name
  611. try:
  612. arg_val = kwargs.pop(param_name)
  613. except KeyError:
  614. # We have no value for this parameter. It's fine though,
  615. # if it has a default value, or it is an '*args'-like
  616. # parameter, left alone by the processing of positional
  617. # arguments.
  618. if (not partial and param.kind != _VAR_POSITIONAL and
  619. param.default is _empty):
  620. raise TypeError('{arg!r} parameter lacking default value'. \
  621. format(arg=param_name))
  622. else:
  623. arguments[param_name] = arg_val
  624. if kwargs:
  625. if kwargs_param is not None:
  626. # Process our '**kwargs'-like parameter
  627. arguments[kwargs_param.name] = kwargs
  628. else:
  629. raise TypeError('too many keyword arguments')
  630. return self._bound_arguments_cls(self, arguments)
  631. def bind(self, *args, **kwargs):
  632. '''Get a :class:`BoundArguments` object, that maps the passed `args`
  633. and `kwargs` to the function's signature. Raises :exc:`TypeError`
  634. if the passed arguments can not be bound.
  635. '''
  636. return self._bind(args, kwargs)
  637. def bind_partial(self, *args, **kwargs):
  638. '''Get a :class:`BoundArguments` object, that partially maps the
  639. passed `args` and `kwargs` to the function's signature.
  640. Raises :exc:`TypeError` if the passed arguments can not be bound.
  641. '''
  642. return self._bind(args, kwargs, partial=True)
  643. def __str__(self):
  644. result = []
  645. render_kw_only_separator = True
  646. for idx, param in enumerate(self.parameters.values()):
  647. formatted = str(param)
  648. kind = param.kind
  649. if kind == _VAR_POSITIONAL:
  650. # OK, we have an '*args'-like parameter, so we won't need
  651. # a '*' to separate keyword-only arguments
  652. render_kw_only_separator = False
  653. elif kind == _KEYWORD_ONLY and render_kw_only_separator:
  654. # We have a keyword-only parameter to render and we haven't
  655. # rendered an '*args'-like parameter before, so add a '*'
  656. # separator to the parameters list ("foo(arg1, *, arg2)" case)
  657. result.append('*')
  658. # This condition should be only triggered once, so
  659. # reset the flag
  660. render_kw_only_separator = False
  661. result.append(formatted)
  662. rendered = '({0})'.format(', '.join(result))
  663. if self.return_annotation is not _empty:
  664. anno = formatannotation(self.return_annotation)
  665. rendered += ' -> {0}'.format(anno)
  666. return rendered