pythonic-fp-gadgets 3.1.0__py3-none-any.whl → 4.0.0__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.
@@ -13,27 +13,71 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- Simple Gadgets
17
- ==============
18
-
19
- Library of simple, but useful, functions and classes with no external
20
- dependencies besides the those from the Python standard Library. This
21
- includes other Pythonic Functional Programming dependencies.
22
-
23
- +------------------------------+----------------------+------------------------------------------------+
24
- | Description | Gadget | Module |
25
- +==============================+======================+================================================+
26
- | Single item box | class ``Box`` | ``pythonic_fp.gadgets.box`` |
27
- +------------------------------+----------------------+------------------------------------------------+
28
- | Return Iterator of arguments | function ``ita`` | ``pythonic_fp.gadgets.iterate_arguments`` |
29
- +------------------------------+----------------------+------------------------------------------------+
30
- | Find least common base class | function ``lca`` | ``pythonic_fp.gadgets.latest_common_ancestor`` |
31
- +------------------------------+----------------------+------------------------------------------------+
32
- | sentinels values with extras | module ``sentinals`` | ``pythonic_fp.gadgets.sentinels`` |
33
- +------------------------------+----------------------+------------------------------------------------+
16
+ **Module level function names.**
17
+
18
+ ========================== ================================================
19
+ Function Description
20
+ ========================== ================================================
21
+ ``first_common_ancestor`` Find least common base class in a type hierarchy
22
+ ``iterate_over_arguments`` Return an iterator over the function's arguments
23
+ ========================== ================================================
34
24
 
35
25
  """
36
26
 
27
+ from collections.abc import Iterator
28
+ from inspect import getmro
29
+
30
+ __all__ = ['iterate_over_arguments', 'first_common_ancestor']
31
+
37
32
  __author__ = 'Geoffrey R. Scheller'
38
33
  __copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
39
34
  __license__ = 'Apache License 2.0'
35
+
36
+
37
+ def iterate_over_arguments[A](*args: A) -> Iterator[A]:
38
+ """Function returning an iterator of its arguments.
39
+
40
+ .. note::
41
+
42
+ Does not create an object to iterate over.
43
+
44
+ - well, not in the Python world
45
+ - maybe in the C world
46
+
47
+ :param args: Objects to iterate over.
48
+ :returns: An iterator of the arguments.
49
+
50
+ """
51
+ yield from args
52
+
53
+
54
+ def first_common_ancestor(cls1: type, cls2: type) -> type:
55
+ """Find the least upper bound in the inheritance graph
56
+ of two classes.
57
+
58
+ .. warning::
59
+
60
+ This function can fail with a TypeError. Some error messages
61
+ seen are
62
+
63
+ - multiple bases have instance lay-out conflict
64
+ - type 'bool' is not an acceptable base type
65
+
66
+ This happens frequently when the function is given
67
+ Python builtin types or in multiple inheritance situations.
68
+
69
+ :param cls1: A class in the inheritance hierarchy.
70
+ :param cls2: A class in the inheritance hierarchy.
71
+ :returns: First common ancestor based on getmro order.
72
+ :raises TypeError: Raised by ``inspect.getmro``.
73
+
74
+ """
75
+ if issubclass(cls1, cls2):
76
+ return cls2
77
+ if issubclass(cls2, cls1):
78
+ return cls1
79
+
80
+ for common_ancestor in getmro(type('LcaDiamondClass', (cls1, cls2), {})):
81
+ if issubclass(cls1, common_ancestor) and issubclass(cls2, common_ancestor):
82
+ return common_ancestor
83
+ raise TypeError("latest_common_ancestor: no common ancestor found!!!")
@@ -0,0 +1,6 @@
1
+ from collections.abc import Iterator
2
+
3
+ __all__ = ['iterate_over_arguments', 'first_common_ancestor']
4
+
5
+ def iterate_over_arguments[A](*args: A) -> Iterator[A]: ...
6
+ def first_common_ancestor(cls1: type, cls2: type) -> type: ...
@@ -12,8 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- """Class for a stateful container that can hold at most one item."""
16
-
17
15
  __all__ = ['Box']
18
16
 
19
17
  from collections.abc import Callable, Iterator
@@ -28,8 +26,8 @@ class Box[T]:
28
26
 
29
27
  .. note::
30
28
 
31
- - ``Box(item: T)``: contains at one item of type ``T``
32
- - ``Box[T]()``: creates empty container
29
+ - ``Box(item: T)``: contains at one item of type ``T``
30
+ - ``Box[T]()``: creates empty container
33
31
 
34
32
  Where type ``T`` is some definite type, which
35
33
  could be ``None`` or even ``Never``.
@@ -42,10 +40,10 @@ class Box[T]:
42
40
  __slots__ = ('_item',)
43
41
  __match_args__ = ('_item',)
44
42
 
45
- @overload
46
- def __init__(self) -> None: ...
47
43
  @overload
48
44
  def __init__(self, item: T) -> None: ...
45
+ @overload
46
+ def __init__(self) -> None: ...
49
47
 
50
48
  def __init__(self, item: T | _Sentinel = _sentinel) -> None:
51
49
  """
