[Python-modules-commits] [jaraco.itertools] 01/04: import jaraco.itertools_2.0.1.orig.tar.gz
Ethan Ward
ethanward-guest at moszumanska.debian.org
Tue Jul 25 22:52:21 UTC 2017
This is an automated email from the git hooks/post-receive script.
ethanward-guest pushed a commit to branch master
in repository jaraco.itertools.
commit ce01ef1a3e3375e4dbbfbf016cab7c01a199a242
Author: Ethan Ward <ethan.ward at mycroft.ai>
Date: Tue Jul 25 17:28:30 2017 -0500
import jaraco.itertools_2.0.1.orig.tar.gz
---
.travis.yml | 24 +
CHANGES.rst | 65 ++
PKG-INFO | 32 +
README.rst | 17 +
conftest.py | 19 +
docs/conf.py | 58 ++
docs/history.rst | 8 +
docs/index.rst | 22 +
docs/requirements.txt | 1 +
jaraco.itertools.egg-info/PKG-INFO | 32 +
jaraco.itertools.egg-info/SOURCES.txt | 21 +
jaraco.itertools.egg-info/dependency_links.txt | 1 +
jaraco.itertools.egg-info/namespace_packages.txt | 1 +
jaraco.itertools.egg-info/requires.txt | 3 +
jaraco.itertools.egg-info/top_level.txt | 1 +
jaraco/__init__.py | 1 +
jaraco/itertools.py | 921 +++++++++++++++++++++++
pytest.ini | 4 +
setup.cfg | 12 +
setup.py | 47 ++
tests/requirements.txt | 2 +
tox.ini | 6 +
22 files changed, 1298 insertions(+)
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..bca0bff
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,24 @@
+sudo: false
+language: python
+python:
+- 2.7
+- 3.6
+install:
+- pip install tox "setuptools>=28.2"
+script:
+- tox
+branches:
+ except:
+ - skeleton
+deploy:
+ provider: pypi
+ server: https://upload.pypi.org/legacy/
+ on:
+ tags: true
+ all_branches: true
+ python: 3.6
+ user: jaraco
+ distributions: dists
+ skip_upload_docs: true
+ password:
+ secure: shK8GEX9tEBfC0h/NoQfz/36AQOXL4U9a4Bl8NxiOJRNcnJpyFjHHPFKc8lzZ9McVltRqAMbdPWqkqOQquuTjM+dTaD5S+DxDnJU0lJbatrHE4gS8jMoJKLotYX/NRup72vzYQyXq1QjMNSf1lrVf8ASqaaUlMwubKUQd0D1OmY57/3CGbqhSnrmhZ5aSwZ7sy289Gk9Il06VXpqhJ6rBiCVtYJdPccu6oYBidE7KH0VhEC132wA8G8onT2jc22CSGpwIrtR8IQxL/B9d4ycAUulpMCXM0a77I5pWpJO8minPBKQD6TWwt3hsn6e1DoKv6gpSOZg4BYD4vxmNVby2vAxwNu0AaQxCdT5i2q6ow2EdCX2G7FN587pbCNKMqZi7CNCxqqE0gO0MacXl6LoP8Om08FIzxytDMDj1Qk+dHr8GAy9dS+iiAARpY47q/uNDQ6MuNvMCrzyjfBmLpmTm6xnkoSFEwTY [...]
diff --git a/CHANGES.rst b/CHANGES.rst
new file mode 100644
index 0000000..6c008e9
--- /dev/null
+++ b/CHANGES.rst
@@ -0,0 +1,65 @@
+2.0.1
+=====
+
+* Refresh package.
+
+2.0
+===
+
+* In ``always_iterable``, mappings are now considered
+ singletons. It seems that the way ``always_iterable``
+ is generally used, one wouldn't expect to only iterate
+ on a mapping, but there are cases where a dictionary
+ should behave like a singleton object.
+
+1.8
+===
+
+* Deprecated ``infiniteCall`` and replaced it with
+ ``infinite_call`` which only takes a single argument
+ (the function to call).
+
+1.7.1
+=====
+
+* Fix failing tests on Python 2.
+
+1.7
+===
+
+* Moved hosting to github.
+
+1.6
+===
+
+* Releases now include wheels.
+
+1.5
+===
+
+* Add ``takewhile_peek`` function.
+
+1.4
+===
+
+* Add ``list_or_single`` function.
+
+1.3
+===
+
+* Add ``apply`` to apply a function to an iterable, but yield the
+ original items.
+
+1.1
+===
+
+* Update ``Count`` object to support comparison for equality and accept
+ None to mean explicitly Infinity. See the docs for details.
+* Fixed Python 3 issues on ``Counter`` object. Added docstrings.
+* Added ``Counter.count`` attribute.
+* ``Counter.GetCount`` is now deprecated. Use ``.count`` instead.
+
+1.0
+===
+
+Initial release based on jaraco.util 10.7.
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..ebbe71b
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,32 @@
+Metadata-Version: 1.1
+Name: jaraco.itertools
+Version: 2.0.1
+Summary: jaraco.itertools
+Home-page: https://github.com/jaraco/jaraco.itertools
+Author: Jason R. Coombs
+Author-email: jaraco at jaraco.com
+License: UNKNOWN
+Description: .. image:: https://img.shields.io/pypi/v/jaraco.itertools.svg
+ :target: https://pypi.org/project/jaraco.itertools
+
+ .. image:: https://img.shields.io/pypi/pyversions/jaraco.itertools.svg
+
+ .. image:: https://img.shields.io/pypi/dm/jaraco.itertools.svg
+
+ .. image:: https://img.shields.io/travis/jaraco/jaraco.itertools/master.svg
+ :target: http://travis-ci.org/jaraco/jaraco.itertools
+
+
+ License
+ =======
+
+ License is indicated in the project metadata (typically one or more
+ of the Trove classifiers). For more details, see `this explanation
+ <https://github.com/jaraco/skeleton/issues/1>`_.
+
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..988c577
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,17 @@
+.. image:: https://img.shields.io/pypi/v/jaraco.itertools.svg
+ :target: https://pypi.org/project/jaraco.itertools
+
+.. image:: https://img.shields.io/pypi/pyversions/jaraco.itertools.svg
+
+.. image:: https://img.shields.io/pypi/dm/jaraco.itertools.svg
+
+.. image:: https://img.shields.io/travis/jaraco/jaraco.itertools/master.svg
+ :target: http://travis-ci.org/jaraco/jaraco.itertools
+
+
+License
+=======
+
+License is indicated in the project metadata (typically one or more
+of the Trove classifiers). For more details, see `this explanation
+<https://github.com/jaraco/skeleton/issues/1>`_.
diff --git a/conftest.py b/conftest.py
new file mode 100644
index 0000000..22466b7
--- /dev/null
+++ b/conftest.py
@@ -0,0 +1,19 @@
+import six
+
+
+def pytest_collection_modifyitems(session, config, items):
+ remove_PY2_broken_tests(items)
+
+
+def remove_PY2_broken_tests(items):
+ if six.PY3:
+ return
+ broken_test_names = [
+ 'jaraco.itertools.always_iterable',
+ 'jaraco.itertools.flatten',
+ ]
+ items[:] = (
+ item
+ for item in items
+ if item.name not in broken_test_names
+ )
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..c29cc17
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import subprocess
+import datetime
+
+if 'check_output' not in dir(subprocess):
+ import subprocess32 as subprocess
+
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'rst.linker',
+]
+
+# General information about the project.
+
+root = os.path.join(os.path.dirname(__file__), '..')
+setup_script = os.path.join(root, 'setup.py')
+fields = ['--name', '--version', '--url', '--author']
+dist_info_cmd = [sys.executable, setup_script] + fields
+output_bytes = subprocess.check_output(dist_info_cmd, cwd=root)
+project, version, url, author = output_bytes.decode('utf-8').strip().split('\n')
+
+origin_date = datetime.date(2005,1,1)
+today = datetime.date.today()
+
+copyright = '{origin_date.year}-{today.year} {author}'.format(**locals())
+
+# The full version, including alpha/beta/rc tags.
+release = version
+
+master_doc = 'index'
+
+link_files = {
+ '../CHANGES.rst': dict(
+ using=dict(
+ GH='https://github.com',
+ project=project,
+ url=url,
+ ),
+ replace=[
+ dict(
+ pattern=r"(Issue )?#(?P<issue>\d+)",
+ url='{url}/issues/{issue}',
+ ),
+ dict(
+ pattern=r"^(?m)((?P<scm_version>v?\d+(\.\d+){1,2}))\n[-=]+\n",
+ with_scm="{text}\n{rev[timestamp]:%d %b %Y}\n",
+ ),
+ dict(
+ pattern=r"PEP[- ](?P<pep_number>\d+)",
+ url='https://www.python.org/dev/peps/pep-{pep_number:0>4}/',
+ ),
+ ],
+ ),
+}
diff --git a/docs/history.rst b/docs/history.rst
new file mode 100644
index 0000000..8e21750
--- /dev/null
+++ b/docs/history.rst
@@ -0,0 +1,8 @@
+:tocdepth: 2
+
+.. _changes:
+
+History
+*******
+
+.. include:: ../CHANGES (links).rst
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..e7a3993
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,22 @@
+Welcome to jaraco.itertools documentation!
+==========================================
+
+.. toctree::
+ :maxdepth: 1
+
+ history
+
+
+.. automodule:: jaraco.itertools
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..442df9f
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1 @@
+rst.linker
diff --git a/jaraco.itertools.egg-info/PKG-INFO b/jaraco.itertools.egg-info/PKG-INFO
new file mode 100644
index 0000000..ebbe71b
--- /dev/null
+++ b/jaraco.itertools.egg-info/PKG-INFO
@@ -0,0 +1,32 @@
+Metadata-Version: 1.1
+Name: jaraco.itertools
+Version: 2.0.1
+Summary: jaraco.itertools
+Home-page: https://github.com/jaraco/jaraco.itertools
+Author: Jason R. Coombs
+Author-email: jaraco at jaraco.com
+License: UNKNOWN
+Description: .. image:: https://img.shields.io/pypi/v/jaraco.itertools.svg
+ :target: https://pypi.org/project/jaraco.itertools
+
+ .. image:: https://img.shields.io/pypi/pyversions/jaraco.itertools.svg
+
+ .. image:: https://img.shields.io/pypi/dm/jaraco.itertools.svg
+
+ .. image:: https://img.shields.io/travis/jaraco/jaraco.itertools/master.svg
+ :target: http://travis-ci.org/jaraco/jaraco.itertools
+
+
+ License
+ =======
+
+ License is indicated in the project metadata (typically one or more
+ of the Trove classifiers). For more details, see `this explanation
+ <https://github.com/jaraco/skeleton/issues/1>`_.
+
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
diff --git a/jaraco.itertools.egg-info/SOURCES.txt b/jaraco.itertools.egg-info/SOURCES.txt
new file mode 100644
index 0000000..f891fd4
--- /dev/null
+++ b/jaraco.itertools.egg-info/SOURCES.txt
@@ -0,0 +1,21 @@
+.travis.yml
+CHANGES.rst
+README.rst
+conftest.py
+pytest.ini
+setup.cfg
+setup.py
+tox.ini
+docs/conf.py
+docs/history.rst
+docs/index.rst
+docs/requirements.txt
+jaraco/__init__.py
+jaraco/itertools.py
+jaraco.itertools.egg-info/PKG-INFO
+jaraco.itertools.egg-info/SOURCES.txt
+jaraco.itertools.egg-info/dependency_links.txt
+jaraco.itertools.egg-info/namespace_packages.txt
+jaraco.itertools.egg-info/requires.txt
+jaraco.itertools.egg-info/top_level.txt
+tests/requirements.txt
\ No newline at end of file
diff --git a/jaraco.itertools.egg-info/dependency_links.txt b/jaraco.itertools.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/jaraco.itertools.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/jaraco.itertools.egg-info/namespace_packages.txt b/jaraco.itertools.egg-info/namespace_packages.txt
new file mode 100644
index 0000000..f6205a5
--- /dev/null
+++ b/jaraco.itertools.egg-info/namespace_packages.txt
@@ -0,0 +1 @@
+jaraco
diff --git a/jaraco.itertools.egg-info/requires.txt b/jaraco.itertools.egg-info/requires.txt
new file mode 100644
index 0000000..2cf1e3c
--- /dev/null
+++ b/jaraco.itertools.egg-info/requires.txt
@@ -0,0 +1,3 @@
+six
+more_itertools
+inflect
diff --git a/jaraco.itertools.egg-info/top_level.txt b/jaraco.itertools.egg-info/top_level.txt
new file mode 100644
index 0000000..f6205a5
--- /dev/null
+++ b/jaraco.itertools.egg-info/top_level.txt
@@ -0,0 +1 @@
+jaraco
diff --git a/jaraco/__init__.py b/jaraco/__init__.py
new file mode 100644
index 0000000..5284146
--- /dev/null
+++ b/jaraco/__init__.py
@@ -0,0 +1 @@
+__import__("pkg_resources").declare_namespace(__name__)
diff --git a/jaraco/itertools.py b/jaraco/itertools.py
new file mode 100644
index 0000000..7eedca6
--- /dev/null
+++ b/jaraco/itertools.py
@@ -0,0 +1,921 @@
+# -*- coding: UTF-8 -*-
+
+"""
+jaraco.itertools
+Tools for working with iterables. Complements itertools and more_itertools.
+"""
+
+from __future__ import absolute_import, unicode_literals, print_function
+
+import operator
+import itertools
+import collections
+import math
+import warnings
+import functools
+
+import six
+from six.moves import queue, xrange as range
+
+import inflect
+from more_itertools import more
+from more_itertools import recipes
+
+
+def make_rows(num_columns, seq):
+ """
+ Make a sequence into rows of num_columns columns.
+
+ >>> tuple(make_rows(2, [1, 2, 3, 4, 5]))
+ ((1, 4), (2, 5), (3, None))
+ >>> tuple(make_rows(3, [1, 2, 3, 4, 5]))
+ ((1, 3, 5), (2, 4, None))
+ """
+ # calculate the minimum number of rows necessary to fit the list in
+ # num_columns Columns
+ num_rows, partial = divmod(len(seq), num_columns)
+ if partial:
+ num_rows += 1
+ # break the seq into num_columns of length num_rows
+ result = recipes.grouper(num_rows, seq)
+ # result is now a list of columns... transpose it to return a list
+ # of rows
+ return zip(*result)
+
+def bisect(seq, func=bool):
+ """
+ Split a sequence into two sequences: the first is elements that
+ return False for func(element) and the second for True for
+ func(element).
+ By default, func is ``bool``, so uses the truth value of the object.
+
+ >>> is_odd = lambda n: n%2
+ >>> even, odd = bisect(range(5), is_odd)
+ >>> list(odd)
+ [1, 3]
+ >>> list(even)
+ [0, 2, 4]
+
+ >>> other, zeros = bisect(reversed(range(5)))
+ >>> list(zeros)
+ [0]
+ >>> list(other)
+ [4, 3, 2, 1]
+
+ """
+ queues = GroupbySaved(seq, func)
+ return queues.get_first_n_queues(2)
+
+class GroupbySaved(object):
+ """
+ Split a sequence into n sequences where n is determined by the
+ number of distinct values returned by a key function applied to each
+ element in the sequence.
+
+ >>> truthsplit = GroupbySaved(['Test', '', 30, None], bool)
+ >>> truthsplit['x']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'x'
+ >>> true_items = truthsplit[True]
+ >>> false_items = truthsplit[False]
+ >>> tuple(iter(false_items))
+ ('', None)
+ >>> tuple(iter(true_items))
+ ('Test', 30)
+
+ >>> every_third_split = GroupbySaved(range(99), lambda n: n%3)
+ >>> zeros = every_third_split[0]
+ >>> ones = every_third_split[1]
+ >>> twos = every_third_split[2]
+ >>> next(zeros)
+ 0
+ >>> next(zeros)
+ 3
+ >>> next(ones)
+ 1
+ >>> next(twos)
+ 2
+ >>> next(ones)
+ 4
+ """
+ def __init__(self, sequence, func = lambda x: x):
+ self.sequence = iter(sequence)
+ self.func = func
+ self.queues = collections.OrderedDict()
+
+ def __getitem__(self, key):
+ try:
+ return self.queues[key]
+ except KeyError:
+ return self.__find_queue__(key)
+
+ def __fetch__(self):
+ "get the next item from the sequence and queue it up"
+ item = next(self.sequence)
+ key = self.func(item)
+ queue = self.queues.setdefault(key, FetchingQueue(self.__fetch__))
+ queue.enqueue(item)
+
+ def __find_queue__(self, key):
+ "search for the queue indexed by key"
+ try:
+ while not key in self.queues:
+ self.__fetch__()
+ return self.queues[key]
+ except StopIteration:
+ raise KeyError(key)
+
+ def get_first_n_queues(self, n):
+ """
+ Run through the sequence until n queues are created and return
+ them. If fewer are created, return those plus empty iterables to
+ compensate.
+ """
+ try:
+ while len(self.queues) < n:
+ self.__fetch__()
+ except StopIteration:
+ pass
+ values = list(self.queues.values())
+ missing = n - len(values)
+ values.extend(iter([]) for n in range(missing))
+ return values
+
+class FetchingQueue(queue.Queue):
+ """
+ A FIFO Queue that is supplied with a function to inject more into
+ the queue if it is empty.
+
+ >>> values = iter(range(10))
+ >>> get_value = lambda: globals()['q'].enqueue(next(values))
+ >>> q = FetchingQueue(get_value)
+ >>> [x for x in q] == list(range(10))
+ True
+
+ Note that tuple(q) or list(q) would not have worked above because
+ tuple(q) just copies the elements in the list (of which there are
+ none).
+ """
+ def __init__(self, fetcher):
+ if six.PY3:
+ super(FetchingQueue, self).__init__()
+ else:
+ queue.Queue.__init__(self)
+ self._fetcher = fetcher
+
+ def __next__(self):
+ while self.empty():
+ self._fetcher()
+ return self.get()
+ next = __next__
+
+ def __iter__(self):
+ while True:
+ yield next(self)
+
+ def enqueue(self, item):
+ self.put_nowait(item)
+
+class Count(object):
+ """
+ A stop object that will count how many times it's been called and return
+ False on the N+1st call. Useful for use with takewhile.
+
+ >>> tuple(itertools.takewhile(Count(5), range(20)))
+ (0, 1, 2, 3, 4)
+
+ >>> print('catch', Count(5))
+ catch at most 5
+
+ It's possible to construct a Count with no limit or infinite limit.
+
+ >>> unl_c = Count(None)
+ >>> inf_c = Count(float('Inf'))
+
+ Unlimited or limited by infinity are equivalent.
+
+ >>> unl_c == inf_c
+ True
+
+ An unlimited counter is useful for wrapping an iterable to get the
+ count after it's consumed.
+
+ >>> tuple(itertools.takewhile(unl_c, range(20)))[-3:]
+ (17, 18, 19)
+ >>> unl_c.count
+ 20
+
+ If all you need is the count of items, consider :class:`Counter` instead.
+ """
+ def __init__(self, limit):
+ self.count = 0
+ self.limit = limit if limit is not None else float('Inf')
+
+ def __call__(self, arg):
+ if self.count > self.limit:
+ raise ValueError("Should not call count stop more anymore.")
+ self.count += 1
+ return self.count <= self.limit
+
+ def __str__(self):
+ if self.limit:
+ return 'at most %d' % self.limit
+ else:
+ return 'all'
+
+ def __eq__(self, other):
+ return vars(self) == vars(other)
+
+
+class islice(object):
+ """May be applied to an iterable to limit the number of items returned.
+ Works similarly to count, except is called only once on an iterable.
+ Functionality is identical to islice, except for __str__ and reusability.
+
+ >>> tuple(islice(5).apply(range(20)))
+ (0, 1, 2, 3, 4)
+
+ >>> tuple(islice(None).apply(range(20)))
+ (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
+
+ >>> print(islice(3, 10))
+ items 3 to 9
+
+ >>> print(islice(3, 10, 2))
+ every 2nd item from 3 to 9
+ """
+ def __init__(self, *sliceArgs):
+ self.sliceArgs = sliceArgs
+
+ def apply(self, i):
+ return itertools.islice(i, *self.sliceArgs)
+
+ def __str__(self):
+ if self.sliceArgs == (None,):
+ result = 'all'
+ else:
+ result = self._formatArgs()
+ return result
+
+ def _formatArgs(self):
+ slice_range = lambda a_b: '%d to %d' % (a_b[0], a_b[1] - 1)
+ if len(self.sliceArgs) == 1:
+ result = 'at most %d' % self.sliceArgs
+ if len(self.sliceArgs) == 2:
+ result = 'items %s' % slice_range(self.sliceArgs)
+ if len(self.sliceArgs) == 3:
+ ord = inflect.engine().ordinal(self.sliceArgs[2])
+ range = slice_range(self.sliceArgs[0:2])
+ result = 'every %(ord)s item from %(range)s' % locals()
+ return result
+
+class LessThanNBlanks(object):
+ """
+ An object that when called will return True until n false elements
+ are encountered.
+
+ Can be used with filter or itertools.ifilter, for example:
+
+ >>> import itertools
+ >>> sampleData = ['string 1', 'string 2', '', 'string 3', '', 'string 4', '', '', 'string 5']
+ >>> first = itertools.takewhile(LessThanNBlanks(2), sampleData)
+ >>> tuple(first)
+ ('string 1', 'string 2', '', 'string 3')
+ >>> first = itertools.takewhile(LessThanNBlanks(3), sampleData)
+ >>> tuple(first)
+ ('string 1', 'string 2', '', 'string 3', '', 'string 4')
+ """
+ def __init__(self, nBlanks):
+ self.limit = nBlanks
+ self.count = 0
+
+ def __call__(self, arg):
+ self.count += not arg
+ if self.count > self.limit:
+ raise ValueError("Should not call this object anymore.")
+ return self.count < self.limit
+
+class LessThanNConsecutiveBlanks(object):
+ """
+ An object that when called will return True until n consecutive
+ false elements are encountered.
+
+ Can be used with filter or itertools.ifilter, for example:
+
+ >>> import itertools
+ >>> sampleData = ['string 1', 'string 2', '', 'string 3', '', 'string 4', '', '', 'string 5']
+ >>> first = itertools.takewhile(LessThanNConsecutiveBlanks(2), sampleData)
+ >>> tuple(first)
+ ('string 1', 'string 2', '', 'string 3', '', 'string 4', '')
+ """
+
+ def __init__(self, nBlanks):
+ self.limit = nBlanks
+ self.count = 0
+ self.last = False
+
+ def __call__(self, arg):
+ self.count += not arg
+ if arg:
+ self.count = 0
+ self.last = operator.truth(arg)
+ if self.count > self.limit:
+ raise ValueError("Should not call this object anymore.")
+ return self.count < self.limit
+
+class splitter(object):
+ """
+ object that will split a string with the given arguments for each call.
+
+ >>> s = splitter(',')
+ >>> list(s('hello, world, this is your, master calling'))
+ ['hello', ' world', ' this is your', ' master calling']
+ """
+ def __init__(self, sep = None):
+ self.sep = sep
+
+ def __call__(self, s):
+ lastIndex = 0
+ while True:
+ nextIndex = s.find(self.sep, lastIndex)
+ if nextIndex != -1:
+ yield s[lastIndex:nextIndex]
+ lastIndex = nextIndex + 1
+ else:
+ yield s[lastIndex:]
+ break
+
+def grouper_nofill_str(n, iterable):
+ """
+ Take a sequence and break it up into chunks of the specified size.
+ The last chunk may be smaller than size.
+
+ This works very similar to grouper_nofill, except
+ it works with strings as well.
+
+ >>> tuple(grouper_nofill_str(3, 'foobarbaz'))
+ ('foo', 'bar', 'baz')
+
+ You can still use it on non-strings too if you like.
+
+ >>> tuple(grouper_nofill_str(42, []))
+ ()
+
+ >>> tuple(grouper_nofill_str(3, list(range(10))))
+ ([0, 1, 2], [3, 4, 5], [6, 7, 8], [9])
+ """
+ res = more.chunked(iterable, n)
+ if isinstance(iterable, six.string_types):
+ res = (''.join(item) for item in res)
+ return res
+
+
+def infinite_call(f):
+ """
+ Perpetually yield the result of calling function f.
+
+ >>> counter = itertools.count()
+ >>> get_next = functools.partial(next, counter)
+ >>> numbers = infinite_call(get_next)
+ >>> next(numbers)
+ 0
+ >>> next(numbers)
+ 1
+ """
+ return (f() for _ in itertools.repeat(None))
+
+
+def infiniteCall(f, *args):
+ warnings.warn("Use infinite_call")
+ return infinite_call(functools.partial(f, *args))
+
+
+class Counter(object):
+ """
+ Wrap an iterable in an object that stores the count of items
+ that pass through it.
+
+ >>> items = Counter(range(20))
+ >>> values = list(items)
+ >>> items.count
+ 20
+ """
+ def __init__(self, i):
+ self.count = 0
+ self._orig_iter = iter(i)
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ result = next(self._orig_iter)
+ self.count += 1
+ return result
+ next = __next__
+
+ def GetCount(self):
+ warnings.warn("Use count attribute directly", DeprecationWarning)
+ return self.count
+
+# todo, factor out caching capability
+class iterable_test(dict):
+ """
+ Test objects for iterability, caching the result by type
+
+ >>> test = iterable_test()
+ >>> test['foo']
+ False
+ >>> test[[]]
+ True
+ """
+ def __init__(self, ignore_classes=six.string_types+(six.binary_type,)):
+ """ignore_classes must include str, because if a string
+ is iterable, so is a single character, and the routine runs
+ into an infinite recursion"""
+ assert set(six.string_types) <= set(ignore_classes), (
+ 'str must be in ignore_classes')
+ self.ignore_classes = ignore_classes
+
+ def __getitem__(self, candidate):
+ return dict.get(self, type(candidate)) or self._test(candidate)
+
+ def _test(self, candidate):
+ try:
+ if isinstance(candidate, tuple(self.ignore_classes)):
+ raise TypeError
+ iter(candidate)
+ result = True
+ except TypeError:
+ result = False
+ self[type(candidate)] = result
+ return result
+
+def iflatten(subject, test=None):
+ if test is None:
+ test = iterable_test()
+ if not test[subject]:
+ yield subject
+ else:
+ for elem in subject:
+ for subelem in iflatten(elem, test):
+ yield subelem
+
+def flatten(subject, test=None):
+ """
+ Flatten an iterable with possible nested iterables.
+
+ Adapted from
+ http://mail.python.org/pipermail/python-list/2003-November/233971.html
+
+ >>> flatten(['a','b',['c','d',['e','f'],'g'],'h'])
+ ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
+
+ Note this will normally ignore string types as iterables.
+
+ >>> flatten(['ab', 'c'])
+ ['ab', 'c']
+
+ Same for bytes
+
+ >>> flatten([b'ab', b'c'])
+ [b'ab', b'c']
+ """
+ return list(iflatten(subject, test))
+
+def empty():
+ """
+ An empty iterator.
+ """
+ return iter(tuple())
+
+def is_empty(iterable):
+ """
+ Return whether the iterable is empty or not. Consumes at most one item
+ from the iterator to test.
+
+ >>> is_empty(iter(range(0)))
+ True
+ >>> is_empty(iter(range(1)))
+ False
+ """
+ try:
+ next(iter(iterable))
+ except StopIteration:
+ return True
+ return False
+
+class Reusable(object):
+ """
+ An iterator that may be reset and reused.
+
+ >>> ri = Reusable(range(3))
+ >>> tuple(ri)
+ (0, 1, 2)
+ >>> next(ri)
+ 0
+ >>> tuple(ri)
+ (1, 2)
+ >>> next(ri)
+ 0
+ >>> ri.reset()
+ >>> tuple(ri)
+ (0, 1, 2)
+ """
+
+ def __init__(self, iterable):
+ self.__saved = iterable
+ self.reset()
+
+ def __iter__(self): return self
+
+ def reset(self):
+ """
+ Resets the iterator to the start.
+
+ Any remaining values in the current iteration are discarded.
+ """
+ self.__iterator, self.__saved = itertools.tee(self.__saved)
+
+ def __next__(self):
+ try:
+ return next(self.__iterator)
+ except StopIteration:
+ # we're still going to raise the exception, but first
+ # reset the iterator so it's good for next time
+ self.reset()
+ raise
+ next = __next__
+
+def every_other(iterable):
+ """
+ Yield every other item from the iterable
+
+ >>> ' '.join(every_other('abcdefg'))
+ 'a c e g'
+ """
+ items = iter(iterable)
+ while True:
+ yield next(items)
+ next(items)
+
... 461 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/jaraco.itertools.git
More information about the Python-modules-commits
mailing list