iterable.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # -*- coding: utf-8 -*-
  2. '''stuf iterables.'''
  3. from functools import partial
  4. from itertools import starmap
  5. from .six import items, map, next
  6. def _xhaust(mapfunc, call, iterable, exception=StopIteration, n=next):
  7. '''Call function `call` on an `iterable` until it's exhausted.'''
  8. iterable = mapfunc(call, iterable)
  9. try:
  10. while 1:
  11. n(iterable)
  12. except exception:
  13. pass
  14. def breakcount(call, length):
  15. '''Call function `call` until it reaches its original `length`.'''
  16. while length:
  17. yield call()
  18. length -= 1
  19. def count(iterable, _n=next, S=StopIteration):
  20. '''Lazily calculate number of items in `iterable`.'''
  21. counter = enumerate(iterable, 1)
  22. idx = ()
  23. while 1:
  24. try:
  25. idx = _n(counter)
  26. except S:
  27. try:
  28. return _n(iter(idx))
  29. except S:
  30. return 0
  31. def deferfunc(call):
  32. '''Defer running `call`.'''
  33. yield call()
  34. def deferiter(iterator):
  35. '''Defer running `iterator`.'''
  36. yield next(iterator)
  37. def exhaust(iterable, exception=StopIteration, _n=next):
  38. '''Call `next` on an `iterable` until it's exhausted.'''
  39. try:
  40. while 1:
  41. _n(iterable)
  42. except exception:
  43. pass
  44. def exhaustmap(call, mapping, filter=None, exception=StopIteration, _n=next):
  45. '''Call `call` with optional `filter` on a `mapping` until exhausted.'''
  46. iterable = starmap(
  47. call,
  48. items(mapping) if filter is None else filter(filter, items(mapping)),
  49. )
  50. try:
  51. while 1:
  52. _n(iterable)
  53. except exception:
  54. pass
  55. def gauntlet(throws, this):
  56. '''Run sequence of callables in `thrown` on `this` object.'''
  57. for thrown in throws:
  58. this = thrown(this)
  59. return this
  60. def iterexcept(call, exception, start=None):
  61. '''
  62. Call function `call` until `exception` is raised.
  63. from Raymond Hettinger Python Cookbook recipe # 577155
  64. '''
  65. try:
  66. if start is not None:
  67. yield start()
  68. while 1:
  69. yield call()
  70. except exception:
  71. pass
  72. _part = lambda m, p, c, d, *a, **k: m(p(c, *a, **k), d)
  73. partmap = partial(_part, map, partial,)
  74. partstar = partial(_part, starmap, partial)
  75. exhaustcall = partial(_xhaust, map)
  76. exhauststar = partial(_xhaust, starmap)
  77. xpartmap = partial(_part, exhaustcall, partial)
  78. xpartstar = partial(_part, exhauststar, partial)
  79. xpartitems = partial(
  80. lambda x, p, c, i, f=None, *a, **k: x(p(c, *a, **k), i, f),
  81. exhaustmap,
  82. partial,
  83. )