pythonic-fp.splitends 0.30.0__py3-none-any.whl → 1.0.1__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/__init__.py +14 -3
- pythonic_fp/splitends/splitend.py +81 -60
- pythonic_fp/splitends/splitend.pyi +38 -0
- pythonic_fp/splitends/splitend_node.py +50 -28
- pythonic_fp/splitends/splitend_node.pyi +36 -0
- pythonic_fp_splitends-1.0.1.dist-info/METADATA +64 -0
- pythonic_fp_splitends-1.0.1.dist-info/RECORD +10 -0
- pythonic_fp_splitends-0.30.0.dist-info/METADATA +0 -55
- pythonic_fp_splitends-0.30.0.dist-info/RECORD +0 -8
- {pythonic_fp_splitends-0.30.0.dist-info → pythonic_fp_splitends-1.0.1.dist-info}/WHEEL +0 -0
- {pythonic_fp_splitends-0.30.0.dist-info → pythonic_fp_splitends-1.0.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,10 +12,21 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""
|
|
15
|
+
"""Mutable stack objects that can safely share data.
|
|
16
|
+
|
|
17
|
+
Python package Implementing a singularly linked LIFO queue
|
|
18
|
+
called a ``SplitEnd``. These data structures can safely share
|
|
19
|
+
data nodes between themselves.
|
|
20
|
+
|
|
21
|
+
- each ``SplitEnd`` is a very simple stateful (mutable) LIFO stack
|
|
22
|
+
- data can be "extended" to or "snipped" off of the end (tip)
|
|
23
|
+
- the "root" value of a ``SplitEnd`` is fixed and cannot be "snipped"
|
|
24
|
+
- different mutable split ends can safely share the same "tail"
|
|
25
|
+
- each ``SplitEnd`` sees itself as a singularly linked list
|
|
26
|
+
- bush-like datastructures can be formed using multiple ``SplitEnds``
|
|
27
|
+
- the ``SplitEnd`` copy method and ``len`` are O(1)
|
|
28
|
+
- in boolean context returns true if the ``SplitEnd`` is not just a "root"
|
|
16
29
|
|
|
17
|
-
Package implementing a singularly linked LIFO queue called a SplitEnd. These
|
|
18
|
-
data structures can safely share data nodes between themselves.
|
|
19
30
|
"""
|
|
20
31
|
|
|
21
32
|
__author__ = 'Geoffrey R. Scheller'
|
|
@@ -12,57 +12,51 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
With use I am finding this data structure needs some sort of supporting
|
|
18
|
-
infrastructure. Hence I split the original splitend module out to be its own
|
|
19
|
-
subpackage.
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
from __future__ import annotations
|
|
15
|
+
"""LIFO stacks safely sharing immutable data between themselves."""
|
|
23
16
|
|
|
24
17
|
from collections.abc import Callable, Hashable, Iterator
|
|
25
|
-
from typing import
|
|
26
|
-
from pythonic_fp.
|
|
27
|
-
from .splitend_node import SENode
|
|
18
|
+
from typing import TypeVar
|
|
19
|
+
from pythonic_fp.iterables.folding import maybe_fold_left
|
|
20
|
+
from .splitend_node import SENode
|
|
28
21
|
|
|
29
22
|
__all__ = ['SplitEnd']
|
|
30
23
|
|
|
31
24
|
D = TypeVar('D', bound=Hashable)
|
|
32
|
-
T = TypeVar('T')
|
|
33
25
|
|
|
34
26
|
|
|
35
27
|
class SplitEnd[D]:
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- each SplitEnd sees itself as a singularly linked list
|
|
43
|
-
- bush-like datastructures can be formed using multiple SplitEnds
|
|
44
|
-
- len() returns the number of elements on the SplitEnd stack
|
|
45
|
-
- in boolean context, return true if split end is not the "root"
|
|
28
|
+
"""Like one of many "split ends" from a shaft of hair,
|
|
29
|
+
a ``splitend`` can be "snipped" shorter or "extended"
|
|
30
|
+
further from its "tip". Its root is irremovable and
|
|
31
|
+
cannot be "snipped" off. While mutable, different
|
|
32
|
+
splitends can safely share data with each other.
|
|
33
|
+
|
|
46
34
|
"""
|
|
47
|
-
__slots__ = '_count', '_top', '_root'
|
|
48
35
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
__slots__ = '_count', '_tip', '_root'
|
|
37
|
+
|
|
38
|
+
def __init__(self, root_data: D, *data: D) -> None:
|
|
39
|
+
"""
|
|
40
|
+
:param root_data: irremovable initial data at bottom of stack
|
|
41
|
+
:param data: removable data to be pushed onto splitend stack
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
node: SENode[D] = SENode(root_data)
|
|
45
|
+
self._root = node
|
|
46
|
+
self._tip, self._count = node, 1
|
|
47
|
+
for d in data:
|
|
48
|
+
node = SENode(d, self._tip)
|
|
49
|
+
self._tip, self._count = node, self._count + 1
|
|
56
50
|
|
|
57
51
|
def __iter__(self) -> Iterator[D]:
|
|
58
|
-
return iter(self.
|
|
52
|
+
return iter(self._tip)
|
|
59
53
|
|
|
60
54
|
def __reversed__(self) -> Iterator[D]:
|
|
61
55
|
return reversed(list(self))
|
|
62
56
|
|
|
63
57
|
def __bool__(self) -> bool:
|
|
64
58
|
# Returns true until all data is exhausted
|
|
65
|
-
return bool(self.
|
|
59
|
+
return bool(self._tip)
|
|
66
60
|
|
|
67
61
|
def __len__(self) -> int:
|
|
68
62
|
return self._count
|
|
@@ -82,8 +76,8 @@ class SplitEnd[D]:
|
|
|
82
76
|
if self._root != other._root:
|
|
83
77
|
return False
|
|
84
78
|
|
|
85
|
-
left = self.
|
|
86
|
-
right = other.
|
|
79
|
+
left = self._tip
|
|
80
|
+
right = other._tip
|
|
87
81
|
for _ in range(self._count):
|
|
88
82
|
if left is right:
|
|
89
83
|
return True
|
|
@@ -94,40 +88,67 @@ class SplitEnd[D]:
|
|
|
94
88
|
right = right._prev.get()
|
|
95
89
|
return True
|
|
96
90
|
|
|
97
|
-
def
|
|
98
|
-
"""
|
|
91
|
+
def extend(self, *ds: D) -> None:
|
|
92
|
+
"""Add data onto the tip of the SplitEnd. Like adding a hair
|
|
93
|
+
extension.
|
|
94
|
+
|
|
95
|
+
:param ds: data to extend the splitend
|
|
96
|
+
|
|
97
|
+
"""
|
|
99
98
|
for d in ds:
|
|
100
|
-
node =
|
|
101
|
-
self.
|
|
99
|
+
node = SENode(d, self._tip)
|
|
100
|
+
self._tip, self._count = node, self._count + 1
|
|
101
|
+
|
|
102
|
+
def snip(self) -> D:
|
|
103
|
+
"""Snip data off tip of SplitEnd. Just return data if tip is root.
|
|
104
|
+
|
|
105
|
+
:returns: data snipped off tip, otherwise root data if tip is root
|
|
102
106
|
|
|
103
|
-
def pop(self) -> D | Never:
|
|
104
|
-
"""Pop data off of the top of the SplitEnd.
|
|
105
|
-
Re-root SplitEnd if root is popped off.
|
|
106
107
|
"""
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
if self._count > 1:
|
|
109
|
+
data, self._tip, self._count = self._tip.pop2() + (self._count - 1,)
|
|
110
|
+
else:
|
|
111
|
+
data = self._tip.peak()
|
|
112
|
+
|
|
110
113
|
return data
|
|
111
114
|
|
|
112
115
|
def peak(self) -> D:
|
|
113
|
-
"""Return
|
|
114
|
-
|
|
116
|
+
"""Return data from tip of SplitEnd, do not consume it.
|
|
117
|
+
|
|
118
|
+
:returns: data at the end of the SplitEnd
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
return self._tip.peak()
|
|
122
|
+
|
|
123
|
+
def copy(self) -> 'SplitEnd[D]':
|
|
124
|
+
"""Return a copy of the SplitEnd. O(1) space & time complexity.
|
|
115
125
|
|
|
116
|
-
|
|
117
|
-
"""Return a copy of the SplitEnd.
|
|
126
|
+
:returns: a new SplitEnd instance with same data and root
|
|
118
127
|
|
|
119
|
-
- O(1) space & time complexity.
|
|
120
|
-
- returns a new instance with same data, including the root
|
|
121
128
|
"""
|
|
122
|
-
se: SplitEnd[D] = SplitEnd(self._root.
|
|
123
|
-
se._count, se.
|
|
129
|
+
se: SplitEnd[D] = SplitEnd(self._root.peak())
|
|
130
|
+
se._count, se._tip, se._root = self._count, self._tip, self._root
|
|
124
131
|
return se
|
|
125
132
|
|
|
126
|
-
def fold[T](self, f: Callable[[T, D], T], init: T | None = None
|
|
127
|
-
"""Reduce with a function, fold in natural LIFO Order.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
def fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T:
|
|
134
|
+
"""Reduce with a function, fold in natural LIFO Order.
|
|
135
|
+
|
|
136
|
+
:param f: folding function, for argument is for the accumulator
|
|
137
|
+
:param init: optional initial starting value for the fold
|
|
138
|
+
:returns: reduced value folding from tip to root in natural LIFO order
|
|
139
|
+
|
|
140
|
+
"""
|
|
141
|
+
return self._tip.fold(f, init)
|
|
142
|
+
|
|
143
|
+
def rev_fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T:
|
|
144
|
+
"""Reduce with a function, fold from root to tip.
|
|
145
|
+
|
|
146
|
+
:param f: folding function, for argument is for the accumulator
|
|
147
|
+
:param init: optional initial starting value for the fold
|
|
148
|
+
:returns: reduced value folding from tip to root in natural LIFO order
|
|
149
|
+
|
|
150
|
+
"""
|
|
151
|
+
# The get() is safe because SplitEnds are never "empty" due to the root.
|
|
152
|
+
if init is None:
|
|
153
|
+
return maybe_fold_left(reversed(self), f).get()
|
|
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: ...
|
|
@@ -14,19 +14,19 @@
|
|
|
14
14
|
|
|
15
15
|
"""Data node class used privately by class SplitEnd.
|
|
16
16
|
|
|
17
|
-
Node classes used
|
|
18
|
-
|
|
17
|
+
Node classes used to make bush-like graphs. API made public since it
|
|
18
|
+
might prove useful to someone designing other data structures similar
|
|
19
|
+
to a ``splitend``.
|
|
20
|
+
|
|
19
21
|
"""
|
|
20
22
|
|
|
21
|
-
from __future__ import annotations
|
|
22
23
|
from collections.abc import Callable, Hashable, Iterator
|
|
23
24
|
from typing import cast, TypeVar
|
|
24
|
-
from pythonic_fp.
|
|
25
|
+
from pythonic_fp.fptools.maybe import MayBe
|
|
25
26
|
|
|
26
27
|
__all__ = ['SENode']
|
|
27
28
|
|
|
28
29
|
D = TypeVar('D', bound=Hashable)
|
|
29
|
-
T = TypeVar('T')
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class SENode[D]:
|
|
@@ -34,31 +34,28 @@ class SENode[D]:
|
|
|
34
34
|
|
|
35
35
|
- hashable data node for a end-to-root singularly linked list.
|
|
36
36
|
- designed so multiple splitends can safely share the same data
|
|
37
|
-
- this type of node always
|
|
38
|
-
|
|
39
|
-
- contain data
|
|
40
|
-
- potential link to previous node
|
|
41
|
-
|
|
42
|
-
- nodes point towards a unique "bottom node" with no predecessor
|
|
43
|
-
|
|
44
|
-
- in a Boolean context returns true if not at the bottom
|
|
45
|
-
- multiple bottom nodes can exist
|
|
46
37
|
|
|
47
38
|
- two nodes compare as equal if
|
|
48
39
|
|
|
49
40
|
- both their previous Nodes are the same
|
|
50
|
-
- their data
|
|
41
|
+
- their data compare as equal
|
|
51
42
|
|
|
52
43
|
- more than one node can point to the same proceeding node
|
|
53
44
|
|
|
54
45
|
- forming bush like graphs
|
|
46
|
+
|
|
55
47
|
"""
|
|
56
48
|
|
|
57
49
|
__slots__ = '_data', '_prev'
|
|
58
50
|
|
|
59
|
-
def __init__(self, data: D, prev:
|
|
51
|
+
def __init__(self, data: D, prev: 'SENode[D] | None' = None) -> None:
|
|
52
|
+
"""
|
|
53
|
+
:param data: nodes always contain data of type D
|
|
54
|
+
:param prev: potential link to a previous node
|
|
55
|
+
|
|
56
|
+
"""
|
|
60
57
|
self._data: D = data
|
|
61
|
-
self._prev:
|
|
58
|
+
self._prev: MayBe[SENode[D]] = MayBe(prev) if prev is not None else MayBe()
|
|
62
59
|
|
|
63
60
|
def __iter__(self) -> Iterator[D]:
|
|
64
61
|
node = self
|
|
@@ -68,7 +65,7 @@ class SENode[D]:
|
|
|
68
65
|
yield node._data
|
|
69
66
|
|
|
70
67
|
def __bool__(self) -> bool:
|
|
71
|
-
return self._prev !=
|
|
68
|
+
return self._prev != MayBe()
|
|
72
69
|
|
|
73
70
|
def __eq__(self, other: object) -> bool:
|
|
74
71
|
if not isinstance(other, type(self)):
|
|
@@ -81,22 +78,47 @@ class SENode[D]:
|
|
|
81
78
|
return False
|
|
82
79
|
|
|
83
80
|
def peak(self) -> D:
|
|
84
|
-
"""
|
|
81
|
+
"""Returns contained data.
|
|
82
|
+
|
|
83
|
+
:returns: data stored in SENode
|
|
84
|
+
|
|
85
|
+
"""
|
|
85
86
|
return self._data
|
|
86
87
|
|
|
87
|
-
def pop2(self) -> tuple[D,
|
|
88
|
-
"""Return the data at the
|
|
89
|
-
|
|
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
|
+
"""
|
|
94
|
+
if self._prev:
|
|
95
|
+
return self._data, self._prev.get()
|
|
96
|
+
return self._data, self
|
|
97
|
+
|
|
98
|
+
def push(self, data: D) -> 'SENode[D]':
|
|
99
|
+
"""Push data onto the queue and return a new node containing the data.
|
|
90
100
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
+
"""
|
|
105
|
+
return SENode(data, self)
|
|
94
106
|
|
|
95
107
|
def fold[T](self, f: Callable[[T, D], T], init: T | None = None) -> T:
|
|
96
|
-
"""
|
|
108
|
+
"""Fold data across linked nodes with a function..
|
|
109
|
+
|
|
110
|
+
.. code:: python
|
|
111
|
+
|
|
112
|
+
def fold[T](
|
|
113
|
+
self,
|
|
114
|
+
f: Callable([T, D], T],
|
|
115
|
+
init: T | None = None
|
|
116
|
+
) -> T
|
|
117
|
+
|
|
118
|
+
:param f: folding function, first argument is for accumulated value
|
|
119
|
+
:param init: optional initial starting value for the fold
|
|
120
|
+
:returns: reduced value folding from end to root in natural LIFO order
|
|
97
121
|
|
|
98
|
-
- with a function and an optional starting value
|
|
99
|
-
- reduces in natural LIFO order, from self to the root
|
|
100
122
|
"""
|
|
101
123
|
if init is None:
|
|
102
124
|
acc: T = cast(T, self._data)
|
|
@@ -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: ...
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pythonic-fp-splitends
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Mutable stack objects that can safely share data.
|
|
5
|
+
Keywords: SplitEnd,lifo,stack
|
|
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 :: 3 - Alpha
|
|
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-iterables>=5.1.0
|
|
19
|
+
Requires-Dist: pytest>=8.4.1 ; extra == "test"
|
|
20
|
+
Requires-Dist: pythonic-fp-gadgets>=3.0.1 ; extra == "test"
|
|
21
|
+
Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-splitends/blob/main/CHANGELOG.rst
|
|
22
|
+
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/splitends/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-splitends
|
|
25
|
+
Provides-Extra: test
|
|
26
|
+
|
|
27
|
+
Pythonic FP - SplitEnds
|
|
28
|
+
=======================
|
|
29
|
+
|
|
30
|
+
PyPI project
|
|
31
|
+
`pythonic-fp.splitends <https://pypi.org/project/pythonic-fp.splitends/>`_.
|
|
32
|
+
|
|
33
|
+
Python package Implementing a singularly linked LIFO queue called
|
|
34
|
+
a ``SplitEnd``. These data structures can safely share data nodes
|
|
35
|
+
between themselves.
|
|
36
|
+
|
|
37
|
+
- each ``SplitEnd`` is a very simple stateful (mutable) LIFO stack
|
|
38
|
+
- data can be "extended" to or "snipped" off of the end (tip)
|
|
39
|
+
- the "root" value of a ``SplitEnd`` is fixed and cannot be "snipped"
|
|
40
|
+
- different mutable split ends can safely share the same "tail"
|
|
41
|
+
- each ``SplitEnd`` sees itself as a singularly linked list
|
|
42
|
+
- bush-like datastructures can be formed using multiple ``SplitEnds``
|
|
43
|
+
- the ``SplitEnd`` copy method and ``len`` are O(1)
|
|
44
|
+
- in boolean context returns true if the ``SplitEnd`` is not just a "root"
|
|
45
|
+
|
|
46
|
+
This PyPI project is part of of the grscheller
|
|
47
|
+
`pythonic-fp namespace projects <https://github.com/grscheller/pythonic-fp/blob/main/README.md>`_
|
|
48
|
+
|
|
49
|
+
**Warning:** This PyPI project is Alpha level software and subject to
|
|
50
|
+
change.
|
|
51
|
+
|
|
52
|
+
Documentation
|
|
53
|
+
-------------
|
|
54
|
+
|
|
55
|
+
Documentation for this project is hosted on
|
|
56
|
+
`GitHub Pages
|
|
57
|
+
<https://grscheller.github.io/pythonic-fp/splitends/development/build/html>`_.
|
|
58
|
+
|
|
59
|
+
Copyright and License
|
|
60
|
+
---------------------
|
|
61
|
+
|
|
62
|
+
Copyright (c) 2023-2025 Geoffrey R. Scheller. Licensed under the Apache
|
|
63
|
+
License, Version 2.0. See the LICENSE file for details.
|
|
64
|
+
|
|
@@ -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.1.dist-info/licenses/LICENSE,sha256=IJMkVWQUVy-SonK6SMaMotDQ6Zb-lVi2bUTiGp1GUO8,10774
|
|
8
|
+
pythonic_fp_splitends-1.0.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
9
|
+
pythonic_fp_splitends-1.0.1.dist-info/METADATA,sha256=Q1-I-USkH1CwBTKIJ82ctnvwuLFKZxDGvQmawdzLHkY,2575
|
|
10
|
+
pythonic_fp_splitends-1.0.1.dist-info/RECORD,,
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pythonic-fp.splitends
|
|
3
|
-
Version: 0.30.0
|
|
4
|
-
Summary: Pythonic FP - Splitends
|
|
5
|
-
Keywords: SplitEnd,lifo,stack
|
|
6
|
-
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
7
|
-
Requires-Python: >=3.12
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
Classifier: Development Status :: 3 - Alpha
|
|
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.containers >=2.0.0
|
|
18
|
-
Project-URL: Changelog, https://grscheller.github.io/pythonic-fp-splitends/html/changelog.html
|
|
19
|
-
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp-splitends/html/
|
|
20
|
-
Project-URL: Homepage, https://github.com/grscheller/pythonic-fp/blob/main/README.md
|
|
21
|
-
Project-URL: Source, https://github.com/grscheller/pythonic-fp-splitends
|
|
22
|
-
|
|
23
|
-
# Pythonic FP - SplitEnds
|
|
24
|
-
|
|
25
|
-
PyPI project
|
|
26
|
-
[pythonic-fp.splitends](https://pypi.org/project/pythonic-fp.splitends/)
|
|
27
|
-
implementing a singularly linked data structures allowing data to be
|
|
28
|
-
safely shared between multiple instances.
|
|
29
|
-
|
|
30
|
-
- Singularly link stack with shareable data nodes
|
|
31
|
-
- *module* `pythonic_fp.splitends.splitend`
|
|
32
|
-
- *class* `SplitEnd`
|
|
33
|
-
|
|
34
|
-
- Shareable nodes used by SplitEnd instances
|
|
35
|
-
- *module* `pythonic_fp.splitends.splitend_node`
|
|
36
|
-
- *class* `SENode`
|
|
37
|
-
- shareable nodes used by SplitEnd instances
|
|
38
|
-
- this class is designed to be inaccessible to client code
|
|
39
|
-
|
|
40
|
-
This PyPI project is part of of the grscheller
|
|
41
|
-
[pythonic-fp namespace projects](https://github.com/grscheller/pythonic-fp/blob/main/README.md).
|
|
42
|
-
|
|
43
|
-
**Warning:** This PyPI project is Alpha level software and subject to
|
|
44
|
-
change. It will probably remain Alpha for quite a while.
|
|
45
|
-
|
|
46
|
-
## Documentation
|
|
47
|
-
|
|
48
|
-
Documentation hosted on
|
|
49
|
-
[GitHub Pages](https://grscheller.github.io/pythonic-fp-splitends/html).
|
|
50
|
-
|
|
51
|
-
## Copyright and License
|
|
52
|
-
|
|
53
|
-
Copyright (c) 2023-2025 Geoffrey R. Scheller. Licensed under the Apache
|
|
54
|
-
License, Version 2.0. See the LICENSE file for details.
|
|
55
|
-
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pythonic_fp/splitends/__init__.py,sha256=hAswthv0JMpJlJqid_hwgIO1OEYRqGSRKcACKBdvmUw,898
|
|
2
|
-
pythonic_fp/splitends/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
pythonic_fp/splitends/splitend.py,sha256=C4Zw_s02oAo9ivItinbeavJWFSuyWRx8QdLxa9MQAe0,4608
|
|
4
|
-
pythonic_fp/splitends/splitend_node.py,sha256=T0bAGMY4dL8Vv5w5z6BYX6pUrNQhXHaLVZo2XTtmvFI,3362
|
|
5
|
-
pythonic_fp_splitends-0.30.0.dist-info/licenses/LICENSE,sha256=IJMkVWQUVy-SonK6SMaMotDQ6Zb-lVi2bUTiGp1GUO8,10774
|
|
6
|
-
pythonic_fp_splitends-0.30.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
7
|
-
pythonic_fp_splitends-0.30.0.dist-info/METADATA,sha256=nYdAplEfe5m2LH5X2Yc1fOIZ3lPijnVa-jbfzjJ4vUs,2091
|
|
8
|
-
pythonic_fp_splitends-0.30.0.dist-info/RECORD,,
|
|
File without changes
|
{pythonic_fp_splitends-0.30.0.dist-info → pythonic_fp_splitends-1.0.1.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|