pythonic-fp-booleans 4.0.0__tar.gz → 4.1.1__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.
Files changed (42) hide show
  1. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/PKG-INFO +18 -26
  2. pythonic_fp_booleans-4.1.1/README.md +21 -0
  3. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/pyproject.toml +23 -17
  4. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/src/pythonic_fp/booleans/flavored.py +24 -23
  5. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/src/pythonic_fp/booleans/subtypable.py +38 -45
  6. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/src/pythonic_fp/booleans/truthy_falsy.py +24 -14
  7. pythonic_fp_booleans-4.0.0/.github/workflows/static.yml +0 -64
  8. pythonic_fp_booleans-4.0.0/.gitignore +0 -9
  9. pythonic_fp_booleans-4.0.0/CHANGELOG.rst +0 -132
  10. pythonic_fp_booleans-4.0.0/README.rst +0 -29
  11. pythonic_fp_booleans-4.0.0/docs/Makefile +0 -78
  12. pythonic_fp_booleans-4.0.0/docs/gen_conf.py +0 -110
  13. pythonic_fp_booleans-4.0.0/docs/requirements.txt +0 -2
  14. pythonic_fp_booleans-4.0.0/docs/source/_static/.gitkeep +0 -0
  15. pythonic_fp_booleans-4.0.0/docs/source/_static/custom.css +0 -3
  16. pythonic_fp_booleans-4.0.0/docs/source/_templates/.gitkeep +0 -0
  17. pythonic_fp_booleans-4.0.0/docs/source/api/flavored.rst +0 -4
  18. pythonic_fp_booleans-4.0.0/docs/source/api/index.rst +0 -20
  19. pythonic_fp_booleans-4.0.0/docs/source/api/subtypable.rst +0 -6
  20. pythonic_fp_booleans-4.0.0/docs/source/api/truthy_falsy.rst +0 -4
  21. pythonic_fp_booleans-4.0.0/docs/source/changelog.rst +0 -7
  22. pythonic_fp_booleans-4.0.0/docs/source/description.rst +0 -25
  23. pythonic_fp_booleans-4.0.0/docs/source/index.rst +0 -30
  24. pythonic_fp_booleans-4.0.0/docs/source/releases.rst +0 -28
  25. pythonic_fp_booleans-4.0.0/docs/source/usage.rst +0 -63
  26. pythonic_fp_booleans-4.0.0/src/pythonic_fp/booleans/__init__.pyi +0 -0
  27. pythonic_fp_booleans-4.0.0/src/pythonic_fp/booleans/flavored.pyi +0 -16
  28. pythonic_fp_booleans-4.0.0/src/pythonic_fp/booleans/subtypable.pyi +0 -22
  29. pythonic_fp_booleans-4.0.0/src/pythonic_fp/booleans/truthy_falsy.pyi +0 -25
  30. pythonic_fp_booleans-4.0.0/tests/test_bool_vs_fbool.py +0 -195
  31. pythonic_fp_booleans-4.0.0/tests/test_bool_vs_sbool.py +0 -160
  32. pythonic_fp_booleans-4.0.0/tests/test_flavored.py +0 -157
  33. pythonic_fp_booleans-4.0.0/tests/test_flavored_non_shortcut_logic.py +0 -136
  34. pythonic_fp_booleans-4.0.0/tests/test_flavored_sbool.py +0 -167
  35. pythonic_fp_booleans-4.0.0/tests/test_subtypable_non_shortcut_logic.py +0 -83
  36. pythonic_fp_booleans-4.0.0/tests/test_true_false.py +0 -189
  37. pythonic_fp_booleans-4.0.0/tests/test_true_false_non_shortcut_logic.py +0 -121
  38. pythonic_fp_booleans-4.0.0/tests/test_typing.py +0 -167
  39. pythonic_fp_booleans-4.0.0/tests/test_variance.py +0 -216
  40. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/LICENSE +0 -0
  41. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/src/pythonic_fp/booleans/__init__.py +0 -0
  42. {pythonic_fp_booleans-4.0.0 → pythonic_fp_booleans-4.1.1}/src/pythonic_fp/booleans/py.typed +0 -0