@@ -0,0 +1,27 @@
1
+ from _typeshed import Incomplete
2
+ from collections.abc import Callable, Iterator
3
+ from typing import overload
4
+
5
+ __all__ = ['Box']
6
+
7
+ type _Sentinel = object
8
+ class Box[T]:
9
+ __match_args__: Incomplete
10
+ @overload
11
+ def __init__(self, item: T) -> None: ...
12
+ @overload
13
+ def __init__(self) -> None: ...
14
+ def __bool__(self) -> bool: ...
15
+ def __iter__(self) -> Iterator[T]: ...
16
+ def __len__(self) -> int: ...
17
+ def __eq__(self, other: object) -> bool: ...
18
+ @overload
19
+ def get(self) -> T: ...
20
+ @overload
21
+ def get(self, alt: T) -> T: ...
22
+ def pop(self) -> T: ...
23
+ def push(self, item: T) -> None: ...
24
+ def put(self, item: T) -> None: ...
25
+ def exchange(self, new_item: T) -> T: ...
26
+ def map[U](self, f: Callable[[T], U]) -> Box[U]: ...
27
+ def bind[U](self, f: Callable[[T], 'Box[U]']) -> Box[U]: ...
@@ -12,20 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- """
16
- Sentinels with Extras
17
- =====================
18
-
19
- +-----------------------+---------------------------+-----------------------------------------------+
20
- | Module | Class | Represents |
21
- +=======================+===========================+===============================================+
22
- | ``sentinel.novalue`` | ``NoValue`` | an actually , not potentially, missing value |
23
- +-----------------------+---------------------------+-----------------------------------------------+
24
- | ``sentinel.flavored`` | ``Sentinel[H: Hashable]`` | distinct sentinels labeled by hashable values |
25
- +-----------------------+---------------------------+-----------------------------------------------+
26
-
27
- """
28
-
29
15
  __author__ = 'Geoffrey R. Scheller'
30
16
  __copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
31
17
  __license__ = 'Apache License 2.0'
File without changes
@@ -13,15 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- Flavored Sentinels
17
- ==================
18
-
19
- Sentinel values labeled by different (hashable) flavors. Can be used
20
- with functions or classes.
21
-
22
- .. note::
23
-
24
- Threadsafe.
16
+ **Sentinel values labeled by different (hashable) flavors.**
25
17
 
26
18
  .. note::
27
19
 
@@ -35,15 +27,9 @@ with functions or classes.
35
27
  To ensure that reference equality is used, put the known
36
28
  sentinel value first in the comparison.
37
29
 
38
- .. tip::
39
-
40
- Use as a hidden implementation detail when creating "optional"
41
- arguments to functions and methods. Do not export the sentinel
42
- value.
43
-
44
- - does not clash with end user code
30
+ .. note::
45
31
 
46
- - which may be using either ``None`` or ``()`` as a "sentinel" values
32
+ Threadsafe.
47
33
 
