_functools.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import collections.abc
  2. import functools
  3. # from jaraco.functools 3.5
  4. def pass_none(func):
  5. """
  6. Wrap func so it's not called if its first param is None
  7. >>> print_text = pass_none(print)
  8. >>> print_text('text')
  9. text
  10. >>> print_text(None)
  11. """
  12. @functools.wraps(func)
  13. def wrapper(param, *args, **kwargs):
  14. if param is not None:
  15. return func(param, *args, **kwargs)
  16. return wrapper
  17. # from jaraco.functools 4.0
  18. @functools.singledispatch
  19. def _splat_inner(args, func):
  20. """Splat args to func."""
  21. return func(*args)
  22. @_splat_inner.register
  23. def _(args: collections.abc.Mapping, func):
  24. """Splat kargs to func as kwargs."""
  25. return func(**args)
  26. def splat(func):
  27. """
  28. Wrap func to expect its parameters to be passed positionally in a tuple.
  29. Has a similar effect to that of ``itertools.starmap`` over
  30. simple ``map``.
  31. >>> import itertools, operator
  32. >>> pairs = [(-1, 1), (0, 2)]
  33. >>> _ = tuple(itertools.starmap(print, pairs))
  34. -1 1
  35. 0 2
  36. >>> _ = tuple(map(splat(print), pairs))
  37. -1 1
  38. 0 2
  39. The approach generalizes to other iterators that don't have a "star"
  40. equivalent, such as a "starfilter".
  41. >>> list(filter(splat(operator.add), pairs))
  42. [(0, 2)]
  43. Splat also accepts a mapping argument.
  44. >>> def is_nice(msg, code):
  45. ... return "smile" in msg or code == 0
  46. >>> msgs = [
  47. ... dict(msg='smile!', code=20),
  48. ... dict(msg='error :(', code=1),
  49. ... dict(msg='unknown', code=0),
  50. ... ]
  51. >>> for msg in filter(splat(is_nice), msgs):
  52. ... print(msg)
  53. {'msg': 'smile!', 'code': 20}
  54. {'msg': 'unknown', 'code': 0}
  55. """
  56. return functools.wraps(func)(functools.partial(_splat_inner, func=func))