@@ -1,11 +1,11 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: pythonic-fp-booleans
3
- Version: 4.0.0
4
- Summary: Booleans
3
+ Version: 4.1.1
4
+ Summary: True Booleans which are subtypable.
5
5
  Keywords: booleans,subtypable
6
6
  Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
7
7
  Requires-Python: >=3.13
8
- Description-Content-Type: text/x-rst
8
+ Description-Content-Type: text/markdown
9
9
  Classifier: Development Status :: 4 - Beta
10
10
  Classifier: Framework :: Pytest
11
11
  Classifier: Intended Audience :: Developers
@@ -15,39 +15,31 @@ Classifier: Programming Language :: Python :: 3.14
15
15
  Classifier: Typing :: Typed
16
16
  License-File: LICENSE
17
17
  Requires-Dist: pythonic-fp-gadgets>=4.0.2
18
- Requires-Dist: pytest>=8.4.1 ; extra == "test"
19
- Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-booleans/blob/main/CHANGELOG.rst
20
- Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/projects/booleans.html
18
+ Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-booleans/blob/main/CHANGELOG.md
19
+ Project-URL: Documentation, https://grscheller.github.io/pythonic-fp-booleans/release/html/
21
20
  Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/
22
21
  Project-URL: Source, https://github.com/grscheller/pythonic-fp-booleans
23
- Provides-Extra: test
22
+ Import-Name: pythonic_fp.booleans
23
+ Import-Namespace: pythonic_fp
24
24
 
25
- Pythonic FP - Booleans
26
- ======================
27
-
28
- PyPI project
29
- `pythonic-fp-booleans
30
- <https://pypi.org/project/pythonic-fp-booleans>`_.
25
+ # Pythonic FP - Booleans
31
26
 
32
27
  Subtypable Boolean like classes.
33
28
 
