python-pipeline-0.1.3+py3k/0000755000000000000000000000000011443737356014234 5ustar rootrootpython-pipeline-0.1.3+py3k/pipeline.py0000644000000000000000000002631611440444130016401 0ustar rootroot# encoding=UTF-8 # Copyright © 2007, 2008, 2009, 2010 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' >>> dev_null | tuple () >>> cat([1, 2, 3], [4, 5, 6]) | list [1, 2, 3, 4, 5, 6] >>> [1, 2, 3] | cat | list [1, 2, 3] >>> cat([1, 2, 3]) | (-x for x in STDIN) | list [-1, -2, -3] >>> cat(x + 1 for x in (1, 2, 3)) | (x * x for x in STDIN) | list [4, 9, 16] >>> ['foo', 'bar', 'baz'] | grep('a[rz]') | list ['bar', 'baz'] >>> range(-10, 10) | grep(lambda x: x % 7 == 1) | list [-6, 1, 8] >>> ['foo', 'bar', 'quux'] | cut[-2:] | list ['oo', 'ar', 'ux'] >>> sum(range(100) | select[i] | tuple != (list(range(100))[i],) for i in range(-3, 4)) 0 >>> sum(range(100) | select[i:j:k] | list != list(range(100))[i:j:k] for i in range(-3, 4) for j in range(-3, 4) for k in range(-3, 4) if k != 0) 0 >>> sort([4, 2, 1, 3]) | list [1, 2, 3, 4] >>> cat(['foo', 'bar', 'qaax']) | sort(key = lambda x: x[1:3]) | list ['qaax', 'bar', 'foo'] >>> print('-'.join(['foo', 'bar', 'quux'] | cat | sort)) bar-foo-quux >>> cat([1, 2, 3, 3, 2, 1]) | uniq | list [1, 2, 3, 2, 1] >>> cat([1, 2, 3, 3, 2, 1]) | zuniq | list [1, 2, 3] >>> cat([1, 2, 3, 42]) | wc 4 >>> seq(5) | list [1, 2, 3, 4, 5] >>> seq(3.5, 6) | list [3.5, 4.5, 5.5] >>> seq(-10, 40, 100) | list [-10, 30, 70] >>> echo('punt') | list ['punt'] >>> sum(yes(6) | head(7)) 42 >>> ('foo', 'bar', 'quux') | nl | list [(1, 'foo'), (2, 'bar'), (3, 'quux')] >>> ('foo', 'bar', 'quux') | nl1 | list [(1, 'foo'), (2, 'bar'), (3, 'quux')] >>> ('foo', 'bar', 'quux') | nl0 | list [(0, 'foo'), (1, 'bar'), (2, 'quux')] >>> wc(['foo', 'bar', 'quux']) 3 >>> cat(None for x in range(0, 7) for y in range(0, x) for z in range(y, x)) | wc 56 >>> tmp = [] >>> cat(tmp.__iadd__([x]) for x in range(5)) | slurp >>> tmp [0, 1, 2, 3, 4] >>> del tmp >>> range(7) | split(3) | list [(0, 1, 2), (3, 4, 5), (6,)] ''' import itertools import operator import re import sys import types class BrokenPipe(Exception): def __iter__(self): return self def __next__(self): raise self class _singleton(object): def __repr__(self): return '%s.%s' % (self.__module__, self.__class__.__name__) class STDIN(_singleton): __slots__ = () def __iter__(self): return self def __next__(self): frame = sys._getframe() try: while frame: try: iterator = frame.f_locals[STDIN] except KeyError: frame = frame.f_back continue return next(iterator) finally: frame = None iterator = None raise BrokenPipe() def __hash__(self): return hash(self.__class__) def __eq__(self, other): return self.__class__ == other.__class__ STDIN = STDIN() def _feed_iterator(iterator, stdin): if isinstance(iterator, types.GeneratorType): generator = iterator else: generator = (x for x in iterator) generator.gi_frame.f_locals[STDIN] = iter(stdin) return generator def _chain(iterables): return (len(iterables) == 1 and iter or itertools.chain)(*iterables) class Pipe(object): __slots__ = ['iterator'] broken_pipe = BrokenPipe() def __init__(self, *iterables): object.__init__(self) if iterables: self.iterator = _chain(iterables) else: self.iterator = None def __call__(self, iterable): if self.iterator is None: return self.__class__(iterable) else: self.iterator = _feed_iterator(self.iterator, iterable) return self def __iter__(self): if self.iterator is None: return self.broken_pipe else: return self.iterator @staticmethod def _or(left, right): try: right.__call__ except AttributeError: try: right_iter = iter(right) except TypeError: return NotImplemented else: return Pipe(_feed_iterator(right_iter, left)) else: applied = right(left) if isinstance(right, type): return applied else: try: iter(applied) except TypeError: return applied else: return Pipe(applied) def leak(self): return self.iterator def __or__(left, right): return Pipe._or(left, right) def __ror__(right, left): return Pipe._or(left, right) def __repr__(self): if self.iterator is None: iterator_repr = '' else: iterator_repr = repr(self.iterator) return '%s.%s(%s)' % (self.__module__, self.__class__.__name__, iterator_repr) class dev_null(_singleton, Pipe): __slots__ = () def __init__(self): Pipe.__init__(self, ()) dev_null = dev_null() class cat(Pipe): __slots__ = () def __call__(self, *iterables): iterable = _chain(iterables) if self.iterator is None: return self.__class__(iterable) else: return Pipe.__call__(self, iterable) cat = cat() class grep(Pipe): __slots__ = 'test', REPattern = type(re.compile('')) def __init__(self, test, *iterables): if isinstance(test, str): self.test = re.compile(test).search elif isinstance(test, grep.REPattern): self.test = test.search else: try: self.test = test.__call__ except AttributeError: raise TypeError() if iterables: Pipe.__init__(self, filter(self.test, _chain(iterables))) else: Pipe.__init__(self) def __call__(self, iterable): if self.iterator is None: return self.__class__(self.test, iterable) else: return Pipe.__call__(self, iterable) def __repr__(self): return '%s.%s(%s%s)' % (self.__module__, self.__class__.__name__, repr(self.test), self.iterator and ', ' or '') def _slice_repr(_slice): if not isinstance(_slice, slice): return repr(_slice) else: values = [] for name in ['start', 'stop', 'step']: value = getattr(_slice, name) if value is not None: value = repr(value) values += value, (start, stop, step) = values if step is None: return '%s:%s' % (start or '', stop or '') else: return '%s:%s:%s' % (start or '', stop or '', step) class _cut(Pipe): __slots__ = 'slice', def __init__(self, slice): Pipe.__init__(self) self.slice = slice def __call__(self, iterable): return Pipe(item[self.slice] for item in iterable) def __repr__(self): return '%s.%s[%s]' % (cut.__module__, cut.__class__.__name__, _slice_repr(self.slice)) class cut(_singleton): __slots__ = () def __getitem__(self, slice): return _cut(slice) cut = cut() class _select(Pipe): __slots__ = ['slice'] def __init__(self, slice_): Pipe.__init__(self) if isinstance(slice_, int): if slice_ == -1: slice_ = slice(-1, None) else: slice_ = slice(slice_, slice_ + 1) [][slice_] self.slice = slice_ def _select(self, iterable): def _step_select(step, iterable): def _iter(step, iterable): i = len = 0 for item in iterable: len += 1 if i == 0: yield item i += 1 if i == step: i = 0 yield len result = list(_iter(step, iterable)) return result.pop(), result slice = self.slice start, stop, step = (slice.start or 0, slice.stop, slice.step or 1) if step >= 0 and start >= 0: iterator = iter(iterable) if stop is None or stop >= 0: return itertools.islice(iterator, start, stop, step) iterator = itertools.islice(iterator, start, None) length, result = _step_select(step, iterator) del result[max(0, stop + length + step - 1) // step:] return result else: # FIXME: do it more efficiently if isinstance(iterable, (list, tuple, str)): return iterable[slice] else: return tuple(iterable)[slice] def __call__(self, iterable): return Pipe(self._select(iterable)) def __repr__(self): return '%s.%s[%s]' % (select.__module__, select.__class__.__name__, _slice_repr(self.slice)) class select(_singleton): __slots__ = () def __getitem__(self, slice): return _select(slice) select = select() def head(n): return select[:n] def tail(n): if n < 0: return select[n:] elif n >= 0: return select[max(0, n - 1):] else: raise TypeError() class sort(Pipe): __slots__ = ['key', 'reverse'] def __init__(self, *iterables, **kwargs): def _sort(iterables, key, reverse): sorted_ = sorted(_chain(iterables), key = key, reverse = reverse) for item in sorted_: yield item self.key = kwargs.get('key') self.reverse = kwargs.get('reverse', False) if iterables: Pipe.__init__(self, _sort(iterables, self.key, self.reverse)) else: Pipe.__init__(self) def __call__(self, iterable): if self.iterator is None: return self.__class__(iterable, key = self.key, reverse = self.reverse) else: return Pipe.__call__(self, iterable) class uniq(Pipe): __slots__ = () @classmethod def _uniq(self, iterable): return map( operator.itemgetter(0), itertools.groupby(iterable) ) def __init__(self, *iterables): if iterables: Pipe.__init__(self, self._uniq(_chain(iterables))) else: Pipe.__init__(self) class zuniq(uniq): __slots__ = () @classmethod def _uniq(self, iterable): set_ = set() for item in iterable: if item in set_: continue set_.add(item) yield item uniq = uniq() zuniq = zuniq() def echo(object): return Pipe((object,)) def yes(object): return Pipe(itertools.repeat(object)) class nl(Pipe): __slots__ = () start = 0 def __init__(self, *iterables): if iterables: iterator = enumerate(_chain((range(self.start),) + iterables)) for i in range(self.start): next(iterator) Pipe.__init__(self, iterator) else: Pipe.__init__(self) class nl1(nl): __slots__ = () start = 1 nl0 = nl() nl1 = nl1() nl = nl1 def wc(iterable): try: return len(iterable) except TypeError: pass i = 0 for item in iterable: i += 1 return i def slurp(iterable): for x in iterable: pass def seq(x, y = None, z = None): def _seq(first, step, last): while first <= last: yield first first += step if z is None: step = 1 if y is None: first, last = 1, x else: first, last = x, y else: first, step, last = x, y, z return Pipe(_seq(first, step, last)) class leak(object): __slots__ = () def __new__(self, object): try: leak = object.leak except AttributeError: return object else: return leak() class split(Pipe): __slots__ = 'n', def __init__(self, n): if n >= 1: self.n = n else: raise TypeError() def _split(self, iterable): iterator = iter(iterable) while 1: tup = tuple(itertools.islice(iterator, self.n)) if tup: yield tup else: return def __call__(self, iterable): return Pipe(self._split(iterable)) __author__ = 'Jakub Wilk ' __version__ = '0.1.3+py3k' # vim:ts=4 sw=4 noet python-pipeline-0.1.3+py3k/PKG-INFO0000644000000000000000000000117711443737356015337 0ustar rootrootMetadata-Version: 1.0 Name: python-pipeline Version: 0.1.3+py3k Summary: Iterator pipelines Home-page: http://python-pipeline.googlecode.com/ Author: Jakub Wilk Author-email: jwilk@jwilk.net License: MIT Description: *python-pipeline* lets you create pipelines of iterators. Platform: any Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules python-pipeline-0.1.3+py3k/setup.py0000644000000000000000000000150711443737313015742 0ustar rootroot''' *python-pipeline* lets you create pipelines of iterators. ''' classifiers = '''\ Development Status :: 3 - Alpha Intended Audience :: Developers License :: OSI Approved :: MIT License Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 3 Topic :: Software Development :: Libraries :: Python Modules'''.split('\n') from distutils.core import setup import os os.putenv('TAR_OPTIONS', '--owner root --group root --mode a+rX') setup( name = 'python-pipeline', version = '0.1.3+py3k', license = 'MIT', platforms = ['any'], description = 'Iterator pipelines', long_description = __doc__.strip(), classifiers = classifiers, url = 'http://python-pipeline.googlecode.com/', author = 'Jakub Wilk', author_email = 'jwilk@jwilk.net', py_modules = ['pipeline'] ) # vim:ts=4 sw=4 noet