Skip to content

Commit e1878bb

Browse files
committed
-
1 parent b5f5094 commit e1878bb

File tree

6 files changed

+33
-35
lines changed

6 files changed

+33
-35
lines changed

source_py2/python_toolbox/collection_tools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from python_toolbox import nifty_collections
1111

1212

13-
@nifty_collections.LazyTuple.factory
13+
@nifty_collections.LazyTuple.factory()
1414
def get_all_contained_counters(counter, use_lazy_tuple=True):
1515
'''
1616
Get all counters that are subsets of `counter`.

source_py2/python_toolbox/nifty_collections/lazy_tuple.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ def _with_lock(method, *args, **kwargs):
4949
return method(*args, **kwargs)
5050

5151

52+
@collections.Sequence.register
53+
@comparison_tools.total_ordering
5254
class LazyTuple(collections.Sequence, object):
5355
'''
5456
A lazy tuple which requests as few values as possible from its iterator.
@@ -75,8 +77,8 @@ def my_generator():
7577
(e.g. asking for the seventh-to-last element.)
7678
'''
7779

78-
def __init__(self, iterable):
79-
was_given_a_sequence = sequence_tools.is_sequence(iterable) and \
80+
def __init__(self, iterable, definitely_infinite=False):
81+
was_given_a_sequence = isinstance(iterable, collections.Sequence) and \
8082
not isinstance(iterable, LazyTuple)
8183

8284
self.exhausted = True if was_given_a_sequence else False
@@ -88,18 +90,20 @@ def __init__(self, iterable):
8890
self._iterator = None if was_given_a_sequence else iter(iterable)
8991
'''The internal iterator from which we get data.'''
9092

93+
self.definitely_infinite = definitely_infinite
94+
9195
self.lock = threading.Lock()
9296
'''Lock used while exhausting to make `LazyTuple` thread-safe.'''
9397

9498

9599
@classmethod
96-
def factory(cls, callable):
100+
def factory(cls, definitely_infinite=False):
97101
'''
98102
Decorator to make generators return a `LazyTuple`.
99103
100104
Example:
101105
102-
@LazyTuple.factory
106+
@LazyTuple.factory()
103107
def my_generator():
104108
yield 'hello'; yield 'world'; yield 'have'; yield 'fun'
105109
@@ -108,8 +112,9 @@ def my_generator():
108112
'''
109113

110114
def inner(function, *args, **kwargs):
111-
return cls(callable(*args, **kwargs))
112-
return decorator_tools.decorator(inner, callable)
115+
return cls(function(*args, **kwargs),
116+
definitely_infinite=definitely_infinite)
117+
return decorator_tools.decorator(inner)
113118

114119

115120
@property
@@ -169,6 +174,9 @@ def __getitem__(self, i):
169174

170175

171176
def __len__(self):
177+
if self.definitely_infinite:
178+
return 0 # Unfortunately infinity isn't supported.
179+
else:
172180
self.exhaust()
173181
return len(self.collected_data)
174182

@@ -270,12 +278,9 @@ def __hash__(self):
270278
271279
Note: Hashing the `LazyTuple` will completely exhaust it.
272280
'''
281+
if self.definitely_infinite:
282+
raise TypeError("An infinite `LazyTuple` isn't hashable.")
283+
else:
273284
self.exhaust()
274285
return hash(tuple(self))
275286

276-
277-
comparison_tools.total_ordering(LazyTuple)
278-
279-
if hasattr(collections, 'Sequence'):
280-
collections.Sequence.register(LazyTuple)
281-

source_py2/python_toolbox/sequence_tools.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,10 @@ def partitions(sequence, partition_size=None, n_partitions=None,
151151
return blocks
152152

153153

154-
def is_sequence(thing):
155-
'''Is `thing` a sequence, like `list` or `tuple`?'''
156-
return collections.Sequence.__instancecheck__(thing)
157-
158-
159-
def is_mutable_sequence(thing):
160-
'''Is `thing` a mutable sequence, like `list`?'''
161-
return collections.MutableSequence.__instancecheck__(thing)
162-
163-
164154
def is_immutable_sequence(thing):
165155
'''Is `thing` an immutable sequence, like `tuple`?'''
166-
return collections.Sequence.__instancecheck__(thing) and not \
167-
collections.MutableSequence.__instancecheck__(thing)
156+
return isinstance(thing, collections.Sequence) and not \
157+
isinstance(thing, collections.MutableSequence)
168158

169159

170160
def parse_slice(s):
@@ -252,7 +242,7 @@ def to_tuple(single_or_sequence, item_type=None, item_test=None):
252242
actual_item_test = None
253243

254244
if actual_item_test is None:
255-
if is_sequence(single_or_sequence):
245+
if isinstance(single_or_sequence, collections.Sequence):
256246
return tuple(single_or_sequence)
257247
else:
258248
return (single_or_sequence,)

source_py2/test_python_toolbox/test_cute_iter_tools/test_iterate_overlapping_subsequences.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
'''Testing module for `cute_iter_tools.iterate_overlapping_subsequences`.'''
55

6+
import collections
7+
68
from python_toolbox import gc_tools
79
from python_toolbox import nifty_collections
810
from python_toolbox import cute_testing
@@ -14,8 +16,9 @@
1416
def test_length_2():
1517

1618
# `iterate_overlapping_subsequences` returns an iterator, not a sequence:
17-
assert not sequence_tools.is_sequence(
18-
iterate_overlapping_subsequences(range(4))
19+
assert not isinstance(
20+
iterate_overlapping_subsequences(list(range(4))),
21+
collections.Sequence
1922
)
2023

2124
assert tuple(iterate_overlapping_subsequences(range(4))) == \

source_py2/test_python_toolbox/test_nifty_collections/test_lazy_tuple/test_lazy_tuple.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,16 @@ def test_infinite():
115115

116116
def test_factory_decorator():
117117
'''Test the `LazyTuple.factory` decorator.'''
118-
@LazyTuple.factory
118+
@LazyTuple.factory(definitely_infinite=True)
119119
def count(*args, **kwargs):
120120
return itertools.count(*args, **kwargs)
121121

122122
my_count = count()
123123
assert isinstance(my_count, LazyTuple)
124124
assert repr(my_count) == '<LazyTuple: (...)>'
125-
assert my_count[:10] == tuple(xrange(10))
125+
assert my_count.definitely_infinite
126+
assert my_count[:10] == tuple(range(10))
127+
assert len(my_count) == 0
126128

127129

128130
def test_finite_iterator():

source_py3/python_toolbox/nifty_collections/lazy_tuple.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ def _with_lock(method, *args, **kwargs):
4848
with self.lock:
4949
return method(*args, **kwargs)
5050

51-
51+
52+
@collections.Sequence.register
53+
@comparison_tools.total_ordering
5254
class LazyTuple(collections.Sequence):
5355
'''
5456
A lazy tuple which requests as few values as possible from its iterator.
@@ -281,8 +283,4 @@ def __hash__(self):
281283
else:
282284
self.exhaust()
283285
return hash(tuple(self))
284-
285-
286-
comparison_tools.total_ordering(LazyTuple)
287-
collections.Sequence.register(LazyTuple)
288286

0 commit comments

Comments
 (0)