48
34
  """
49
35
 
@@ -0,0 +1,8 @@
1
+ from typing import Hashable
2
+
3
+ __all__ = ['Sentinel']
4
+
5
+ class Sentinel[H: Hashable]:
6
+ def __new__(cls, flavor: H) -> Sentinel[H]: ...
7
+ def __init__(self, flavor: H) -> None: ...
8
+ def flavor(self) -> H: ...
@@ -13,66 +13,78 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- Missing Value Sentinel
17
- ======================
16
+ **Singleton class representing an actually, not potentially, missing value.**
18
17
 
19
- Singleton class representing a missing value.
18
+ .. note:
20
19
 
21
- In untyped Python, both ``None`` and ``()`` are often used by end users
22
- and libraries as sentinel values. I prefer to think of them as
20
+ ``NoValue()`` is a singleton object representing a missing value.
23
21
 
24
- - ``None``: returned (or returns) no values
25
- - ``()``: an empty, possibly typed, but still iterable collection
22
+ While ``None`` and ``()`` are frequently used as sentinel values,
23
+ I prefer to think of them as
26
24
 
27
- While ``NoValue()`` is a singleton object representing a missing value.
25
+ - ``None``: Returns, or returned, no values.
26
+ - ``()``: An empty, possibly typed, iterable collection.
28
27
 
29
- Given variables
28
+ .. important::
30
29
 
31
- .. code:: python
30
+ Given variables
32
31
 
33
- x: int | NoValue
34
- y: int | NoValue
32
+ .. code:: python
35
33
 
36
- Equality between ``x`` and ``y`` means both values exist and compare as equal.
37
- If one or both of theses values are missing, then what is there to compare?
34
+ x: int | NoValue
35
+ y: int | NoValue
38
36
 
39
- .. table:: ``x == y``
37
+ Equality between ``x`` and ``y`` means both values exist and compare
38
+ as equal. If one or both of theses values are missing, then what is
39
+ there to compare?
40
40
 
41
- +-----------+-----------+--------+--------+
42
- | x∖y | NoValue() | 42 | 57 |
43
- +===========+===========+========+========+
44
- | NoValue() | false | false | false |
45
- +-----------+-----------+--------+--------+
46
- | 42 | false | true | false |
47
- +-----------+-----------+--------+--------+
48
- | 57 | false | false | true |
49
- +-----------+-----------+--------+--------+
41
+ .. table:: ``x == y``
50
42
 
51
- Similarly for not equals.
43
+ +-----------+-----------+--------+--------+
44
+ | x∖y | NoValue() | 42 | 57 |
45
+ +===========+===========+========+========+
46
+ | NoValue() | false | false | false |
47
+ +-----------+-----------+--------+--------+
48
+ | 42 | false | true | false |
49
+ +-----------+-----------+--------+--------+
50
+ | 57 | false | false | true |
51
+ +-----------+-----------+--------+--------+
52
52
 
53
- .. table:: ``x != y``
53
+ Similarly for not equals.
54
54
 
55
- +-----------+-----------+--------+--------+
56
- | x∖y | NoValue() | 42 | 57 |
57
- +===========+===========+========+========+
58
- | NoValue() | false | false | false |
59
- +-----------+-----------+--------+--------+
60
- | 42 | false | false | true |
61
- +-----------+-----------+--------+--------+
62
- | 57 | false | true | false |
63
- +-----------+-----------+--------+--------+
55
+ .. table:: ``x != y``
56
+
57
+ +-----------+-----------+--------+--------+
58
+ | x∖y | NoValue() | 42 | 57 |
59
+ +===========+===========+========+========+
60
+ | NoValue() | false | false | false |
61
+ +-----------+-----------+--------+--------+
62
+ | 42 | false | false | true |
63
+ +-----------+-----------+--------+--------+
64
+ | 57 | false | true | false |
65
+ +-----------+-----------+--------+--------+
66
+
67
+ .. warning::
68
+
69
+ Only use ``==`` or ``!=`` in value comparisons. To directly
70
+ identity the ``NoValue`` singleton, use ``is`` and ``is not``
71
+ instead.
64
72
 
65
73
  .. note::
66
74
 
67
75
  Threadsafe.
68
76
 
69
- .. warning::
77
+ .. tip::
70
78
 
71
- Do not use ``==`` or ``!=`` to identify ``NoValue()``, compare
72
- directly by identity using ``is`` and ``is not``.
79
+ Use as a hidden implementation detail when creating "optional"
80
+ arguments to functions and methods.
73
81
 
74
- """
82
+ To help ensure the abstraction does not leak,
75
83
 