34
- While still compatible with Python shortcut logic, these singleton classes
35
- can be non-shortcut logically composed with Python’s bitwise operators.
36
-
29
+ PyPI project
30
+ [pythonic-fp-booleans](https://pypi.org/project/pythonic-fp-booleans).
37
31
  Part of the
38
- `pythonic-fp
39
- <https://grscheller.github.io/pythonic-fp/>`_
32
+ [pythonic-fp](https://grscheller.github.io/pythonic-fp/)
40
33
  PyPI projects.
41
34
 
42
- Documentation
43
- -------------
35
+ ## Description
44
36
 
45
- Documentation and other links for this project are hosted on
46
- `GitHub Pages
47
- <https://grscheller.github.io/pythonic-fp/projects/booleans.html>`_.
37
+ While still compatible with Python shortcut logic, these singleton
38
+ classes can be non-shortcut logically composed with Python’s bitwise
39
+ operators. Unlike Python booleans which bitwise compose as integers,
40
+ these compose as true Booleans in a contravariant way.
48
41
 
49
- Copyright and License
50
- ---------------------
42
+ ## Copyright and License
51
43
 
52
44
  Copyright (c) 2025-2026 Geoffrey R. Scheller. Licensed under the Apache
53
45
  License, Version 2.0. See the LICENSE file for details.
@@ -0,0 +1,21 @@
1
+ # Pythonic FP - Booleans
2
+
3
+ Subtypable Boolean like classes.
4
+
5
+ PyPI project
6
+ [pythonic-fp-booleans](https://pypi.org/project/pythonic-fp-booleans).
7
+ Part of the
8
+ [pythonic-fp](https://grscheller.github.io/pythonic-fp/)
9
+ PyPI projects.
10
+
11
+ ## Description
12
+
13
+ While still compatible with Python shortcut logic, these singleton
14
+ classes can be non-shortcut logically composed with Python’s bitwise
15
+ operators. Unlike Python booleans which bitwise compose as integers,
16
+ these compose as true Booleans in a contravariant way.
17
+
18
+ ## Copyright and License
19
+
20
+ Copyright (c) 2025-2026 Geoffrey R. Scheller. Licensed under the Apache
21
+ License, Version 2.0. See the LICENSE file for details.
@@ -4,8 +4,8 @@ build-backend = "flit_core.buildapi"
4
4
 
5
5
  [project]
6
6
  name = "pythonic-fp-booleans"
7
- version = "4.0.0"
8
- readme = "README.rst"
7
+ version = "4.1.1"
8
+ readme = "README.md"
9
9
  requires-python = ">=3.13"
10
10
  authors = [
11
11
  { name = "Geoffrey R. Scheller", email = "geoffrey@scheller.com" },
@@ -26,15 +26,22 @@ classifiers = [
26
26
  dependencies = [
27
27
  "pythonic-fp-gadgets>=4.0.2",
28
28
  ]
29
- dynamic = ["description"]
29
+ description = "True Booleans which are subtypable."
30
30
 
31
31
  [project.urls]
32
- Changelog = "https://github.com/grscheller/pythonic-fp-booleans/blob/main/CHANGELOG.rst"
33
- Documentation = "https://grscheller.github.io/pythonic-fp/projects/booleans.html"
32
+ Changelog = "https://github.com/grscheller/pythonic-fp-booleans/blob/main/CHANGELOG.md"
33
+ Documentation ="https://grscheller.github.io/pythonic-fp-booleans/release/html/"
34
34
  Homepage = "https://grscheller.github.io/pythonic-fp/"
35
35
  Source = "https://github.com/grscheller/pythonic-fp-booleans"
36
36
 
37
- [project.optional-dependencies]
37
+ [dependency-groups]
38
+ docs = [
39
+ "furo>=2025.12.19",
40
+ "sphinx>=9.1",
41
+ ]
42
+ pub = [
43
+ "flit",
44
+ ]
38
45
  test = [
39
46
  "pytest>=8.4.1",
40
47
  ]
@@ -42,6 +49,12 @@ test = [
42
49
  [tool.flit.module]
43
50
  name = "pythonic_fp.booleans"
44
51
 
52
+ [tool.flit.sdist]
53
+ exclude = [
54
+ "docs/",
55
+ "tests/",
56
+ ]
57
+
45
58
  [tool.mypy]
46
59
  explicit_package_bases = true
47
60
  local_partial_types = true
@@ -50,23 +63,17 @@ warn_redundant_casts = true
50
63
  warn_return_any = true
51
64
  warn_unused_configs = true
52
65
 
53
- [tool.pylsp-mypy]
54
- enabled = true
55
- live-mode = true
56
- dmypy = false
57
- strict = true
58
- report_progress = true
59
-
60
66
  [tool.pytest]
61
- addopts = [
62
- "-ra",
63
- ]
67
+ addopts = ["-ra"]
64
68
  consider_namespace_packages = true
65
69
  testpaths = ["tests/"]
66
70
 
67
71
  [tool.ruff]
68
72
  target-version = "py314"
69
73
 
74
+ [tool.ruff.lint]
75
+ ignore = ["RUF022", "E741"]
76
+
70
77
  [tool.ruff.lint.flake8-quotes]
71
78
  docstring-quotes = "double"
72
79
 
@@ -75,7 +82,6 @@ docstring-quotes = "double"
75
82
  "E731",
76
83
  "C901",
77
84
  ]
78
- "**/*.py" = ["E741"]
79
85
 
80
86
  [tool.ruff.format]
81
87
  quote-style = "single"
@@ -1,4 +1,4 @@
1
- # Copyright 2023-2025 Geoffrey R. Scheller
1
+ # Copyright 2023-2026 Geoffrey R. Scheller
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import threading
16
15
  from collections.abc import Hashable
17
- from typing import ClassVar, final, Self
16
+ from threading import Lock
17
+ from typing import ClassVar, Self, final
18
+
18
19
  from .subtypable import SBool
19
20
 
20
21
  __all__ = ['FBool', 'truthy', 'falsy']
@@ -25,8 +26,8 @@ class FBool(SBool):
25
26
  """
26
27
  .. admonition:: Favored Booleans
27
28
 
28
- When different flavors of the truth matter. Each FBool is
29
- an SBool subtype corresponding to a hashable flavor.
29
+ When different flavors of the truth matter. Each ``FBool`` is
30
+ an ``SBool`` subtype corresponding to a hashable flavor.
30
31
 
31
32
  .. warning::
32
33
 
@@ -36,11 +37,11 @@ class FBool(SBool):
36
37
 
37
38
  """
38
39
 
39
- _falsy_dict: 'ClassVar[dict[Hashable, FBool]]' = {}
40
- _falsy_dict_lock: ClassVar[threading.Lock] = threading.Lock()
40
+ _falsy_dict: ClassVar[dict[Hashable, FBool]] = {}
41
+ _falsy_dict_lock: ClassVar[Lock] = Lock()
41
42
 
42
- _truthy_dict: 'ClassVar[dict[Hashable, FBool]]' = {}
43
- _truthy_dict_lock: ClassVar[threading.Lock] = threading.Lock()
43
+ _truthy_dict: ClassVar[dict[Hashable, FBool]] = {}
44
+ _truthy_dict_lock: ClassVar[Lock] = Lock()
44
45
 
45
46
  def __new__(cls, witness: object, flavor: Hashable) -> Self:
46
47
  """
@@ -123,17 +124,17 @@ class FBool(SBool):
123
124
 
124
125
  Create strings of the form
125
126
 
126
- - `FBool(True, repr_flavor)'
127
- - `FBool(False, repr_flavor)'
127
+ - ``FBool(True, repr_flavor)``
128
+ - ``FBool(False, repr_flavor)``
128
129
 
129
- Where repr_flavor = repr(self.flavor())
130
+ Where ``repr_flavor = repr(self.flavor())``
130
131
 
131
132
  :returns: A String to reproduce the flavored boolean.
132
133
 
133
134
  """
134
135
  if self:
135
- return f'FBool(True, {repr(self._flavor)})'
136
- return f'FBool(False, {repr(self._flavor)})'
136
+ return f'FBool(True, {self._flavor!r})'
137
+ return f'FBool(False, {self._flavor!r})'
137
138
 
138
139
  def __str__(self) -> str:
139
140
  """
@@ -141,23 +142,23 @@ class FBool(SBool):
141
142
 
142
143
  Create strings of the form
143
144
 
144
- - `FBool(True, str_flavor)'
145
- - `FBool(False, str_flavor)'
145
+ - ``FBool(True, str_flavor)``
146
+ - ``FBool(False, str_flavor)``
146
147
 
147
- Where str_flavor = str(self.flavor())
148
+ Where ``str_flavor = str(self.flavor())``
148
149
 
149
- :returns: A String to meaningful to an end user.
150
+ :returns: A String meaningful to an end user.
150
151
 
151
152
  """
152
153
  if self:
153
- return f'FBool(True, {str(self._flavor)})'
154
- return f'FBool(False, {str(self._flavor)})'
154
+ return f'FBool(True, {self._flavor!s})'
155
+ return f'FBool(False, {self._flavor!s})'
155
156
 
156
157
  def flavor(self) -> Hashable:
157
158
  """
158
159
  .. admonition:: flavor
159
160
 
160
- Get the flavor of the FBool, a hashable value.
161
+ Get the flavor of the ``FBool``, a hashable value.
161
162
 
162
163
  :returns: The flavor.
163
164
 
@@ -169,7 +170,7 @@ def truthy(flavor: Hashable) -> FBool:
169
170
  """
170
171
  .. admonition:: function truthy
171
172
 
172
- Returns the truthy singleton FBool of a particular flavor.
173
+ Returns the truthy singleton ``FBool`` of a particular flavor.
173
174
 
174
175
  :param flavor: Hashable value to determine which
175
176
  singleton flavor to return.
@@ -183,7 +184,7 @@ def falsy(flavor: Hashable) -> FBool:
183
184
  """
184
185
  .. admonition:: Function falsy
185
186
 
186
- Returns the falsy singleton FBool of a particular flavor.
187
+ Returns the falsy singleton ``FBool`` of a particular flavor.
187
188
 
188
189
  :param flavor: Hashable value to determine which
189
190
  singleton flavor to return.
@@ -12,47 +12,38 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import threading
16
15
  from collections.abc import Hashable
17
- from typing import cast, ClassVar, Final, overload, Self
16
+ from threading import Lock
17
+ from typing import ClassVar, Final, Self, cast, overload
18
+
18
19
  from pythonic_fp.gadgets import first_common_ancestor as fca
19
20
  from pythonic_fp.gadgets.sentinels.novalue import NoValue
20
21
 
21
22
  __all__ = ['SBool', 'TRUTH', 'LIE']
22
23
 
24
+ no_value = NoValue()
23
25
 
24
26
  class SBool(int):
25
27
  """
26
- .. depricated:: 3.1.0
27
-
28
- Will re-architecture the entire pythonic-fp-booleans effort for
29
- the PyPI version 4.0.0 release.
30
-
31
- Going forward, subtypable Booleans will no longer be a subclass
32
- of int. The maintainer has found this approach is a maintenance
33
- burden. Maintainer also feels the current version is somewhat
34
- "unpythonic" in the typing sophistication it requires for
35
- end user code to leverage the project.
36
-
37
28
  .. admonition:: Subtypable Boolean
38
29
 
39
- Like Python's built in bool, class SBool is a singleton subclass
40
- of int. Unlike bool, it can be further subclassed.
30
+ Like Python's built in ``bool``, class ``SBool`` is a singleton
31
+ subclass of ``int``. Unlike ``bool``, it can be further subclassed.
41
32
 
42
- SBool and its subtypes can also do (non-shortcut) Boolean logic
33
+ ``SBool`` and its subtypes can also do (non-shortcut) Boolean logic
43
34
  using Python bitwise operators.
44
35
 
45
- +-------------------+--------+------------+
46
- | Boolean operation | symbol | dunder |
47
- +===================+========+============+
48
- | not | ``~`` | __invert__ |
49
- +-------------------+--------+------------+
50
- | and | ``&`` | __and__ |
51
- +-------------------+--------+------------+
52
- | or | ``|`` | __or__ |
53
- +-------------------+--------+------------+
54
- | xor | ``^`` | __xor__ |
55
- +-------------------+--------+------------+
36
+ +-------------------+--------+----------------+
37
+ | Boolean operation | symbol | dunder |
38
+ +===================+========+================+
39
+ | not | ``~`` | ``__invert__`` |
40
+ +-------------------+--------+----------------+
41
+ | and | ``&`` | ``__and__`` |
42
+ +-------------------+--------+----------------+
43
+ | or | ``|`` | ``__or__`` |
44
+ +-------------------+--------+----------------+
45
+ | xor | ``^`` | ``__xor__`` |
46
+ +-------------------+--------+----------------+
56
47
 
57
48
  While compatible with Python short-cut logic, , the not
58
49
  operator unfortunately always returns a bool.
@@ -78,28 +69,30 @@ class SBool(int):
78
69
 
79
70
  """
80
71
 
81
- _falsy: 'ClassVar[SBool | NoValue]' = NoValue()
82
- _falsy_lock: ClassVar[threading.Lock] = threading.Lock()
72
+ _falsy: ClassVar[SBool | NoValue] = NoValue()
73
+ _falsy_lock: ClassVar[Lock] = Lock()
83
74
 
84
- _truthy: 'ClassVar[SBool | NoValue]' = NoValue()
85
- _truthy_lock: ClassVar[threading.Lock] = threading.Lock()
75
+ _truthy: ClassVar[SBool | NoValue] = NoValue()
76
+ _truthy_lock: ClassVar[Lock] = Lock()
86
77
 
87
78
  @overload
88
79
  def __new__(cls, witness: object) -> Self: ...
89
80
  @overload
90
- def __new__(cls, witness: object, flavor: Hashable | NoValue = NoValue()) -> Self: ...
81
+ def __new__(
82
+ cls, witness: object, flavor: Hashable | NoValue = no_value
83
+ ) -> Self: ...
91
84
 
92
85
  def __new__(
93
86
  cls,
94
87
  witness: object,
95
- flavor: Hashable | NoValue = NoValue(),
96
- ) -> 'SBool':
88
+ flavor: Hashable | NoValue = no_value,
89
+ ) -> Self:
97
90
  """
98
91
  .. admonition:: new
99
92
 
100
- :param witness: Determines truthiness of the SBool.
101
- :param flavor: Ignored
102
- :returns: The truthy or falsy SBool class instance.
93
+ :param witness: Determines truthiness of the ``SBool``.
94
+ :param flavor: Ignored
95
+ :returns: The truthy or falsy ``SBool`` class instance.
103
96
 
104
97
  """
105
98
  if witness:
@@ -107,13 +100,13 @@ class SBool(int):
107
100
  with cls._truthy_lock:
108
101
  if cls._truthy is NoValue():
109
102
  cls._truthy = super().__new__(cls, 1)
110
- return cast(SBool, cls._truthy)
103
+ return cast(Self, cls._truthy)
111
104
  else:
112
105
  if cls._falsy is NoValue():
113
106
  with cls._falsy_lock:
114
107
  if cls._falsy is NoValue():
115
108
  cls._falsy = super().__new__(cls, 0)
116
- return cast(SBool, cls._falsy)
109
+ return cast(Self, cls._falsy)
117
110
 
118
111
  @overload
119
112
  def __init__(self, witness: object) -> None: ...
@@ -123,14 +116,14 @@ class SBool(int):
123
116
  def __init__(
124
117
  self,
125
118
  witness: object = False,
126
- flavor: Hashable | NoValue = NoValue(),
119
+ flavor: Hashable | NoValue = no_value,
127
120
  ) -> None:
128
121
  """
129
122
  .. admonition:: init
130
123
 
131
- :param witness: Determines the truthiness of the SBool.
132
- :param flavor: Ignored by SBool, here only for support the
133
- Liskov Substitution Principle.
124
+ :param witness: Determines the truthiness of the ``SBool``.
125
+ :param flavor: Ignored by ``SBool``, here only to support
126
+ the Liskov Substitution Principle.
134
127
  """
135
128
  self._flavor: Hashable | NoValue = NoValue()
136
129
 
@@ -213,7 +206,7 @@ class SBool(int):
213
206
  - 'SBool(True)' if truthy
214
207
  - 'SBool(False)' if falsy
215
208
 
216
- :returns: A string to reproduce the SBool.
209
+ :returns: A string to reproduce the ``SBool``.
217
210
 
218
211
  """
219
212
  if self:
@@ -240,7 +233,7 @@ TRUTH: Final[SBool] = SBool(True)
240
233
  """
241
234
  .. admonition:: TRUTH
242
235
 
243
- :var TRUTH: The truthy singleton of type SBool.
236
+ :var TRUTH: The truthy singleton of type ``SBool``.
244
237
 
245
238
  """
246
239
 
@@ -12,10 +12,12 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import threading
16
15
  from collections.abc import Hashable
17
- from typing import cast, ClassVar, Final, Self
16
+ from threading import Lock
17
+ from typing import ClassVar, Final, Self, cast
18
+
18
19
  from pythonic_fp.gadgets.sentinels.novalue import NoValue
20
+
19
21
  from .subtypable import SBool
20
22
 
21
23
  __all__ = [
@@ -55,10 +57,12 @@ class TF_Bool(SBool):
55
57
 
56
58
  """
57
59
 
60
+ no_value = NoValue()
61
+
58
62
  def __new__(
59
63
  cls,
60
64
  witness: object,
61
- flavor: Hashable = NoValue(),
65
+ flavor: Hashable = no_value,
62
66
  ) -> Self:
63
67
  """
64
68
  .. admonition:: new
@@ -114,13 +118,16 @@ class T_Bool(TF_Bool):
114
118
  A distinct type from F_Bool.
115
119
 
116
120
  """
117
- _truthy: 'ClassVar[T_Bool | NoValue]' = NoValue()
118
- _lock: ClassVar[threading.Lock] = threading.Lock()
121
+
122
+ no_value = NoValue()
123
+
124
+ _truthy: ClassVar[T_Bool | NoValue] = no_value
125
+ _lock: ClassVar[Lock] = Lock()
119
126
 
120
127
  def __new__(
121
128
  cls,
122
- witness: object = NoValue(),
123
- flavor: Hashable | NoValue = NoValue(),
129
+ witness: object = no_value,
130
+ flavor: Hashable | NoValue = no_value,
124
131
  ) -> Self:
125
132
  """
126
133
  .. admonition:: new
@@ -130,9 +137,9 @@ class T_Bool(TF_Bool):
130
137
  :returns: The truthy T_Bool singleton instance.
131
138
 
132
139
  """
133
- if cls._truthy is NoValue():
140
+ if cls._truthy is (no_value := NoValue()):
134
141
  with cls._lock:
135
- if cls._truthy is NoValue():
142
+ if cls._truthy is no_value:
136
143
  cls._truthy = super(SBool, cls).__new__(cls, 1)
137
144
  return cast(Self, cls._truthy)
138
145
 
@@ -162,13 +169,16 @@ class F_Bool(TF_Bool):
162
169
  A distinct type from T_Bool.
163
170
 
164
171
  """
165
- _falsy: 'ClassVar[F_Bool | NoValue]' = NoValue()
166
- _lock: ClassVar[threading.Lock] = threading.Lock()
172
+
173
+ no_value = NoValue()
174
+
175
+ _falsy: ClassVar[F_Bool | NoValue] = no_value
176
+ _lock: ClassVar[Lock] = Lock()
167
177
 
168
178
  def __new__(
169
179
  cls,
170
180
  witness: object = NoValue(),
171
- flavor: Hashable | NoValue = NoValue(),
181
+ flavor: Hashable | NoValue = no_value,
172
182
  ) -> Self:
173
183
  """
174
184
  .. admonition:: new
@@ -178,9 +188,9 @@ class F_Bool(TF_Bool):
178
188
  :returns: The falsy F_Bool singleton instance.
179
189
 
180
190
  """
181
- if cls._falsy is NoValue():
191
+ if cls._falsy is (no_value := NoValue()):
182
192
  with cls._lock:
183
- if cls._falsy is NoValue():
193
+ if cls._falsy is no_value:
184
194
  cls._falsy = super(SBool, cls).__new__(cls, 0)
185
195
  return cast(Self, cls._falsy)
186
196
 
@@ -1,64 +0,0 @@
1
- name: Build and Deploy Furo Themed Sphinx Documentation
2
-
3
- on:
4
- push:
5
- branches: ["main"]
6
- workflow_dispatch:
7
-
8
- env:
9
- RELEASE: '4.0.0'
10
- DEVEL: '4.0.1'
11
- PYTHON: '3.14'
12
-
13
- permissions:
14
- contents: read
15
- pages: write
16
- id-token: write
17
-
18
- concurrency:
19
- group: "pages"
20
- cancel-in-progress: false
21
-
22
- jobs:
23
- deploy:
24
- runs-on: ubuntu-latest
25
- environment:
26
- name: github-pages
27
- url: ${{ steps.deployment.outputs.page_url }}
28
- steps:
29
- - name: Checkout
30
- uses: actions/checkout@v6
31
-
32
- - name: Select Python
33
- uses: actions/setup-python@v6
34
- with:
35
- python-version: ${{ env.PYTHON }}
36
-
37
- - name: Install Sphinx Dependencies
38
- run: |
39
- pip install -r docs/requirements.txt
40
- sudo apt-get install -y graphviz
41
-
42
- - name: Build Release Docs
43
- run: |
44
- pip install pythonic-fp-booleans
45
- docs/gen_conf.py release ${{ env.RELEASE }} Booleans booleans > docs/source/conf.py
46
- sphinx-build -M html docs/source docs/build/release
47
-
48
- - name: Build Development Docs
49
- run: |
50
- pip install -e .
51
- docs/gen_conf.py devel ${{ env.DEVEL }} Booleans booleans > docs/source/conf.py
52
- sphinx-build -M html docs/source docs/build/development
53
-
54
- - name: Setup Pages
55
- uses: actions/configure-pages@v6
56
-
57
- - name: Upload Artifact
58
- uses: actions/upload-pages-artifact@v5
59
- with:
60
- path: docs/build
61
-
62
- - name: Deploy to GitHub Pages
63
- uses: actions/deploy-pages@v5
64
- id: deployment
@@ -1,9 +0,0 @@
1
- # Minimal version - only add to when necessary
2
- **/__pycache__/
3
- dist/
4
- docs/build/
5
- docs/source/conf.py
6
- **/.dmypy.json
7
- **/.mypy_cache/
8
- **/.pytest_cache/
9
- **/.ruff_cache