put-back-iterator 0.1.0a0__tar.gz → 0.1.0a1__tar.gz

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)
@@ -19,6 +19,8 @@ This package solves it with:
19
19
  ## Quick Start
20
20
 
21
21
  ```python
22
+ # coding=utf-8
23
+ from __future__ import print_function
22
24
  from put_back_iterator import PutBackIterator
23
25
 
24
26
  # Wrap any iterable
@@ -41,7 +43,7 @@ print(list(it)) # [1, 2, 3]
41
43
 
42
44
  ### 1. **Parsing/Tokenizing**
43
45
 
44
- ```python
46
+ ```
45
47
  tokens = PutBackIterator(tokenize(source_code))
46
48
  while tokens.has_next():
47
49
  token = next(tokens)
@@ -54,7 +56,7 @@ while tokens.has_next():
54
56
 
55
57
  ### 2. **Backtracking Algorithms**
56
58
 
57
- ```python
59
+ ```
58
60
  def backtrack(it):
59
61
  item = next(it)
60
62
  if not is_valid(item):
@@ -64,7 +66,7 @@ def backtrack(it):
64
66
 
65
67
  ### 3. **Stream Processing**
66
68
 
67
- ```python
69
+ ```
68
70
  for chunk in PutBackIterator(stream):
69
71
  if needs_retry(chunk):
70
72
  chunk = modify(chunk)
@@ -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)
@@ -6,4 +6,5 @@ setup.cfg
6
6
  put_back_iterator.egg-info/PKG-INFO
7
7
  put_back_iterator.egg-info/SOURCES.txt
8
8
  put_back_iterator.egg-info/dependency_links.txt
9
+ put_back_iterator.egg-info/requires.txt
9
10
  put_back_iterator.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+
2
+ [:python_version < "3.5"]
3
+ typing
@@ -0,0 +1,130 @@
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.
4
+ import sys
5
+ from typing import Iterable, Iterator, List, TypeVar
6
+
7
+ DEFAULT_PLACEHOLDER = object()
8
+ T = TypeVar('T')
9
+
10
+
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
+
38
+ def __init__(self, iterable):
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]
47
+
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
+ """
59
+ return self
60
+
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()
80
+ else:
81
+ end_sentinel = object()
82
+ element_or_sentinel = next(self.iterator, end_sentinel)
83
+ if element_or_sentinel is end_sentinel:
84
+ if default is DEFAULT_PLACEHOLDER:
85
+ raise StopIteration
86
+ else:
87
+ return default
88
+ else:
89
+ return element_or_sentinel
90
+
91
+ if sys.version_info < (3,):
92
+ next = next_implementation
93
+ else:
94
+ __next__ = next_implementation
95
+
96
+ def put_back(self, 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)
108
+
109
+ def has_next(self):
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:
122
+ return True
123
+ else:
124
+ end_sentinel = object()
125
+ element_or_sentinel = next(self, end_sentinel)
126
+ if element_or_sentinel is end_sentinel:
127
+ return False
128
+ else:
129
+ self.put_back_stack.append(element_or_sentinel)
130
+ return True
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["setuptools>=61.0"]
2
+ requires = ["setuptools"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "put-back-iterator"
7
- version = "0.1.0a0"
7
+ version = "0.1.0a1"
8
8
  description = "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."
9
9
  readme = "README.md"
10
10
  requires-python = ">=2"
@@ -18,6 +18,7 @@ classifiers = [
18
18
  "Operating System :: OS Independent",
19
19
  ]
20
20
  dependencies = [
21
+ "typing; python_version < '3.5'"
21
22
  ]
22
23
 
23
24
 
@@ -1,47 +0,0 @@
1
- from __future__ import absolute_import, division, print_function
2
- import sys
3
-
4
-
5
- _DEFAULT_PLACEHOLDER = object()
6
-
7
- class PutBackIterator:
8
- def __init__(self, iterable):
9
- self._iterator = iter(iterable)
10
- self._put_back_stack = []
11
-
12
- def __iter__(self):
13
- return self
14
-
15
- def _next_impl(self, default=_DEFAULT_PLACEHOLDER):
16
- if self._put_back_stack:
17
- return self._put_back_stack.pop()
18
- else:
19
- end_sentinel = object()
20
- element_or_sentinel = next(self._iterator, end_sentinel)
21
- if element_or_sentinel is end_sentinel:
22
- if default is _DEFAULT_PLACEHOLDER:
23
- raise StopIteration
24
- else:
25
- return default
26
- else:
27
- return element_or_sentinel
28
-
29
- if sys.version_info < (3,):
30
- next = _next_impl
31
- else:
32
- __next__ = _next_impl
33
-
34
- def put_back(self, element):
35
- self._put_back_stack.append(element)
36
-
37
- def has_next(self):
38
- if self._put_back_stack:
39
- return True
40
- else:
41
- end_sentinel = object()
42
- element_or_sentinel = next(self, end_sentinel)
43
- if element_or_sentinel is end_sentinel:
44
- return False
45
- else:
46
- self._put_back_stack.append(element_or_sentinel)
47
- return True