84
+ - Do not export the sentinel value.
85
+ - Use ``@overload`` to keep the NoValue type out of documentation and IDEs.
86
+
87
+ """
76
88
  import threading
77
89
  from typing import ClassVar, final
78
90
 
@@ -100,7 +112,13 @@ class NoValue():
100
112
  return 'NoValue()'
101
113
 
102
114
  def __eq__(self, other: object) -> bool:
115
+ """
116
+ :returns: False
117
+ """
103
118
  return False
104
119
 
105
120
  def __ne__(self, other: object) -> bool:
121
+ """
122
+ :returns: False
123
+ """
106
124
  return False
@@ -0,0 +1,6 @@
1
+ __all__ = ['NoValue']
2
+
3
+ class NoValue:
4
+ def __new__(cls) -> NoValue: ...
5
+ def __eq__(self, other: object) -> bool: ...
6
+ def __ne__(self, other: object) -> bool: ...
@@ -0,0 +1,124 @@
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
+ __all__ = ['Wrap', 'HWrap']
16
+
17
+ from collections.abc import Callable, Iterator, Hashable
18
+
19
+
20
+ class Wrap[T]():
21
+ """Immutablely wrap exactly one value of a given type.
22
+
23
+ .. tip::
24
+
25
+ ``Wrap`` objects can be used in Python match statements.
26
+
27
+ """
28
+ __slots__ = ('_item',)
29
+ __match_args__ = ('_item',)
30
+
31
+ def __init__(self, item: T) -> None:
32
+ self._item = item
33
+
34
+ def __bool__(self) -> bool:
35
+ return bool(self._item)
36
+
37
+ def __iter__(self) -> Iterator[T]:
38
+ if self:
39
+ yield self._item
40
+
41
+ def __repr__(self) -> str:
42
+ return 'Wrap(' + repr(self._item) + ')'
43
+
44
+ def __eq__(self, other: object) -> bool:
45
+ if not isinstance(other, type(self)):
46
+ return False
47
+
48
+ if self._item is other._item:
49
+ return True
50
+ return self._item == other._item
51
+
52
+ def map[U](self, f: Callable[[T], U]) -> 'Wrap[U]':
53
+ """Map function ``f`` over contents.
54
+
55
+ :param f: Mapping function.
56
+ :returns: A new instance.
57
+
58
+ """
59
+ return Wrap(f(self._item))
60
+
61
+ def bind[U](self, f: Callable[[T], 'Wrap[U]']) -> 'Wrap[U]':
62
+ """Flatmap the ``Wrap`` with function ``f``.
63
+
64
+ :param f: Binding function.
65
+ :returns: A new instance.
66
+
67
+ """
68
+ return f(self._item)
69
+
70
+
71
+ class HWrap[T: Hashable](Hashable):
72
+ """Immutablely wrap exactly one hashable value of a given type.
73
+
74
+ .. tip::
75
+
76
+ ``Wrap`` objects can be used in Python match statements.
77
+
78
+ """
79
+ __slots__ = ('_item', '_hash')
80
+ __match_args__ = ('_item',)
81
+
82
+ def __init__(self, item: T) -> None:
83
+ self._item, self._hash = item, hash(item)
84
+
85
+ def __hash__(self) -> int:
86
+ return self._hash
87
+
88
+ def __bool__(self) -> bool:
89
+ return bool(self._item)
90
+
91
+ def __iter__(self) -> Iterator[T]:
92
+ if self:
93
+ yield self._item
94
+
95
+ def __repr__(self) -> str:
96
+ return 'Wrap(' + repr(self._item) + ')'
97
+
98
+ def __eq__(self, other: object) -> bool:
99
+ if not isinstance(other, type(self)):
100
+ return False
101
+
102
+ if self._hash != other._hash:
103
+ return False
104
+ if self._item is other._item:
105
+ return True
106
+ return self._item == other._item
107
+
108
+ def map[U](self, f: Callable[[T], U]) -> 'HWrap[U]':
109
+ """Map function ``f`` over contents.
110
+
111
+ :param f: Mapping function.
112
+ :returns: A new instance.
113
+
114
+ """
115
+ return HWrap(f(self._item))
116
+
117
+ def bind[U](self, f: Callable[[T], 'HWrap[U]']) -> 'HWrap[U]':
118
+ """Flatmap the ``Wrap`` with function ``f``.
119
+
120
+ :param f: Binding function.
121
+ :returns: A new instance.
122
+
123
+ """
124
+ return f(self._item)
@@ -0,0 +1,23 @@
1
+ from _typeshed import Incomplete
2
+ from collections.abc import Callable, Hashable, Iterator
3
+
4
+ __all__ = ['Wrap', 'HWrap']
5
+
6
+ class Wrap[T]:
7
+ __match_args__: Incomplete
8
+ def __init__(self, item: T) -> None: ...
9
+ def __bool__(self) -> bool: ...
10
+ def __iter__(self) -> Iterator[T]: ...
11
+ def __eq__(self, other: object) -> bool: ...
12
+ def map[U](self, f: Callable[[T], U]) -> Wrap[U]: ...
13
+ def bind[U](self, f: Callable[[T], 'Wrap[U]']) -> Wrap[U]: ...
14
+
15
+ class HWrap[T: Hashable](Hashable):
16
+ __match_args__: Incomplete
17
+ def __init__(self, item: T) -> None: ...
18
+ def __hash__(self) -> int: ...
19
+ def __bool__(self) -> bool: ...
20
+ def __iter__(self) -> Iterator[T]: ...
21
+ def __eq__(self, other: object) -> bool: ...
22
+ def map[U](self, f: Callable[[T], U]) -> HWrap[U]: ...
23
+ def bind[U](self, f: Callable[[T], 'HWrap[U]']) -> HWrap[U]: ...
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonic-fp-gadgets
3
- Version: 3.1.0
4
- Summary: Simple Gadgets
3
+ Version: 4.0.0
4
+ Summary: **Module level function names.**
5
5
  Keywords: gadgets
6
6
  Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
7
7
  Requires-Python: >=3.13
@@ -17,8 +17,8 @@ License-File: LICENSE
17
17
  Requires-Dist: pytest>=8.4.1 ; extra == "test"
18
18
  Requires-Dist: pythonic-fp-circulararray>=6.0.0 ; extra == "test"
19
19
  Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-gadgets/blob/main/CHANGELOG.rst
20
- Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/gadgets/development/build/html/releases.html
21
- Project-URL: Homepage, https://github.com/grscheller/pythonic-fp/blob/main/README.md
20
+ Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/gadgets/development/build/html/
21
+ Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/homepage/build/html/
22
22
  Project-URL: Source, https://github.com/grscheller/pythonic-fp-gadgets
23
23
  Provides-Extra: test
24
24
 
@@ -39,7 +39,7 @@ outside the Python Standard Library.
39
39
 
40
40
  Part of the
41
41
  `pythonic-fp
42
- <https://grscheller.github.io/pythonic-fp/homepage/build/html/index.html>`_
42
+ <https://grscheller.github.io/pythonic-fp>`_
43
43
  PyPI projects.
44
44
 
45
45
  Documentation
@@ -47,7 +47,7 @@ Documentation
47
47
 
48
48
  Documentation for this project is hosted on
49
49
  `GitHub Pages
50
- <https://grscheller.github.io/pythonic-fp/gadgets/development/build/html>`_.
50
+ <https://grscheller.github.io/pythonic-fp/gadgets>`_.
51
51
 
52
52
  Copyright and License
53
53
  ---------------------
@@ -0,0 +1,17 @@
1
+ pythonic_fp/gadgets/__init__.py,sha256=PXZJRwsDkGrI2_B3nbwU4n3tzeSGONquV-_inWroxsg,2811
2
+ pythonic_fp/gadgets/__init__.pyi,sha256=cAf10WX2ZHMs-Tf93mImmDdZw7lNEmwjorkiVF04s_E,224
3
+ pythonic_fp/gadgets/box.py,sha256=aSR9V_PuAhjqQ8Vs7fj80zgirb8BWzkUFr1pWvSbBDc,4994
4
+ pythonic_fp/gadgets/box.pyi,sha256=UkJBY8Xiv4oe70Q3bhJL1jGHwYmFWwkTIdxvf2zR3v4,837
5
+ pythonic_fp/gadgets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ pythonic_fp/gadgets/wrap.py,sha256=5FonuzJ6E3SeUoneUoUsjM6x9COZUnyzWQHPKN45cRo,3259
7
+ pythonic_fp/gadgets/wrap.pyi,sha256=TRbBph_517VNCKchwU-pdtPCn73c09gq8EchDFM7Uyo,868
8
+ pythonic_fp/gadgets/sentinels/__init__.py,sha256=81T-HGQ9BgXj57PO_pduo8MpSQpRgZwT8LIXwODhHkI,724
9
+ pythonic_fp/gadgets/sentinels/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ pythonic_fp/gadgets/sentinels/flavored.py,sha256=RMqDRmN_ImbRlf_Yaqj7jwnOc6YBeEdAfi8xGCyw1xs,2195
11
+ pythonic_fp/gadgets/sentinels/flavored.pyi,sha256=K3YSyXLyylPII2ahRP0olhzLJruOeR73TFJDC6rCUwk,212
12
+ pythonic_fp/gadgets/sentinels/novalue.py,sha256=RA5foyWFgSHCpaJPJ0N0Td7cldLEbwX_bzkTgs_ZW-o,3573
13
+ pythonic_fp/gadgets/sentinels/novalue.pyi,sha256=zhZdePpWoQ3ZXOq7xQWGR0A4W_XzasdBQKcoywXZEZI,173
14
+ pythonic_fp_gadgets-4.0.0.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
15
+ pythonic_fp_gadgets-4.0.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
16
+ pythonic_fp_gadgets-4.0.0.dist-info/METADATA,sha256=sbyH2GplSHaJ52be21JwZasacpNr5v2bG72MIvWQMVA,1827
17
+ pythonic_fp_gadgets-4.0.0.dist-info/RECORD,,
@@ -1,36 +0,0 @@
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
- """Function which returns an iterator of its arguments."""
16
-
17
- from collections.abc import Iterator
18
-
19
- __all__ = ['ita']
20
-
21
-
22
- def ita[A](*args: A) -> Iterator[A]:
23
- """Function returning an iterator of its arguments.
24
-
25
- .. note::
26
-
27
- Does not create an object to iterate over.
28
-
29
- - well, not in the Python world
30
- - maybe in the C world
31
-
32
- :param args: Objects to iterate over.
33
- :returns: An iterator of the arguments.
34
-
35
- """
36
- yield from args
@@ -1,51 +0,0 @@
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
- """Last Common Ancestor of Two Classes."""
16
-
17
- from inspect import getmro
18
-
19
- __all__ = ['lca']
20
-
21
-
22
- def lca(cls1: type, cls2: type) -> type:
23
- """Find the least upper bound in the inheritance graph
24
- of two classes.
25
-
26
- .. warning::
27
-
28
- This function can fail with a TypeError. Some error messages
29
- seen are
30
-
31
- - multiple bases have instance lay-out conflict
32
- - type 'bool' is not an acceptable base type
33
-
34
- This happens frequently when the function is given
35
- Python builtin types.
36
-
37
- :param cls1: first class
38
- :param cls2: second class
39
- :returns: Least common ancestor base class of ``cls1`` and ``cls2``.
40
- :raises TypeError: theoretically only from ``inspect.getmto``
41
-
42
- """
43
- if issubclass(cls1, cls2):
44
- return cls2
45
- if issubclass(cls2, cls1):
46
- return cls1
47
-
48
- for common_ancestor in getmro(type('LcaDiamondClass', (cls1, cls2), {})):
49
- if issubclass(cls1, common_ancestor) and issubclass(cls2, common_ancestor):
50
- return common_ancestor
51
- raise TypeError("latest_common_ancestor: no common ancestor found!!!")
@@ -1,12 +0,0 @@
1
- pythonic_fp/gadgets/__init__.py,sha256=dWSy355mwnu8WWX473KMLgSduFaUwmCqFyc93aWJ0yA,2122
2
- pythonic_fp/gadgets/box.py,sha256=gdlCI0BXXRvlaHrN8j0gjcVh5omZnE_g0fTpEYLBBxE,5068
3
- pythonic_fp/gadgets/iterate_arguments.py,sha256=7gFQgqn8vpBQIxOPYlpAgW26Fyzfjnux3Y2cxHYZuSM,1057
4
- pythonic_fp/gadgets/latest_common_ancestor.py,sha256=CHN5q82p8n05XPuA5rTq9gwtOkvuz9U-QMJEqOjlqqM,1689
5
- pythonic_fp/gadgets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- pythonic_fp/gadgets/sentinels/__init__.py,sha256=2166dSxuQqQT_f7QKOsD6vKrMkFy6XzIJKhPnXMCKy0,1493
7
- pythonic_fp/gadgets/sentinels/flavored.py,sha256=g1Y2qGAGL06GDmF7d6jTuPj11OCWaxbQ89E7TtXGWtU,2543
8
- pythonic_fp/gadgets/sentinels/novalue.py,sha256=Whu0BPSWrl7t_V2dITlyLT6lt2UiNphMr_fWT_heOfI,3077
9
- pythonic_fp_gadgets-3.1.0.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
10
- pythonic_fp_gadgets-3.1.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
11
- pythonic_fp_gadgets-3.1.0.dist-info/METADATA,sha256=hwYMFjf0xfV4z8cfwWHC-E5oUySAFcEHHtdB6Qr67Ls,1876
12
- pythonic_fp_gadgets-3.1.0.dist-info/RECORD,,