pythonic-fp-booleans 1.1.2__tar.gz → 2.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.
- pythonic_fp_booleans-2.1.0/CHANGELOG.rst +82 -0
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/PKG-INFO +11 -11
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/README.rst +5 -4
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/pyproject.toml +5 -6
- {pythonic_fp_booleans-1.1.2/src/pythonic_fp/booleans/subtypes → pythonic_fp_booleans-2.1.0/src/pythonic_fp/booleans}/__init__.py +19 -13
- {pythonic_fp_booleans-1.1.2/src/pythonic_fp/booleans/subtypes → pythonic_fp_booleans-2.1.0/src/pythonic_fp/booleans}/flavored.py +38 -46
- {pythonic_fp_booleans-1.1.2/src/pythonic_fp/booleans/subtypes → pythonic_fp_booleans-2.1.0/src/pythonic_fp/booleans}/flavored.pyi +1 -1
- pythonic_fp_booleans-2.1.0/src/pythonic_fp/booleans/py.typed +0 -0
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/src/pythonic_fp/booleans/subtypable.py +47 -26
- {pythonic_fp_booleans-1.1.2/src/pythonic_fp/booleans/subtypes → pythonic_fp_booleans-2.1.0/src/pythonic_fp/booleans}/truthy_falsy.py +21 -32
- {pythonic_fp_booleans-1.1.2/src/pythonic_fp/booleans/subtypes → pythonic_fp_booleans-2.1.0/src/pythonic_fp/booleans}/truthy_falsy.pyi +1 -1
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_bool_vs_fbool.py +1 -1
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_flavored.py +1 -1
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_flavored_non_shortcut_logic.py +1 -1
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_flavored_sbool.py +1 -1
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_true_false.py +1 -1
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_true_false_non_shortcut_logic.py +2 -2
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_typing.py +2 -2
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_variance.py +2 -2
- pythonic_fp_booleans-1.1.2/CHANGELOG.rst +0 -46
- pythonic_fp_booleans-1.1.2/src/pythonic_fp/booleans/__init__.py +0 -99
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/.gitignore +0 -0
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/LICENSE +0 -0
- /pythonic_fp_booleans-1.1.2/src/pythonic_fp/booleans/py.typed → /pythonic_fp_booleans-2.1.0/src/pythonic_fp/booleans/__init__.pyi +0 -0
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/src/pythonic_fp/booleans/subtypable.pyi +0 -0
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_bool_vs_sbool.py +0 -0
- {pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_subtypable_non_shortcut_logic.py +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
CHANGELOG
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
PyPI pythonic-fp-booleans project.
|
|
5
|
+
|
|
6
|
+
Semantic Versioning
|
|
7
|
+
-------------------
|
|
8
|
+
|
|
9
|
+
Strict 3 digit semantic versioning adopted 2025-05-19.
|
|
10
|
+
|
|
11
|
+
- **MAJOR** version incremented for incompatible API changes
|
|
12
|
+
- **MINOR** version incremented for backward compatible added functionality
|
|
13
|
+
- **PATCH** version incremented for backward compatible bug fixes
|
|
14
|
+
|
|
15
|
+
See `Semantic Versioning 2.0.0 <https://semver.org>`_.
|
|
16
|
+
|
|
17
|
+
Releases and Important Milestones
|
|
18
|
+
---------------------------------
|
|
19
|
+
|
|
20
|
+
PyPI 2.1.0 - 2025-12-02
|
|
21
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
22
|
+
|
|
23
|
+
Now requires pythonic-fp-gadgets 4.0.1 to be installed.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
PyPI 2.0.0 - 2025-09-27
|
|
27
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
28
|
+
|
|
29
|
+
Released to get the next consistent set of Pythonic FP out (v3.2.0) out.
|
|
30
|
+
|
|
31
|
+
- PyPI documentation link now goes to root, not releases
|
|
32
|
+
- decided to flatten directory structure
|
|
33
|
+
|
|
34
|
+
- makes more sense from an end user perspective
|
|
35
|
+
- will help Sphinx docs be more homogeneous across repos
|
|
36
|
+
|
|
37
|
+
Warning: API not fully locked down, major version number change may be needed.
|
|
38
|
+
|
|
39
|
+
TODO:
|
|
40
|
+
|
|
41
|
+
- bitwise operators not symmetric when used with ``SBool`` types and ``int`` or ``bool``
|
|
42
|
+
|
|
43
|
+
- may need to define reversed bit-wise operators
|
|
44
|
+
|
|
45
|
+
- ``TS_Boolean`` has a code smell to it
|
|
46
|
+
|
|
47
|
+
- may be just a hack to get get around sub-optimal type usage
|
|
48
|
+
- Using ``TS_Bool`` as a variable type may be enough
|
|
49
|
+
|
|
50
|
+
PyPI 1.1.2 - 2025-09-09
|
|
51
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
52
|
+
|
|
53
|
+
Fixed pyproject.toml dependency issues.
|
|
54
|
+
|
|
55
|
+
PyPI 1.1.1 - 2025-09-03
|
|
56
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
57
|
+
|
|
58
|
+
Only change was to give README.rst a final edit. Missed this on
|
|
59
|
+
the v1.1.0 release.
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
PyPI 1.1.0 - 2025-09-02
|
|
63
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
64
|
+
|
|
65
|
+
First PyPI release as pythonic-fp-booleans.
|
|
66
|
+
|
|
67
|
+
- module booleans.subtypable
|
|
68
|
+
- package booleans.subtypes
|
|
69
|
+
|
|
70
|
+
- module booleans.subtypes.flavored
|
|
71
|
+
- module booleans.subtypes.truthy_falsy
|
|
72
|
+
|
|
73
|
+
Needs
|
|
74
|
+
|
|
75
|
+
- "pythonic-fp>=3.0.0" for gadgets
|
|
76
|
+
- "pythonic-fp-sentinels>=2.1.0",
|
|
77
|
+
|
|
78
|
+
Created pythonic-fp-boolean repo - 2025-08-06
|
|
79
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
80
|
+
|
|
81
|
+
- created grscheller/pythonic-fp-boolean GitHub repo
|
|
82
|
+
- moved pythonic_fp.singletons.sbool to pythonic_fp.booleans.sbool
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonic-fp-booleans
|
|
3
|
-
Version:
|
|
4
|
-
Summary: Subtypable Boolean
|
|
3
|
+
Version: 2.1.0
|
|
4
|
+
Summary: Subtypable Boolean Class Hierarchy
|
|
5
5
|
Keywords: booleans,subtypable
|
|
6
6
|
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
7
7
|
Requires-Python: >=3.13
|
|
8
8
|
Description-Content-Type: text/x-rst
|
|
9
|
-
Classifier: Development Status ::
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
10
|
Classifier: Framework :: Pytest
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -14,12 +14,11 @@ 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-gadgets>=
|
|
18
|
-
Requires-Dist: pythonic-fp-sentinels>=2.1.0
|
|
17
|
+
Requires-Dist: pythonic-fp-gadgets>=4.0.1
|
|
19
18
|
Requires-Dist: pytest>=8.4.1 ; extra == "test"
|
|
20
19
|
Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-booleans/blob/main/CHANGELOG.rst
|
|
21
|
-
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/booleans/development/build/html/
|
|
22
|
-
Project-URL: Homepage, https://github.
|
|
20
|
+
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/booleans/development/build/html/
|
|
21
|
+
Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/homepage/build/html/
|
|
23
22
|
Project-URL: Source, https://github.com/grscheller/pythonic-fp-booleans
|
|
24
23
|
Provides-Extra: test
|
|
25
24
|
|
|
@@ -35,16 +34,17 @@ Subtypable Boolean like classes.
|
|
|
35
34
|
While still compatible with Python shortcut logic, these classes can be non-shortcut logically
|
|
36
35
|
composed with Python’s bitwise operators.
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
`pythonic-fp
|
|
40
|
-
<https://github.
|
|
37
|
+
Part of the
|
|
38
|
+
`pythonic-fp
|
|
39
|
+
<https://grscheller.github.io/pythonic-fp>`_
|
|
40
|
+
PyPI projects.
|
|
41
41
|
|
|
42
42
|
Documentation
|
|
43
43
|
-------------
|
|
44
44
|
|
|
45
45
|
Documentation for this project is hosted on
|
|
46
46
|
`GitHub Pages
|
|
47
|
-
<https://grscheller.github.io/pythonic-fp/booleans
|
|
47
|
+
<https://grscheller.github.io/pythonic-fp/booleans>`_.
|
|
48
48
|
|
|
49
49
|
Copyright and License
|
|
50
50
|
---------------------
|
|
@@ -10,16 +10,17 @@ Subtypable Boolean like classes.
|
|
|
10
10
|
While still compatible with Python shortcut logic, these classes can be non-shortcut logically
|
|
11
11
|
composed with Python’s bitwise operators.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
`pythonic-fp
|
|
15
|
-
<https://github.
|
|
13
|
+
Part of the
|
|
14
|
+
`pythonic-fp
|
|
15
|
+
<https://grscheller.github.io/pythonic-fp>`_
|
|
16
|
+
PyPI projects.
|
|
16
17
|
|
|
17
18
|
Documentation
|
|
18
19
|
-------------
|
|
19
20
|
|
|
20
21
|
Documentation for this project is hosted on
|
|
21
22
|
`GitHub Pages
|
|
22
|
-
<https://grscheller.github.io/pythonic-fp/booleans
|
|
23
|
+
<https://grscheller.github.io/pythonic-fp/booleans>`_.
|
|
23
24
|
|
|
24
25
|
Copyright and License
|
|
25
26
|
---------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pythonic-fp-booleans"
|
|
3
|
-
version = "
|
|
3
|
+
version = "2.1.0"
|
|
4
4
|
readme = "README.rst"
|
|
5
5
|
requires-python = ">=3.13"
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -10,7 +10,7 @@ keywords = [
|
|
|
10
10
|
"subtypable",
|
|
11
11
|
]
|
|
12
12
|
classifiers = [
|
|
13
|
-
"Development Status ::
|
|
13
|
+
"Development Status :: 4 - Beta",
|
|
14
14
|
"Framework :: Pytest",
|
|
15
15
|
"Intended Audience :: Developers",
|
|
16
16
|
"License :: OSI Approved :: Apache Software License",
|
|
@@ -19,15 +19,14 @@ classifiers = [
|
|
|
19
19
|
"Typing :: Typed",
|
|
20
20
|
]
|
|
21
21
|
dependencies = [
|
|
22
|
-
"pythonic-fp-gadgets>=
|
|
23
|
-
"pythonic-fp-sentinels>=2.1.0",
|
|
22
|
+
"pythonic-fp-gadgets>=4.0.1",
|
|
24
23
|
]
|
|
25
24
|
dynamic = ["description"]
|
|
26
25
|
|
|
27
26
|
[project.urls]
|
|
28
27
|
Changelog = "https://github.com/grscheller/pythonic-fp-booleans/blob/main/CHANGELOG.rst"
|
|
29
|
-
Documentation = "https://grscheller.github.io/pythonic-fp/booleans/development/build/html/
|
|
30
|
-
Homepage = "https://github.
|
|
28
|
+
Documentation = "https://grscheller.github.io/pythonic-fp/booleans/development/build/html/"
|
|
29
|
+
Homepage = "https://grscheller.github.io/pythonic-fp/homepage/build/html/"
|
|
31
30
|
Source = "https://github.com/grscheller/pythonic-fp-booleans"
|
|
32
31
|
|
|
33
32
|
[project.optional-dependencies]
|
|
@@ -13,23 +13,29 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Subtypable Boolean Class Hierarchy
|
|
17
|
+
==================================
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
---------------
|
|
19
|
+
.. graphviz::
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
digraph Booleans {
|
|
22
|
+
bgcolor="#957fb8";
|
|
23
|
+
node [style=filled, fillcolor="#181616", fontcolor="#dcd7ba"];
|
|
24
|
+
edge [color="#181616", fontcolor="#dcd7ba"];
|
|
25
|
+
int -> bool;
|
|
26
|
+
int -> SBool;
|
|
27
|
+
SBool -> "FBool(h1)";
|
|
28
|
+
SBool -> "FBool(h2)";
|
|
29
|
+
SBool -> "FBool(h3)";
|
|
30
|
+
SBool -> TF_Bool;
|
|
31
|
+
TF_Bool -> T_Bool;
|
|
32
|
+
TF_Bool -> F_Bool;
|
|
33
|
+
}
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
While still compatible with Python shortcut logic, ``SBool`` and its
|
|
36
|
+
subclasses can be non-shortcut logically composed with Python's bitwise
|
|
37
|
+
operators.
|
|
27
38
|
|
|
28
|
-
- where truthy and falsy are typeable
|
|
29
|
-
- class ``TF_Bool`` consists of two disjoint subclasses
|
|
30
|
-
|
|
31
|
-
- ``T_Bool`` instances are always truthy
|
|
32
|
-
- ``F_Bool`` instances are always falsy
|
|
33
39
|
"""
|
|
34
40
|
|
|
35
41
|
__author__ = 'Geoffrey R. Scheller'
|
|
@@ -12,42 +12,46 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
"""
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
**Class F_Bool.**
|
|
17
|
+
|
|
18
|
+
When different flavors of the truth matter. Each ``FBool`` is
|
|
19
|
+
an ``SBool`` subtype corresponds to a hashable value
|
|
20
|
+
called its flavor.
|
|
21
|
+
|
|
22
|
+
.. warning::
|
|
23
|
+
|
|
24
|
+
Combining ``FBool`` instances of different flavors
|
|
25
|
+
with bitwise operators will just result in an ``SBool``.
|
|
26
|
+
|
|
27
|
+
----
|
|
28
|
+
|
|
29
|
+
**Function truthy(flavor: Hashable)**
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
Returns the truthy ``FBool`` of a particular ``flavor``.
|
|
32
|
+
|
|
33
|
+
----
|
|
34
|
+
|
|
35
|
+
**Function falsy(flavor: Hashable)**
|
|
36
|
+
|
|
37
|
+
Returns the falsy ``FBool`` of a particular ``flavor``.
|
|
22
38
|
"""
|
|
23
39
|
|
|
24
40
|
import threading
|
|
25
41
|
from collections.abc import Hashable
|
|
26
42
|
from typing import ClassVar, final
|
|
27
|
-
from
|
|
43
|
+
from .subtypable import SBool
|
|
28
44
|
|
|
29
45
|
__all__ = ['FBool', 'truthy', 'falsy']
|
|
30
46
|
|
|
31
47
|
|
|
32
48
|
@final
|
|
33
49
|
class FBool(SBool):
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
----------------
|
|
50
|
+
_falsy_dict: 'ClassVar[dict[Hashable, FBool]]' = {}
|
|
51
|
+
_falsy_dict_lock: ClassVar[threading.Lock] = threading.Lock()
|
|
37
52
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
This type can also do (non-shortcut) Boolean logic using Python
|
|
42
|
-
bitwise operators. Combining ``FBool`` instances of different
|
|
43
|
-
flavors in this way will just result in an ``SBool``.
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
_truthy: 'ClassVar[dict[Hashable, FBool]]' = {}
|
|
47
|
-
_truthy_lock: ClassVar[threading.Lock] = threading.Lock()
|
|
48
|
-
|
|
49
|
-
_falsy: 'ClassVar[dict[Hashable, FBool]]' = {}
|
|
50
|
-
_falsy_lock: ClassVar[threading.Lock] = threading.Lock()
|
|
53
|
+
_truthy_dict: 'ClassVar[dict[Hashable, FBool]]' = {}
|
|
54
|
+
_truthy_dict_lock: ClassVar[threading.Lock] = threading.Lock()
|
|
51
55
|
|
|
52
56
|
def __new__(cls, witness: object, flavor: Hashable) -> 'FBool':
|
|
53
57
|
"""
|
|
@@ -56,22 +60,21 @@ class FBool(SBool):
|
|
|
56
60
|
:returns: The truthy or falsy ``FBool`` instance of a particular ``flavor``.
|
|
57
61
|
"""
|
|
58
62
|
if witness:
|
|
59
|
-
if flavor not in cls.
|
|
63
|
+
if flavor not in cls._truthy_dict:
|
|
60
64
|
with cls._truthy_lock:
|
|
61
|
-
if flavor not in cls.
|
|
62
|
-
cls.
|
|
63
|
-
return cls.
|
|
65
|
+
if flavor not in cls._truthy_dict:
|
|
66
|
+
cls._truthy_dict[flavor] = super(SBool, cls).__new__(cls, True)
|
|
67
|
+
return cls._truthy_dict[flavor]
|
|
64
68
|
else:
|
|
65
|
-
if flavor not in cls.
|
|
66
|
-
with cls.
|
|
67
|
-
if flavor not in cls.
|
|
68
|
-
cls.
|
|
69
|
-
return cls.
|
|
69
|
+
if flavor not in cls._falsy_dict:
|
|
70
|
+
with cls._falsy_dict_lock:
|
|
71
|
+
if flavor not in cls._falsy_dict:
|
|
72
|
+
cls._falsy_dict[flavor] = super(SBool, cls).__new__(cls, False)
|
|
73
|
+
return cls._falsy_dict[flavor]
|
|
70
74
|
|
|
71
75
|
def __init__(self, witness: object, flavor: Hashable) -> None:
|
|
72
76
|
self._flavor = flavor
|
|
73
77
|
|
|
74
|
-
# override in derived classes
|
|
75
78
|
def __repr__(self) -> str:
|
|
76
79
|
if self:
|
|
77
80
|
return f'FBool(True, {repr(self._flavor)})'
|
|
@@ -110,34 +113,23 @@ class FBool(SBool):
|
|
|
110
113
|
return self ^ other
|
|
111
114
|
|
|
112
115
|
def flavor(self) -> Hashable:
|
|
113
|
-
"""
|
|
116
|
+
"""
|
|
114
117
|
:returns: The flavor of the FBool.
|
|
115
|
-
|
|
116
118
|
"""
|
|
117
119
|
return self._flavor
|
|
118
120
|
|
|
119
121
|
|
|
120
122
|
def truthy(flavor: Hashable) -> FBool:
|
|
121
123
|
"""
|
|
122
|
-
Get truthy FBool
|
|
123
|
-
----------------
|
|
124
|
-
|
|
125
|
-
Get the truthy ``FBool`` of a particular ``flavor``.
|
|
126
|
-
|
|
127
124
|
:param flavor: Hashable value to determine which singleton ``flavor`` to return.
|
|
128
|
-
:returns: The truthy singleton of a particular
|
|
125
|
+
:returns: The truthy singleton of a particular ``flavor``.
|
|
129
126
|
"""
|
|
130
127
|
return FBool(True, flavor)
|
|
131
128
|
|
|
132
129
|
|
|
133
130
|
def falsy(flavor: Hashable) -> FBool:
|
|
134
131
|
"""
|
|
135
|
-
Get falsy FBool
|
|
136
|
-
---------------
|
|
137
|
-
|
|
138
|
-
Get the falsy ``FBool`` of a particular ``flavor``.
|
|
139
|
-
|
|
140
132
|
:param flavor: Hashable value to determine which singleton ``flavor`` to return.
|
|
141
|
-
:returns: The falsy singleton of a particular
|
|
133
|
+
:returns: The falsy singleton of a particular ``flavor``.
|
|
142
134
|
"""
|
|
143
135
|
return FBool(False, flavor)
|
|
File without changes
|
{pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/src/pythonic_fp/booleans/subtypable.py
RENAMED
|
@@ -12,14 +12,52 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
"""
|
|
16
|
+
**Subtypable Boolean.**
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
Like Python's built in bool, class ``SBool`` is a subclass of int.
|
|
19
|
+
Unlike bool, this version can be further subclassed.
|
|
20
|
+
|
|
21
|
+
This type and its subtypes can also do (non-shortcut) Boolean logic
|
|
22
|
+
using Python bitwise operators.
|
|
23
|
+
|
|
24
|
+
+-------------------+--------+------------+
|
|
25
|
+
| Boolean operation | symbol | dunder |
|
|
26
|
+
+===================+========+============+
|
|
27
|
+
| not | ``~`` | __invert__ |
|
|
28
|
+
+-------------------+--------+------------+
|
|
29
|
+
| and | ``&`` | __and__ |
|
|
30
|
+
+-------------------+--------+------------+
|
|
31
|
+
| or | ``|`` | __or__ |
|
|
32
|
+
+-------------------+--------+------------+
|
|
33
|
+
| xor | ``^`` | __xor__ |
|
|
34
|
+
+-------------------+--------+------------+
|
|
35
|
+
|
|
36
|
+
.. note::
|
|
37
|
+
|
|
38
|
+
These operators are contravariant, that is they will return the
|
|
39
|
+
instance of the latest common ancestor of their arguments. More
|
|
40
|
+
specifically, the instance returned will have the type of the
|
|
41
|
+
least upper bound in the inheritance graph of the classes of
|
|
42
|
+
the two arguments.
|
|
43
|
+
|
|
44
|
+
While compatible with Python short-cut logic. Unfortunately, the
|
|
45
|
+
``not`` operator always returns a ``bool``. Use the bitwise ``~``
|
|
46
|
+
operator to return an opposite ``SBool`` class or subclass.
|
|
47
|
+
|
|
48
|
+
.. warning::
|
|
49
|
+
|
|
50
|
+
The "bitwise" operators can raise ``TypeError`` exceptions
|
|
51
|
+
when applied against an ``SBool`` and objects not descended
|
|
52
|
+
from ``int``.
|
|
53
|
+
|
|
54
|
+
"""
|
|
17
55
|
|
|
18
56
|
import threading
|
|
19
57
|
from collections.abc import Hashable
|
|
20
58
|
from typing import cast, ClassVar, Final, overload
|
|
21
|
-
from pythonic_fp.gadgets
|
|
22
|
-
from pythonic_fp.sentinels.novalue import NoValue
|
|
59
|
+
from pythonic_fp.gadgets import first_common_ancestor as fca
|
|
60
|
+
from pythonic_fp.gadgets.sentinels.novalue import NoValue
|
|
23
61
|
|
|
24
62
|
__all__ = ['SBool', 'TRUTH', 'LIE']
|
|
25
63
|
|
|
@@ -27,17 +65,6 @@ _novalue = NoValue()
|
|
|
27
65
|
|
|
28
66
|
|
|
29
67
|
class SBool(int):
|
|
30
|
-
"""Subtypable Booleans.
|
|
31
|
-
|
|
32
|
-
Like Python's built in bool, class SBool is a subclass of int.
|
|
33
|
-
Unlike bool, this version can be further subclassed. It can be
|
|
34
|
-
used with Python ``and`` and ``or`` short-cut logic. The ``not``
|
|
35
|
-
operator will just return a ``bool``. Use the ``snot`` function
|
|
36
|
-
to return an ``SBool`` or ``SBool`` subclass.
|
|
37
|
-
|
|
38
|
-
This type and its subtypes can also do (non-shortcut) Boolean logic
|
|
39
|
-
using Python bitwise operators.
|
|
40
|
-
"""
|
|
41
68
|
_falsy: 'ClassVar[SBool | NoValue]' = _novalue
|
|
42
69
|
_falsy_lock: ClassVar[threading.Lock] = threading.Lock()
|
|
43
70
|
|
|
@@ -83,14 +110,12 @@ class SBool(int):
|
|
|
83
110
|
|
|
84
111
|
def __and__(self, other: int) -> int:
|
|
85
112
|
try:
|
|
86
|
-
base_class =
|
|
113
|
+
base_class = fca(type(self), type(other))
|
|
87
114
|
except TypeError:
|
|
88
115
|
if type(other) is bool:
|
|
89
116
|
base_class = int
|
|
90
117
|
else:
|
|
91
|
-
msg = (
|
|
92
|
-
f"unsupported operand type(s) for &: '{type(self)}' and '{type(other)}'"
|
|
93
|
-
)
|
|
118
|
+
msg = f"unsupported operand type(s) for &: '{type(self)}' and '{type(other)}'"
|
|
94
119
|
raise TypeError(msg)
|
|
95
120
|
|
|
96
121
|
if issubclass(base_class, SBool):
|
|
@@ -102,14 +127,12 @@ class SBool(int):
|
|
|
102
127
|
|
|
103
128
|
def __or__(self, other: int) -> int:
|
|
104
129
|
try:
|
|
105
|
-
base_class =
|
|
130
|
+
base_class = fca(type(self), type(other))
|
|
106
131
|
except TypeError:
|
|
107
132
|
if type(other) is bool:
|
|
108
133
|
base_class = int
|
|
109
134
|
else:
|
|
110
|
-
msg = (
|
|
111
|
-
f"unsupported operand type(s) for |: '{type(self)}' and '{type(other)}'"
|
|
112
|
-
)
|
|
135
|
+
msg = f"unsupported operand type(s) for |: '{type(self)}' and '{type(other)}'"
|
|
113
136
|
raise TypeError(msg)
|
|
114
137
|
|
|
115
138
|
if issubclass(base_class, SBool):
|
|
@@ -121,14 +144,12 @@ class SBool(int):
|
|
|
121
144
|
|
|
122
145
|
def __xor__(self, other: int) -> int:
|
|
123
146
|
try:
|
|
124
|
-
base_class =
|
|
147
|
+
base_class = fca(type(self), type(other))
|
|
125
148
|
except TypeError:
|
|
126
149
|
if type(other) is bool:
|
|
127
150
|
base_class = int
|
|
128
151
|
else:
|
|
129
|
-
msg = (
|
|
130
|
-
f"unsupported operand type(s) for ^: '{type(self)}' and '{type(other)}'"
|
|
131
|
-
)
|
|
152
|
+
msg = f"unsupported operand type(s) for ^: '{type(self)}' and '{type(other)}'"
|
|
132
153
|
raise TypeError(msg)
|
|
133
154
|
|
|
134
155
|
if issubclass(base_class, SBool):
|
|
@@ -12,19 +12,33 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
"""
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
**Class TF_Bool**
|
|
17
|
+
|
|
18
|
+
Subclass of ``SBool`` whose truthy values and falsy values are
|
|
19
|
+
different distinct singleton subtypes.
|
|
20
|
+
|
|
21
|
+
This type can also do (non-shortcut) Boolean logic using Python
|
|
22
|
+
bitwise operators.
|
|
23
|
+
|
|
24
|
+
----
|
|
19
25
|
|
|
26
|
+
**Class T_Bool**
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
The subtype of ``TF_Bool`` which is always truthy.
|
|
29
|
+
|
|
30
|
+
----
|
|
31
|
+
|
|
32
|
+
**Class F_Bool**
|
|
33
|
+
|
|
34
|
+
The subtype of ``TF_Bool`` which is always falsy.
|
|
35
|
+
"""
|
|
22
36
|
|
|
23
37
|
import threading
|
|
24
38
|
from collections.abc import Hashable
|
|
25
39
|
from typing import cast, ClassVar, Final, final
|
|
26
|
-
from pythonic_fp.sentinels.novalue import NoValue
|
|
27
|
-
from
|
|
40
|
+
from pythonic_fp.gadgets.sentinels.novalue import NoValue
|
|
41
|
+
from .subtypable import SBool
|
|
28
42
|
|
|
29
43
|
__all__ = [
|
|
30
44
|
'TF_Bool',
|
|
@@ -39,22 +53,11 @@ _novalue = NoValue()
|
|
|
39
53
|
|
|
40
54
|
|
|
41
55
|
class TF_Bool(SBool):
|
|
42
|
-
"""
|
|
43
|
-
Truthy-Falsy Boolean
|
|
44
|
-
--------------------
|
|
45
|
-
|
|
46
|
-
Subclass of ``SBool`` whose truthy values and falsy values are
|
|
47
|
-
different singleton subtypes.
|
|
48
|
-
|
|
49
|
-
This type can also do (non-shortcut) Boolean logic using Python
|
|
50
|
-
bitwise operators.
|
|
51
|
-
"""
|
|
52
|
-
|
|
53
56
|
def __new__(cls, witness: object, flavor: Hashable = NoValue()) -> 'TF_Bool':
|
|
54
57
|
"""
|
|
55
58
|
:param witness: Determines which subtype, ``T_Bool`` or ``F_Bool`` is returned.
|
|
56
59
|
:param flavor: Ignored parameter, only two flavors, one truthy and one falsy.
|
|
57
|
-
:returns:
|
|
60
|
+
:returns: Either The singleton truthy or singleton falsy subtypes.
|
|
58
61
|
"""
|
|
59
62
|
if witness:
|
|
60
63
|
return T_Bool()
|
|
@@ -94,13 +97,6 @@ class TF_Bool(SBool):
|
|
|
94
97
|
|
|
95
98
|
@final
|
|
96
99
|
class T_Bool(TF_Bool):
|
|
97
|
-
"""
|
|
98
|
-
Truthy TF_Bool
|
|
99
|
-
--------------
|
|
100
|
-
|
|
101
|
-
The subtype of ``TF_Bool`` which is always truthy.
|
|
102
|
-
"""
|
|
103
|
-
|
|
104
100
|
_truthy: 'ClassVar[T_Bool | NoValue]' = _novalue
|
|
105
101
|
_lock: ClassVar[threading.Lock] = threading.Lock()
|
|
106
102
|
|
|
@@ -126,13 +122,6 @@ class T_Bool(TF_Bool):
|
|
|
126
122
|
|
|
127
123
|
@final
|
|
128
124
|
class F_Bool(TF_Bool):
|
|
129
|
-
"""
|
|
130
|
-
Falsy TF_Bool
|
|
131
|
-
-------------
|
|
132
|
-
|
|
133
|
-
The subtype of ``TF_Bool`` which is always falsy.
|
|
134
|
-
"""
|
|
135
|
-
|
|
136
125
|
_falsy: 'ClassVar[F_Bool | NoValue]' = _novalue
|
|
137
126
|
_lock: ClassVar[threading.Lock] = threading.Lock()
|
|
138
127
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from pythonic_fp.booleans.subtypable import SBool, TRUTH, LIE
|
|
16
|
-
from pythonic_fp.booleans.
|
|
16
|
+
from pythonic_fp.booleans.flavored import FBool, truthy, falsy
|
|
17
17
|
|
|
18
18
|
class TestBooleanBehaviors():
|
|
19
19
|
def test_bool(self) -> None:
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from pythonic_fp.booleans.
|
|
15
|
+
from pythonic_fp.booleans.flavored import FBool, truthy, falsy
|
|
16
16
|
from pythonic_fp.booleans.subtypable import TRUTH, LIE
|
|
17
17
|
|
|
18
18
|
t0_1 = FBool(1 == 1, 0)
|
{pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/tests/test_flavored_non_shortcut_logic.py
RENAMED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from pythonic_fp.booleans.subtypable import TRUTH, LIE
|
|
16
|
-
from pythonic_fp.booleans.
|
|
16
|
+
from pythonic_fp.booleans.flavored import FBool, truthy, falsy
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class TestBitwiseOperations():
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from pythonic_fp.booleans.
|
|
15
|
+
from pythonic_fp.booleans.flavored import FBool, truthy, falsy
|
|
16
16
|
from pythonic_fp.booleans.subtypable import SBool, TRUTH, LIE
|
|
17
17
|
|
|
18
18
|
fbt0_1 = FBool(1 == 1, 0)
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from pythonic_fp.booleans.subtypable import TRUTH, LIE
|
|
16
|
-
from pythonic_fp.booleans.
|
|
17
|
-
from pythonic_fp.booleans.
|
|
16
|
+
from pythonic_fp.booleans.truthy_falsy import TF_Boolean, TF_Bool, T_Bool, F_Bool
|
|
17
|
+
from pythonic_fp.booleans.truthy_falsy import ALWAYS, NEVER
|
|
18
18
|
|
|
19
19
|
false0: TF_Boolean = F_Bool('ignored', 'also ignored')
|
|
20
20
|
false1: TF_Boolean = TF_Bool(1 > 42)
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from pythonic_fp.booleans.subtypable import SBool
|
|
16
|
-
from pythonic_fp.booleans.
|
|
17
|
-
from pythonic_fp.booleans.
|
|
16
|
+
from pythonic_fp.booleans.flavored import FBool, truthy, falsy
|
|
17
|
+
from pythonic_fp.booleans.truthy_falsy import TF_Bool, T_Bool, F_Bool
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class TestInvert:
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from pythonic_fp.booleans.
|
|
16
|
-
from pythonic_fp.booleans.
|
|
15
|
+
from pythonic_fp.booleans.truthy_falsy import TF_Bool, TF_Boolean, T_Bool, F_Bool, ALWAYS, NEVER
|
|
16
|
+
from pythonic_fp.booleans.flavored import FBool, truthy, falsy
|
|
17
17
|
from pythonic_fp.booleans.subtypable import SBool, TRUTH, LIE
|
|
18
18
|
|
|
19
19
|
class TestBoolWithInt():
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
CHANGELOG
|
|
2
|
-
=========
|
|
3
|
-
|
|
4
|
-
PyPI pythonic-fp-booleans project.
|
|
5
|
-
|
|
6
|
-
Semantic Versioning
|
|
7
|
-
-------------------
|
|
8
|
-
|
|
9
|
-
Strict 3 digit semantic versioning adopted 2025-05-19.
|
|
10
|
-
|
|
11
|
-
- **MAJOR** version incremented for incompatible API changes
|
|
12
|
-
- **MINOR** version incremented for backward compatible added functionality
|
|
13
|
-
- **PATCH** version incremented for backward compatible bug fixes
|
|
14
|
-
|
|
15
|
-
See `Semantic Versioning 2.0.0 <https://semver.org>`_.
|
|
16
|
-
|
|
17
|
-
Releases and Important Milestones
|
|
18
|
-
---------------------------------
|
|
19
|
-
|
|
20
|
-
PyPI v1.1.1 - 2025-09-03
|
|
21
|
-
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
22
|
-
|
|
23
|
-
Only change was to give README.rst a final edit. Missed this on
|
|
24
|
-
the v1.1.0 release.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
PyPI v1.1.0 - 2025-09-02
|
|
28
|
-
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
29
|
-
|
|
30
|
-
First PyPI release as pythonic-fp-booleans.
|
|
31
|
-
|
|
32
|
-
- module booleans.subtypable
|
|
33
|
-
- package booleans.subtypes
|
|
34
|
-
|
|
35
|
-
- module booleans.subtypes.flavored
|
|
36
|
-
- module booleans.subtypes.truthy_falsy
|
|
37
|
-
|
|
38
|
-
Needs
|
|
39
|
-
|
|
40
|
-
- "pythonic-fp>=3.0.0" for gadgets
|
|
41
|
-
- "pythonic-fp-sentinels>=2.1.0",
|
|
42
|
-
|
|
43
|
-
Created pythonic-fp-boolean GitHub repo - 2025-08-06
|
|
44
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
45
|
-
|
|
46
|
-
Moved pythonic_fp.singletons.sbool -> pythonic_fp.booleans.sbool
|
|
@@ -1,99 +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
|
-
"""
|
|
16
|
-
Subtypable Boolean like classes
|
|
17
|
-
===============================
|
|
18
|
-
|
|
19
|
-
While still compatible with Python shortcut logic, these classes can
|
|
20
|
-
be non-shortcut logically composed with Python's bitwise operators.
|
|
21
|
-
These classes are implemented with the Singleton Pattern.
|
|
22
|
-
|
|
23
|
-
Covariant class hierarchy
|
|
24
|
-
-------------------------
|
|
25
|
-
|
|
26
|
-
.. graphviz::
|
|
27
|
-
|
|
28
|
-
digraph Booleans {
|
|
29
|
-
bgcolor="deepskyblue";
|
|
30
|
-
int -> bool;
|
|
31
|
-
int -> SBool;
|
|
32
|
-
SBool -> "FBool(h1)";
|
|
33
|
-
SBool -> "FBool(h2)";
|
|
34
|
-
SBool -> "FBool(h3)";
|
|
35
|
-
SBool -> TF_Bool;
|
|
36
|
-
TF_Bool -> T_Bool;
|
|
37
|
-
TF_Bool -> F_Bool;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
Contravariant non-shortcut "bitwise" operators
|
|
41
|
-
----------------------------------------------
|
|
42
|
-
|
|
43
|
-
+-------------------+--------+------------+
|
|
44
|
-
| Boolean operation | symbol | dunder |
|
|
45
|
-
+===================+========+============+
|
|
46
|
-
| not | ``~`` | __invert__ |
|
|
47
|
-
+-------------------+--------+------------+
|
|
48
|
-
| and | ``&`` | __and__ |
|
|
49
|
-
+-------------------+--------+------------+
|
|
50
|
-
| or | ``|`` | __or__ |
|
|
51
|
-
+-------------------+--------+------------+
|
|
52
|
-
| xor | ``^`` | __xor__ |
|
|
53
|
-
+-------------------+--------+------------+
|
|
54
|
-
|
|
55
|
-
These operators are contravariant, that is they will return
|
|
56
|
-
the instance of the latest common ancestor of their arguments.
|
|
57
|
-
More specifically, the instance returned will have the type
|
|
58
|
-
of the least upper bound in the inheritance graph of the classes
|
|
59
|
-
of the two arguments.
|
|
60
|
-
|
|
61
|
-
.. warning::
|
|
62
|
-
|
|
63
|
-
These "bitwise" operators could raise ``TypeError`` exceptions
|
|
64
|
-
when applied against an ``SBool`` and objects not descended
|
|
65
|
-
from ``int``.
|
|
66
|
-
|
|
67
|
-
Classes
|
|
68
|
-
-------
|
|
69
|
-
|
|
70
|
-
Class SBool
|
|
71
|
-
~~~~~~~~~~~
|
|
72
|
-
|
|
73
|
-
Base of the hierarchy.
|
|
74
|
-
|
|
75
|
-
Like Python's built-in ``bool``, ``SBool`` is a subclass of ``int``,
|
|
76
|
-
unlike ``bool``, class ``SBool`` can be further subclassed.
|
|
77
|
-
|
|
78
|
-
Class FBool
|
|
79
|
-
~~~~~~~~~~~
|
|
80
|
-
|
|
81
|
-
For when you need to deal with different "flavors" of the truth.
|
|
82
|
-
|
|
83
|
-
Each "flavor" corresponds to a hashable value. Instances of ``FBool``
|
|
84
|
-
are invariant in their flavor. Best to think of the "flavor" as an
|
|
85
|
-
index.
|
|
86
|
-
|
|
87
|
-
Class TF_Bool
|
|
88
|
-
~~~~~~~~~~~~~
|
|
89
|
-
|
|
90
|
-
Class ``TF_Bool`` consists of just two disjoint subclasses, each one
|
|
91
|
-
a singleton.
|
|
92
|
-
|
|
93
|
-
- class ``T_Bool`` is the always truthy ``TF_Bool`` subtype
|
|
94
|
-
- class ``F_Bool`` is the always falsy ``TF_Bool`` subtype
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
__author__ = 'Geoffrey R. Scheller'
|
|
98
|
-
__copyright__ = 'Copyright (c) 2025 Geoffrey R. Scheller'
|
|
99
|
-
__license__ = 'Apache License 2.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonic_fp_booleans-1.1.2 → pythonic_fp_booleans-2.1.0}/src/pythonic_fp/booleans/subtypable.pyi
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|