pythonic-fp.iterables 4.0.0__tar.gz → 5.1.0__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.
@@ -0,0 +1,7 @@
1
+ # Minimal version - only add to when necessary
2
+ **/__pycache__/
3
+ dist/
4
+ **/.dmypy.json
5
+ **/.mypy_cache/
6
+ **/.pytest_cache/
7
+ **/.ruff_cache
@@ -17,6 +17,18 @@ See `Semantic Versioning 2.0.0 <https://semver.org>`_.
17
17
  Releases and Important Milestones
18
18
  ---------------------------------
19
19
 
20
+ 5.1.0 - TBD
21
+ ~~~~~~~~~~~
22
+
23
+ - changed singletons -> sentinels
24
+ - Removed "from __future__ import annotations"
25
+ - Added .pyi files
26
+
27
+ 5.0.0 - 2025-08-02
28
+ ~~~~~~~~~~~~~~~~~~
29
+
30
+ General consistency tweaks and fixes across all pythonic-fp projects.
31
+
20
32
  4.0.0 - 2025-07-16
21
33
  ~~~~~~~~~~~~~~~~~~
22
34
 
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: pythonic-fp-iterables
3
+ Version: 5.1.0
4
+ Summary: Library of functions for iterating iterables
5
+ Keywords: iterables,iterators
6
+ Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
7
+ Requires-Python: >=3.13
8
+ Description-Content-Type: text/x-rst
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Framework :: Pytest
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Typing :: Typed
16
+ License-File: LICENSE
17
+ Requires-Dist: pythonic-fp-fptools>=5.1.0
18
+ Requires-Dist: pythonic-fp-gadgets>=3.0.1
19
+ Requires-Dist: pythonic-fp-sentinels>=2.1.1
20
+ Requires-Dist: pytest>=8.4.1 ; extra == "test"
21
+ Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-iterables/blob/main/CHANGELOG.rst
22
+ Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/iterables/development/build/html/releases.html
23
+ Project-URL: Homepage, https://github.com/grscheller/pythonic-fp/blob/main/README.md
24
+ Project-URL: Source, https://github.com/grscheller/pythonic-fp-iterables
25
+ Provides-Extra: test
26
+
27
+ Pythonic FP - Tools for iterables
28
+ =================================
29
+
30
+ PyPI project
31
+ `pythonic-fp.iterators <https://pypi.org/project/pythonic-fp.iterables>`_.
32
+
33
+ Library of functions for iterating iterables.
34
+
35
+ - Concatenating and merging iterables
36
+ - Dropping and taking values from iterables
37
+ - Reducing and accumulating iterables
38
+ - Assumptions
39
+
40
+ - iterables are not necessarily iterators
41
+ - at all times iterator protocol is assumed to be followed
42
+
43
+ - all iterators are assumed to be iterable
44
+ - for all iterators ``foo`` we assume ``iter(foo) is foo``
45
+
46
+ This PyPI project is part of of the
47
+ `pythonic-fp namespace projects <https://github.com/grscheller/pythonic-fp/blob/main/README.md>`_
48
+
49
+ Documentation
50
+ -------------
51
+
52
+ Documentation for this project is hosted on
53
+ `GitHub Pages
54
+ <https://grscheller.github.io/pythonic-fp/iterables/development/build/html>`_.
55
+
56
+ Copyright and License
57
+ ---------------------
58
+
59
+ Copyright (c) 2023-2025 Geoffrey R. Scheller. Licensed under the Apache
60
+ License, Version 2.0. See the LICENSE file for details.
61
+
@@ -0,0 +1,34 @@
1
+ Pythonic FP - Tools for iterables
2
+ =================================
3
+
4
+ PyPI project
5
+ `pythonic-fp.iterators <https://pypi.org/project/pythonic-fp.iterables>`_.
6
+
7
+ Library of functions for iterating iterables.
8
+
9
+ - Concatenating and merging iterables
10
+ - Dropping and taking values from iterables
11
+ - Reducing and accumulating iterables
12
+ - Assumptions
13
+
14
+ - iterables are not necessarily iterators
15
+ - at all times iterator protocol is assumed to be followed
16
+
17
+ - all iterators are assumed to be iterable
18
+ - for all iterators ``foo`` we assume ``iter(foo) is foo``
19
+
20
+ This PyPI project is part of of the
21
+ `pythonic-fp namespace projects <https://github.com/grscheller/pythonic-fp/blob/main/README.md>`_
22
+
23
+ Documentation
24
+ -------------
25
+
26
+ Documentation for this project is hosted on
27
+ `GitHub Pages
28
+ <https://grscheller.github.io/pythonic-fp/iterables/development/build/html>`_.
29
+
30
+ Copyright and License
31
+ ---------------------
32
+
33
+ Copyright (c) 2023-2025 Geoffrey R. Scheller. Licensed under the Apache
34
+ License, Version 2.0. See the LICENSE file for details.
@@ -1,8 +1,8 @@
1
1
  [project]
