put-back-iterator 0.1.0a0__py2.py3-none-any.whl → 0.1.0a1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: put-back-iterator
3
- Version: 0.1.0a0
3
+ Version: 0.1.0a1
4
4
  Summary: A drop-in replacement for `iter(iterable)` that allows **putting items back** after consuming them. Ideal for parsing, lexing, and other scenarios requiring lookahead or backtracking.
5
5
  Author-email: Jifeng Wu <jifengwu2k@gmail.com>
6
6
  License-Expression: MIT
@@ -12,6 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=2
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
+ Requires-Dist: typing; python_version < "3.5"
15
16
  Dynamic: license-file
16
17
 
17
18
  # `put-back-iterator`
@@ -35,6 +36,8 @@ This package solves it with:
35
36
  ## Quick Start
36
37
 
37
38
  ```python
39
+ # coding=utf-8
40
+ from __future__ import print_function
38
41
  from put_back_iterator import PutBackIterator
39
42
 
40
43
  # Wrap any iterable
@@ -57,7 +60,7 @@ print(list(it)) # [1, 2, 3]
57
60
 
58
61
  ### 1. **Parsing/Tokenizing**
59
62
 
60
- ```python
63
+ ```
61
64
  tokens = PutBackIterator(tokenize(source_code))
62
65
  while tokens.has_next():
63
66
  token = next(tokens)
@@ -70,7 +73,7 @@ while tokens.has_next():
70
73
 
71
74
  ### 2. **Backtracking Algorithms**
72
75
 
73
- ```python
76
+ ```
74
77
  def backtrack(it):
75
78
  item = next(it)
76
79
  if not is_valid(item):
@@ -80,7 +83,7 @@ def backtrack(it):
80
83
 
81
84
  ### 3. **Stream Processing**
82
85
 
83
- ```python
86
+ ```
84
87
  for chunk in PutBackIterator(stream):
85
88
  if needs_retry(chunk):
86
89
  chunk = modify(chunk)
@@ -0,0 +1,6 @@
1
+ put_back_iterator.py,sha256=YaWSHy7WdrMHkfKudP6sCyBN8KwwfxwzIIqrt2x3Pfo,4336
2
+ put_back_iterator-0.1.0a1.dist-info/licenses/LICENSE,sha256=FZ9XWedK_wQ4wfqVanrQVQpArRHDkxwxic2rgii1pZg,1066
3
+ put_back_iterator-0.1.0a1.dist-info/METADATA,sha256=oEMOGzBHbBlJJY5WTmoIHnWaEqso180qX1jKQZmXxYM,3089
4
+ put_back_iterator-0.1.0a1.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
5
+ put_back_iterator-0.1.0a1.dist-info/top_level.txt,sha256=8XJh5rF6eOPUkwrmXZutOmEHGnbXK6VqPPp6mrvkrs4,18
6
+ put_back_iterator-0.1.0a1.dist-info/RECORD,,
put_back_iterator.py CHANGED
@@ -1,25 +1,87 @@
1
- from __future__ import absolute_import, division, print_function
1
+ # coding=utf-8
2
+ # Copyright (c) 2025 Jifeng Wu
3
+ # Licensed under the MIT License. See LICENSE file in the project root for full license information.
2
4
  import sys
5
+ from typing import Iterable, Iterator, List, TypeVar
3
6
 
7
+ DEFAULT_PLACEHOLDER = object()
8
+ T = TypeVar('T')
4
9
 
5
- _DEFAULT_PLACEHOLDER = object()
6
10
 
7
- class PutBackIterator:
11
+ class PutBackIterator(Iterator[T]):
12
+ """A drop-in replacement for built-in iterators that supports putting items back.
13
+
14
+ This iterator wraps any iterable and provides additional functionality to
15
+ push consumed items back into the iterator for later consumption. Ideal for
16
+ parsing, lexing, and other scenarios requiring lookahead or backtracking.
17
+
18
+ Args:
19
+ iterable: Any iterable object (list, string, generator, etc.) to wrap.
20
+
21
+ Example:
22
+ >>> it = PutBackIterator([1, 2, 3])
23
+ >>> next(it)
24
+ 1
25
+ >>> it.put_back(1)
26
+ >>> list(it)
27
+ [1, 2, 3]
28
+
29
+ Attributes:
30
+ iterator (Iterator[T]): The underlying iterator
31
+ put_back_stack (List[T]): Stack for items that have been put back
32
+ """
33
+ __slots__ = (
34
+ 'iterator',
35
+ 'put_back_stack'
36
+ )
37
+
8
38
  def __init__(self, iterable):
9
- self._iterator = iter(iterable)
10
- self._put_back_stack = []
39
+ # type: (Iterable[T]) -> None
40
+ """Initialize the PutBackIterator with an iterable.
41
+
42
+ Args:
43
+ iterable: Any object that can be iterated over
44
+ """
45
+ self.iterator = iter(iterable) # type: Iterator[T]
46
+ self.put_back_stack = [] # type: List[T]
11
47
 
12
48
  def __iter__(self):
49
+ # type: () -> PutBackIterator[T]
50
+ """
51
+ Return the iterator object itself.
52
+
53
+ Returns:
54
+ PutBackIterator[T]: The current iterator instance.
55
+
56
+ This makes PutBackIterator compatible with the iterator protocol,
57
+ so it can be used directly in for-loops and other iterable contexts.
58
+ """
13
59
  return self
14
60
 
15
- def _next_impl(self, default=_DEFAULT_PLACEHOLDER):
16
- if self._put_back_stack:
17
- return self._put_back_stack.pop()
61
+ def next_implementation(self, default=DEFAULT_PLACEHOLDER):
62
+ """
63
+ Return the next item from the iterator, considering any put-back items.
64
+
65
+ Args:
66
+ default: Optional; a value to return if the iterator is exhausted.
67
+ If not provided and no items remain, raises StopIteration.
68
+
69
+ Returns:
70
+ T: The next item from the put-back stack (if not empty), or the underlying iterator.
71
+
72
+ Raises:
73
+ StopIteration: If there are no more items and no default is provided.
74
+
75
+ Notes:
76
+ This method underlies both the Python 2 and 3 iterator protocol methods.
77
+ """
78
+ if self.put_back_stack:
79
+ return self.put_back_stack.pop()
18
80
  else:
19
81
  end_sentinel = object()
20
- element_or_sentinel = next(self._iterator, end_sentinel)
82
+ element_or_sentinel = next(self.iterator, end_sentinel)
21
83
  if element_or_sentinel is end_sentinel:
22
- if default is _DEFAULT_PLACEHOLDER:
84
+ if default is DEFAULT_PLACEHOLDER:
23
85
  raise StopIteration
24
86
  else:
25
87
  return default
@@ -27,15 +89,36 @@ class PutBackIterator:
27
89
  return element_or_sentinel
28
90
 
29
91
  if sys.version_info < (3,):
30
- next = _next_impl
92
+ next = next_implementation
31
93
  else:
32
- __next__ = _next_impl
94
+ __next__ = next_implementation
33
95
 
34
96
  def put_back(self, element):
35
- self._put_back_stack.append(element)
97
+ # type: (T) -> None
98
+ """
99
+ Put an item back into the iterator to be returned on the next call to `next()`.
100
+
101
+ Args:
102
+ element (T): The item to put back onto the iterator.
103
+
104
+ Notes:
105
+ Items are put back in a last-in, first-out (LIFO) order. Calling `put_back()` multiple times will return those items in reverse order of addition.
106
+ """
107
+ self.put_back_stack.append(element)
36
108
 
37
109
  def has_next(self):
38
- if self._put_back_stack:
110
+ # type: () -> bool
111
+ """
112
+ Check whether the iterator has at least one more item to yield, without consuming it.
113
+
114
+ Returns:
115
+ bool: True if there is another item available, False otherwise.
116
+
117
+ Notes:
118
+ If there is no item in the put-back stack, this method advances
119
+ the underlying iterator once for lookahead, puts the value back if found, and then returns the result.
120
+ """
121
+ if self.put_back_stack:
39
122
  return True
40
123
  else:
41
124
  end_sentinel = object()
@@ -43,5 +126,5 @@ class PutBackIterator:
43
126
  if element_or_sentinel is end_sentinel:
44
127
  return False
45
128
  else:
46
- self._put_back_stack.append(element_or_sentinel)
129
+ self.put_back_stack.append(element_or_sentinel)
47
130
  return True
@@ -1,6 +0,0 @@
1
- put_back_iterator.py,sha256=2ME12t-aK1xpCMwAae0yVTrFYIWQPBdNC3emHUpt7JI,1365
2
- put_back_iterator-0.1.0a0.dist-info/licenses/LICENSE,sha256=FZ9XWedK_wQ4wfqVanrQVQpArRHDkxwxic2rgii1pZg,1066
3
- put_back_iterator-0.1.0a0.dist-info/METADATA,sha256=GGca8R3UzTev5VB4uBbewobeaql8BeVC6SXrYVxXhLc,3008
4
- put_back_iterator-0.1.0a0.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
5
- put_back_iterator-0.1.0a0.dist-info/top_level.txt,sha256=8XJh5rF6eOPUkwrmXZutOmEHGnbXK6VqPPp6mrvkrs4,18
6
- put_back_iterator-0.1.0a0.dist-info/RECORD,,