pythonic-fp.splitends 1.0.0__py3-none-any.whl → 1.0.2__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.
- pythonic_fp/splitends/splitend.py +10 -19
- pythonic_fp/splitends/splitend.pyi +38 -0
- pythonic_fp/splitends/splitend_node.py +22 -13
- pythonic_fp/splitends/splitend_node.pyi +36 -0
- {pythonic_fp_splitends-1.0.0.dist-info → pythonic_fp_splitends-1.0.2.dist-info}/METADATA +5 -6
- pythonic_fp_splitends-1.0.2.dist-info/RECORD +10 -0
- pythonic_fp_splitends-1.0.0.dist-info/RECORD +0 -8
- {pythonic_fp_splitends-1.0.0.dist-info → pythonic_fp_splitends-1.0.2.dist-info}/WHEEL +0 -0
- {pythonic_fp_splitends-1.0.0.dist-info → pythonic_fp_splitends-1.0.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
"""LIFO stacks safely sharing immutable data between themselves."""
|
|
16
16
|
|
|
17
|
-
from __future__ import annotations
|
|
18
|
-
|
|
19
17
|
from collections.abc import Callable, Hashable, Iterator
|
|
20
18
|
from typing import TypeVar
|
|
21
19
|
from pythonic_fp.iterables.folding import maybe_fold_left
|
|
@@ -34,6 +32,7 @@ class SplitEnd[D]:
|
|
|
34
32
|
splitends can safely share data with each other.
|
|
35
33
|
|
|
36
34
|
"""
|
|
35
|
+
|
|
37
36
|
__slots__ = '_count', '_tip', '_root'
|
|
38
37
|
|
|
39
38
|
def __init__(self, root_data: D, *data: D) -> None:
|
|
@@ -103,7 +102,7 @@ class SplitEnd[D]:
|
|
|
103
102
|
def snip(self) -> D:
|
|
104
103
|
"""Snip data off tip of SplitEnd. Just return data if tip is root.
|
|
105
104
|
|
|
106
|
-
:
|
|
105
|
+
:returns: data snipped off tip, otherwise root data if tip is root
|
|
107
106
|
|
|
108
107
|
"""
|
|
109
108
|
if self._count > 1:
|
|
@@ -116,48 +115,40 @@ class SplitEnd[D]:
|
|
|
116
115
|
def peak(self) -> D:
|
|
117
116
|
"""Return data from tip of SplitEnd, do not consume it.
|
|
118
117
|
|
|
119
|
-
:
|
|
118
|
+
:returns: data at the end of the SplitEnd
|
|
120
119
|
|
|
121
120
|
"""
|
|
122
121
|
return self._tip.peak()
|
|
123
122
|
|
|
124
|
-
def copy(self) -> SplitEnd[D]:
|
|
123
|
+
def copy(self) -> 'SplitEnd[D]':
|
|
125
124
|
"""Return a copy of the SplitEnd. O(1) space & time complexity.
|
|
126
125
|
|
|
127
|
-
:
|
|
126
|
+
:returns: a new SplitEnd instance with same data and root
|
|
128
127
|
|
|
129
128
|
"""
|
|
130
129
|
se: SplitEnd[D] = SplitEnd(self._root.peak())
|
|
131
130
|
se._count, se._tip, se._root = self._count, self._tip, self._root
|
|
132
131
|
return se
|
|
133
132
|
|
|
134
|
-
def fold[T](
|
|
135
|
-
self,
|
|
136
|
-
f: Callable[[T, D], T],
|
|
137
|
-
init: T | None = None
|
|
138
|
-
) -> T:
|
|
133
|
+
def fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T:
|
|
139
134
|
"""Reduce with a function, fold in natural LIFO Order.
|
|
140
135
|
|
|
141
136
|
:param f: folding function, for argument is for the accumulator
|
|
142
137
|
:param init: optional initial starting value for the fold
|
|
143
|
-
:
|
|
138
|
+
:returns: reduced value folding from tip to root in natural LIFO order
|
|
144
139
|
|
|
145
140
|
"""
|
|
146
141
|
return self._tip.fold(f, init)
|
|
147
142
|
|
|
148
|
-
def rev_fold[T](
|
|
149
|
-
self,
|
|
150
|
-
f: Callable[[T, D], T],
|
|
151
|
-
init: T | None = None
|
|
152
|
-
) -> T:
|
|
143
|
+
def rev_fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T:
|
|
153
144
|
"""Reduce with a function, fold from root to tip.
|
|
154
145
|
|
|
155
146
|
:param f: folding function, for argument is for the accumulator
|
|
156
147
|
:param init: optional initial starting value for the fold
|
|
157
|
-
:
|
|
148
|
+
:returns: reduced value folding from tip to root in natural LIFO order
|
|
158
149
|
|
|
159
150
|
"""
|
|
160
|
-
# The get() is safe because SplitEnds are never "empty" due to the root.
|
|
151
|
+
# The get() is safe because SplitEnds are never "empty" due to the root.
|
|
161
152
|
if init is None:
|
|
162
153
|
return maybe_fold_left(reversed(self), f).get()
|
|
163
154
|
return maybe_fold_left(reversed(self), f, init).get()
|
|
@@ -0,0 +1,38 @@
|
|
|
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, Hashable, Iterator
|
|
16
|
+
from typing import TypeVar
|
|
17
|
+
|
|
18
|
+
__all__ = ['SplitEnd']
|
|
19
|
+
|
|
20
|
+
D = TypeVar('D', bound=Hashable)
|
|
21
|
+
|
|
22
|
+
class SplitEnd[D]:
|
|
23
|
+
__slots__ = '_count', '_tip', '_root'
|
|
24
|
+
|
|
25
|
+
def __init__(self, root_data: D, *data: D) -> None: ...
|
|
26
|
+
def __iter__(self) -> Iterator[D]: ...
|
|
27
|
+
def __reversed__(self) -> Iterator[D]: ...
|
|
28
|
+
def __bool__(self) -> bool: ...
|
|
29
|
+
def __len__(self) -> int: ...
|
|
30
|
+
def __repr__(self) -> str: ...
|
|
31
|
+
def __str__(self) -> str: ...
|
|
32
|
+
def __eq__(self, other: object, /) -> bool: ...
|
|
33
|
+
def extend(self, *ds: D) -> None: ...
|
|
34
|
+
def snip(self) -> D: ...
|
|
35
|
+
def peak(self) -> D: ...
|
|
36
|
+
def copy(self) -> SplitEnd[D]: ...
|
|
37
|
+
def fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T: ...
|
|
38
|
+
def rev_fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T: ...
|
|
@@ -19,7 +19,7 @@ might prove useful to someone designing other data structures similar
|
|
|
19
19
|
to a ``splitend``.
|
|
20
20
|
|
|
21
21
|
"""
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
from collections.abc import Callable, Hashable, Iterator
|
|
24
24
|
from typing import cast, TypeVar
|
|
25
25
|
from pythonic_fp.fptools.maybe import MayBe
|
|
@@ -48,7 +48,7 @@ class SENode[D]:
|
|
|
48
48
|
|
|
49
49
|
__slots__ = '_data', '_prev'
|
|
50
50
|
|
|
51
|
-
def __init__(self, data: D, prev: SENode[D] | None = None) -> None:
|
|
51
|
+
def __init__(self, data: D, prev: 'SENode[D] | None' = None) -> None:
|
|
52
52
|
"""
|
|
53
53
|
:param data: nodes always contain data of type D
|
|
54
54
|
:param prev: potential link to a previous node
|
|
@@ -78,24 +78,33 @@ class SENode[D]:
|
|
|
78
78
|
return False
|
|
79
79
|
|
|
80
80
|
def peak(self) -> D:
|
|
81
|
-
"""
|
|
81
|
+
"""Returns contained data.
|
|
82
|
+
|
|
83
|
+
:returns: data stored in SENode
|
|
84
|
+
|
|
85
|
+
"""
|
|
82
86
|
return self._data
|
|
83
87
|
|
|
84
|
-
def pop2(self) -> tuple[D, SENode[D]]:
|
|
85
|
-
"""Return the data at the tip and the tail of the
|
|
88
|
+
def pop2(self) -> 'tuple[D, SENode[D]]':
|
|
89
|
+
"""Return the data at the tip and the tail of the SENode.
|
|
90
|
+
|
|
91
|
+
:returns: a tuple of the data at the tip and the previous SENode
|
|
92
|
+
|
|
93
|
+
"""
|
|
86
94
|
if self._prev:
|
|
87
95
|
return self._data, self._prev.get()
|
|
88
96
|
return self._data, self
|
|
89
97
|
|
|
90
|
-
def push(self, data: D) -> SENode[D]:
|
|
91
|
-
"""Push data onto the queue and return a new node containing the data.
|
|
98
|
+
def push(self, data: D) -> 'SENode[D]':
|
|
99
|
+
"""Push data onto the queue and return a new node containing the data.
|
|
100
|
+
|
|
101
|
+
:param data: data to be pushed onto the SENode stack
|
|
102
|
+
:returns: the resulting SENode[D] representing the top of the stack
|
|
103
|
+
|
|
104
|
+
"""
|
|
92
105
|
return SENode(data, self)
|
|
93
106
|
|
|
94
|
-
def fold[T](
|
|
95
|
-
self,
|
|
96
|
-
f: Callable[[T, D], T],
|
|
97
|
-
init: T | None = None
|
|
98
|
-
) -> T:
|
|
107
|
+
def fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T:
|
|
99
108
|
"""Fold data across linked nodes with a function..
|
|
100
109
|
|
|
101
110
|
.. code:: python
|
|
@@ -108,7 +117,7 @@ class SENode[D]:
|
|
|
108
117
|
|
|
109
118
|
:param f: folding function, first argument is for accumulated value
|
|
110
119
|
:param init: optional initial starting value for the fold
|
|
111
|
-
:
|
|
120
|
+
:returns: reduced value folding from end to root in natural LIFO order
|
|
112
121
|
|
|
113
122
|
"""
|
|
114
123
|
if init is None:
|
|
@@ -0,0 +1,36 @@
|
|
|
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, Hashable, Iterator
|
|
16
|
+
from typing import TypeVar
|
|
17
|
+
from pythonic_fp.fptools.maybe import MayBe
|
|
18
|
+
|
|
19
|
+
__all__ = ['SENode']
|
|
20
|
+
|
|
21
|
+
D = TypeVar('D', bound=Hashable)
|
|
22
|
+
|
|
23
|
+
class SENode[D]:
|
|
24
|
+
__slots__ = '_data', '_prev'
|
|
25
|
+
|
|
26
|
+
_data: D
|
|
27
|
+
_prev: MayBe[SENode[D]]
|
|
28
|
+
|
|
29
|
+
def __init__(self, data: D, prev: SENode[D] | None = None) -> None: ...
|
|
30
|
+
def __iter__(self) -> Iterator[D]: ...
|
|
31
|
+
def __bool__(self) -> bool: ...
|
|
32
|
+
def __eq__(self, other: object) -> bool: ...
|
|
33
|
+
def peak(self) -> D: ...
|
|
34
|
+
def pop2(self) -> tuple[D, SENode[D]]: ...
|
|
35
|
+
def push(self, data: D) -> SENode[D]: ...
|
|
36
|
+
def fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T: ...
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonic-fp-splitends
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: Mutable stack objects that can safely share data.
|
|
5
5
|
Keywords: SplitEnd,lifo,stack
|
|
6
6
|
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.13
|
|
8
8
|
Description-Content-Type: text/x-rst
|
|
9
9
|
Classifier: Development Status :: 3 - Alpha
|
|
10
10
|
Classifier: Framework :: Pytest
|
|
@@ -14,11 +14,10 @@ Classifier: Operating System :: OS Independent
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
15
|
Classifier: Typing :: Typed
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: pythonic-fp-
|
|
18
|
-
Requires-Dist: pythonic-fp-
|
|
17
|
+
Requires-Dist: pythonic-fp-fptools>=5.1.1
|
|
18
|
+
Requires-Dist: pythonic-fp-iterables>=5.1.1
|
|
19
19
|
Requires-Dist: pytest>=8.4.1 ; extra == "test"
|
|
20
|
-
Requires-Dist: pythonic-fp>=
|
|
21
|
-
Requires-Dist: pythonic-fp-singletons>=1.0.0 ; extra == "test"
|
|
20
|
+
Requires-Dist: pythonic-fp-gadgets>=3.0.0 ; extra == "test"
|
|
22
21
|
Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-splitends/blob/main/CHANGELOG.rst
|
|
23
22
|
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/splitends/development/build/html/releases.html
|
|
24
23
|
Project-URL: Homepage, https://github.com/grscheller/pythonic-fp/blob/main/README.md
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
pythonic_fp/splitends/__init__.py,sha256=gZzfqx_ODj0p32Zije6mFB-VUovxn2e8MGXjtpqcP2g,1457
|
|
2
|
+
pythonic_fp/splitends/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
pythonic_fp/splitends/splitend.py,sha256=k5oBCoTDL3OGKAgJ9bYeHZ5JL-FnRKwdQ7mEqS1e3x0,5018
|
|
4
|
+
pythonic_fp/splitends/splitend.pyi,sha256=xBJHTBdMO0VzeyhIUTiflm3BA3Pfq1GOjy9kvJOju1Q,1437
|
|
5
|
+
pythonic_fp/splitends/splitend_node.py,sha256=Fr74SpejGuLPK4giv1jKslX7NXxYe6Zh31Q3HDyAvEE,3894
|
|
6
|
+
pythonic_fp/splitends/splitend_node.pyi,sha256=3vmKwiQBsJV0v043fkA6CVPaNSFeJ02chUuwIs3G-YY,1273
|
|
7
|
+
pythonic_fp_splitends-1.0.2.dist-info/licenses/LICENSE,sha256=IJMkVWQUVy-SonK6SMaMotDQ6Zb-lVi2bUTiGp1GUO8,10774
|
|
8
|
+
pythonic_fp_splitends-1.0.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
9
|
+
pythonic_fp_splitends-1.0.2.dist-info/METADATA,sha256=jTPGsuy0qVW39R7EgbG60p2Gvwt3yYZY6v-cV8uICkQ,2575
|
|
10
|
+
pythonic_fp_splitends-1.0.2.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pythonic_fp/splitends/__init__.py,sha256=gZzfqx_ODj0p32Zije6mFB-VUovxn2e8MGXjtpqcP2g,1457
|
|
2
|
-
pythonic_fp/splitends/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
pythonic_fp/splitends/splitend.py,sha256=Th4aLzzS_fvIzt_zNn9Y3Dtb1gSJ9ZFI9QV-zQ-FEDg,5139
|
|
4
|
-
pythonic_fp/splitends/splitend_node.py,sha256=YnXrbju5MW6wEjjDfGEmwZ_hjbaYWDi1p7zfM8cC_ug,3682
|
|
5
|
-
pythonic_fp_splitends-1.0.0.dist-info/licenses/LICENSE,sha256=IJMkVWQUVy-SonK6SMaMotDQ6Zb-lVi2bUTiGp1GUO8,10774
|
|
6
|
-
pythonic_fp_splitends-1.0.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
7
|
-
pythonic_fp_splitends-1.0.0.dist-info/METADATA,sha256=TivzYvGfOjBAn-vNUmXsRLxowyRrgE_8g_RU3QhEIr8,2630
|
|
8
|
-
pythonic_fp_splitends-1.0.0.dist-info/RECORD,,
|
|
File without changes
|
{pythonic_fp_splitends-1.0.0.dist-info → pythonic_fp_splitends-1.0.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|