2
- name = "pythonic-fp.iterables"
3
- version = "4.0.0"
4
- readme = "README.md"
5
- requires-python = ">=3.12"
2
+ name = "pythonic-fp-iterables"
3
+ version = "5.1.0"
4
+ readme = "README.rst"
5
+ requires-python = ">=3.13"
6
6
  license = { file = "LICENSE" }
7
7
  authors = [{ name = "Geoffrey R. Scheller", email = "geoffrey@scheller.com" }]
8
8
  keywords = ["iterables", "iterators"]
@@ -16,29 +16,36 @@ classifiers = [
16
16
  "Typing :: Typed",
17
17
  ]
18
18
  dependencies = [
19
- "pythonic-fp.circulararray>=5.0.0",
20
- "pythonic-fp.containers >=2.0.0",
21
- "pythonic-fp.fptools >=3.0.0",
19
+ "pythonic-fp-fptools>=5.1.0",
20
+ "pythonic-fp-gadgets>=3.0.1",
21
+ "pythonic-fp-sentinels>=2.1.1",
22
22
  ]
23
23
  dynamic = ["description"]
24
24
 
25
25
  [project.urls]
26
26
  Changelog = "https://github.com/grscheller/pythonic-fp-iterables/blob/main/CHANGELOG.rst"
27
- Documentation = "https://grscheller.github.io/pythonic-fp/iterables/API/development/build/html/releases.html"
27
+ Documentation = "https://grscheller.github.io/pythonic-fp/iterables/development/build/html/releases.html"
28
28
  Homepage = "https://github.com/grscheller/pythonic-fp/blob/main/README.md"
29
29
  Source = "https://github.com/grscheller/pythonic-fp-iterables"
30
30
 
31
+ [project.optional-dependencies]
32
+ test = [
33
+ "pytest>=8.4.1",
34
+ ]
35
+
31
36
  [build-system]
32
37
  requires = ["flit_core>=3.12,<4"]
33
38
  build-backend = "flit_core.buildapi"
34
39
 
35
- [tool.flit.sdist]
36
- exclude = ["dist", "tests", ".gitignore", ".mypy_cache", ".pytest_cache"]
40
+ [tool.flit.module]
41
+ name = "pythonic_fp.iterables"
37
42
 
38
43
  [tool.mypy]
39
- enable_incomplete_feature = ["NewGenericSyntax"]
44
+ enable_incomplete_feature = "NewGenericSyntax"
45
+ explicit_package_bases = true
40
46
  implicit_reexport = false
41
47
  local_partial_types = true
48
+ namespace_packages = true
42
49
  warn_redundant_casts = true
43
50
  warn_return_any = true
44
51
  warn_unused_configs = true
@@ -46,24 +53,25 @@ warn_unused_configs = true
46
53
  [tool.pylsp-mypy]
47
54
  enabled = true
48
55
  live-mode = true
56
+ dmypy = false
49
57
  strict = true
50
58
  report_progress = true
