[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