51
- exclude = ["tests/.*"]
52
59
 
53
60
  [tool.pytest.ini_options]
54
- consider_namespace_packages = true
55
- testpaths = ["tests"]
56
61
  addopts = "-ra"
62
+ consider_namespace_packages = true
63
+ testpaths = ["tests/"]
57
64
 
58
65
  [tool.ruff]
59
66
  target-version = "py313"
60
67
 
61
- [tool.ruff.lint.per-file-ignores]
62
- "__init__.py" = ["F401"]
63
-
64
68
  [tool.ruff.lint.flake8-quotes]
65
69
  docstring-quotes = "double"
66
70
 
71
+ [tool.ruff.lint.per-file-ignores]
72
+ "tests/*" = ["C901"]
73
+ "**/*.py" = ["E741"]
74
+
67
75
  [tool.ruff.format]
68
76
  quote-style = "single"
69
77
  docstring-code-line-length = 72
@@ -0,0 +1,42 @@
1
+ # Copyright 2023-2024 Geoffrey R. Scheller
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Library of functions for iterating iterables
17
+ ============================================
18
+
19
+ +-----------+-------------------------------------------+
20
+ | Module | Description |
21
+ +===========+===========================================+
22
+ | merging | Concatenating and merging iterables |
23
+ +-----------+-------------------------------------------+
24
+ | drop_take | Dropping and taking values from iterables |
25
+ +-----------+-------------------------------------------+
26
+ | folding | Reducing and accumulating iterables |
27
+ +-----------+-------------------------------------------+
28
+
29
+ Assumptions
30
+ -----------
31
+
32
+ - iterables are not necessarily iterators
33
+ - at all times iterator protocol is assumed to be followed
34
+
35
+ - all iterators are assumed to be iterable
36
+ - for all iterators ``foobar`` we assume ``iter(foobar) is foobar``
37
+
38
+ """
39
+
40
+ __author__ = 'Geoffrey R. Scheller'
41
+ __copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
42
+ __license__ = 'Apache License 2.0'
@@ -0,0 +1,165 @@
1
+ # Copyright 2023-2025 Geoffrey R. Scheller
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Module pythonic_fp.iterables.drop_take
17
+ """
18
+
19
+ from collections.abc import Callable, Iterable, Iterator
20
+ from pythonic_fp.gadgets.box import Box
21
+ from .merging import concat
22
+
23
+ __all__ = [
24
+ 'drop',
25
+ 'drop_while',
26
+ 'take',
27
+ 'take_while',
28
+ 'take_split',
29
+ 'take_while_split',
30
+ ]
31
+
32
+
33
+ ## dropping and taking
34
+
35
+
36
+ def drop[D](iterable: Iterable[D], n: int) -> Iterator[D]:
37
+ """Drop the next n values from iterable.
38
+
39
+ :param iterable: iterable whose values are to be dropped
40
+ :param n: number of values to be dropped
41
+ :returns: an iterator of the remaining values
42
+
43
+ """
44
+ iterator = iter(iterable)
45
+ for _ in range(n):
46
+ try:
47
+ next(iterator)
48
+ except StopIteration:
49
+ break
50
+ return iterator
51
+
52
+
53
+ def drop_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[D]:
54
+ """Drop initial values from iterable while predicate is true.
55
+
56
+ :param iterable: iterable whose values are to be dropped
57
+ :param pred: Boolean valued function, the "predicate"
58
+ :return: an iterator beginning where pred returned false
59
+
60
+ """
61
+ iterator = iter(iterable)
62
+ while True:
63
+ try:
64
+ value = next(iterator)
65
+ if not pred(value):
66
+ iterator = concat((value,), iterator)
67
+ break
68
+ except StopIteration:
69
+ break
70
+ return iterator
71
+
72
+
73
+ def take[D](iterable: Iterable[D], n: int) -> Iterator[D]:
74
+ """Return an iterator of up to n initial values of an iterable.
75
+
76
+ :param iterable: iterable providing the values to be taken
77
+ :param n: number of values to be dropped
78
+ :return: an iterator of up to n initial values from iterable
79
+
80
+ """
81
+ iterator = iter(iterable)
82
+ for _ in range(n):
83
+ try:
84
+ value = next(iterator)
85
+ yield value
86
+ except StopIteration:
87
+ break
88
+
89
+
90
+ def take_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[D]:
91
+ """Yield values from iterable while predicate is true.
92
+
93
+ .. warning::
94
+ Risk of value loss if iterable is multiple referenced iterator.
95
+
96
+ :param iterable: iterable providing the values to be taken
97
+ :param pred: Boolean valued function, the "predicate"
98
+ :return: an Iterator of of values from iterable until predicate false
99
+
100
+ """
101
+ iterator = iter(iterable)
102
+ while True:
103
+ try:
104
+ value = next(iterator)
105
+ if pred(value):
106
+ yield value
107
+ else:
108
+ break
109
+ except StopIteration:
110
+ break
111
+
112
+
113
+ def take_split[D](iterable: Iterable[D], n: int) -> tuple[Iterator[D], Iterator[D]]:
114
+ """Same as take except also return iterator of remaining values.
115
+
116
+ .. Warning::
117
+
118
+ **CONTRACT:** Do not access the second returned iterator until the
119
+ first one is exhausted.
120
+
121
+ :param iterable: iterable providing the values to be taken
122
+ :param n: maximum number of values to be taken
123
+ :return: an iterator of values taken and an iterator of remaining values
124
+
125
+ """
126
+ iterator = iter(iterable)
127
+ itn = take(iterator, n)
128
+
129
+ return itn, iterator
130
+
131
+
132
+ def take_while_split[D](
133
+ iterable: Iterable[D], pred: Callable[[D], bool]
134
+ ) -> tuple[Iterator[D], Iterator[D]]:
135
+ """Yield values from iterable while predicate is true.
136
+
137
+ .. Warning::
138
+
139
+ **CONTRACT:** Do not access the second returned iterator until
140
+ the first one is exhausted.
141
+
142
+ :param iterable: iterable providing the values to be taken
143
+ :param pred: Boolean valued function
144
+ :return: tuple containing an iterator of values taken and an iterator of remaining values
145
+
146
+ """
147
+
148
+ def _take_while(
149
+ iterator: Iterator[D], pred: Callable[[D], bool], val: Box[D]
150
+ ) -> Iterator[D]:
151
+ while True:
152
+ try:
153
+ val.put(next(iterator))
154
+ if pred(val.get()):
155
+ yield val.pop()
156
+ else:
157
+ break
158
+ except StopIteration:
159
+ break
160
+
161
+ iterator = iter(iterable)
162
+ value: Box[D] = Box()
163
+ it_pred = _take_while(iterator, pred, value)
164
+
165
+ return (it_pred, concat(value, iterator))
@@ -0,0 +1,33 @@
1
+ # Copyright 2023-2025 Geoffrey R. Scheller
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from collections.abc import Callable, Iterable, Iterator
16
+
17
+ __all__ = [
18
+ 'drop',
19
+ 'drop_while',
20
+ 'take',
21
+ 'take_while',
22
+ 'take_split',
23
+ 'take_while_split',
24
+ ]
25
+
26
+ def drop[D](iterable: Iterable[D], n: int) -> Iterator[D]: ...
27
+ def drop_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[D]: ...
28
+ def take[D](iterable: Iterable[D], n: int) -> Iterator[D]: ...
29
+ def take_while[D](iterable: Iterable[D], pred: Callable[[D], bool]) -> Iterator[D]: ...
30
+ def take_split[D](iterable: Iterable[D], n: int) -> tuple[Iterator[D], Iterator[D]]: ...
31
+ def take_while_split[D](
32
+ iterable: Iterable[D], pred: Callable[[D], bool]
33
+ ) -> tuple[Iterator[D], Iterator[D]]: ...