optionz 0.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.
- optionz-0.1.0/.github/workflows/publish.yml +35 -0
- optionz-0.1.0/.gitignore +11 -0
- optionz-0.1.0/.python-version +1 -0
- optionz-0.1.0/LICENSE +21 -0
- optionz-0.1.0/PKG-INFO +83 -0
- optionz-0.1.0/README.md +62 -0
- optionz-0.1.0/docs/Makefile +20 -0
- optionz-0.1.0/docs/make.bat +35 -0
- optionz-0.1.0/docs/source/api.rst +40 -0
- optionz-0.1.0/docs/source/conf.py +37 -0
- optionz-0.1.0/docs/source/development.rst +59 -0
- optionz-0.1.0/docs/source/index.rst +21 -0
- optionz-0.1.0/opt.py +582 -0
- optionz-0.1.0/pyproject.toml +57 -0
- optionz-0.1.0/tests/test_api.py +10 -0
- optionz-0.1.0/tests/type_checks.py +96 -0
- optionz-0.1.0/tests/type_errors.py +0 -0
- optionz-0.1.0/uv.lock +920 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# $schema=https://www.schemastore.org/github-workflow.json
|
|
2
|
+
on:
|
|
3
|
+
release:
|
|
4
|
+
types:
|
|
5
|
+
- created
|
|
6
|
+
push:
|
|
7
|
+
tags:
|
|
8
|
+
- "v*.*.*"
|
|
9
|
+
|
|
10
|
+
name: release
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
pypi-publish:
|
|
14
|
+
name: upload release to PyPI
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment: pypi
|
|
17
|
+
permissions:
|
|
18
|
+
id-token: write
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout code
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v3
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
|
|
28
|
+
- name: Set up Python
|
|
29
|
+
run: uv python install
|
|
30
|
+
|
|
31
|
+
- name: Build package distributions
|
|
32
|
+
run: uv build
|
|
33
|
+
|
|
34
|
+
- name: Publish to PyPI
|
|
35
|
+
run: uv publish
|
optionz-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
optionz-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Fábio Macêdo Mendes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
optionz-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: optionz
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Some utility functions for Optional values.
|
|
5
|
+
Project-URL: Homepage, http://github.com/fabiomacedomendes/optionz
|
|
6
|
+
Project-URL: Repository, http://github.com/fabiomacedomendes/optionz
|
|
7
|
+
Author-email: Fábio Macêdo Mendes <fabiomacedomendes@gmail.com>
|
|
8
|
+
Maintainer-email: Fábio Macêdo Mendes <fabiomacedomendes@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.13
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Optionz
|
|
23
|
+
|
|
24
|
+
A nullable type is needed when there can be an absence of a value. Python uses
|
|
25
|
+
`None` to represent the empty value and `Optional[T]`, i.e., `T | None` to
|
|
26
|
+
represent a nullable `T`. The other option is to use exceptions, but they are
|
|
27
|
+
not expressed as values in the type system, which can be brittle and error-prone.
|
|
28
|
+
|
|
29
|
+
Python approach is a compromise between the "million dollar mistake",
|
|
30
|
+
in which `null` is a valid member of every type and the more structured
|
|
31
|
+
`Maybe[T]`, that models nullables as a tagged union of `Just[T]` and `Nothing`.
|
|
32
|
+
|
|
33
|
+
This library provides some utility functions for working with `Optional` values
|
|
34
|
+
in a more functional style, inspired by the `Maybe` monad in Haskell and Rust's
|
|
35
|
+
equivalent `Option` type.
|
|
36
|
+
|
|
37
|
+
The main philosophy is that we *do not* want to introduce a new type like
|
|
38
|
+
[returns](https://returns.readthedocs.io/) and other similar libraries.
|
|
39
|
+
Instead, we want to provide a similar functionality using plain `Optional` values
|
|
40
|
+
so that your code can adopt it incrementally without feeling like an alien in
|
|
41
|
+
the Python ecosystem.
|
|
42
|
+
|
|
43
|
+
As much as I like functional programming and the `Maybe` monad, I think Python's
|
|
44
|
+
approach is fine and offers most of the same static guarantees. The crucial
|
|
45
|
+
difference is that `Maybe` is a **tagged union** of two types and Python's
|
|
46
|
+
`Optional` is a **union of sets**. They behave mostly the same, but the latter do
|
|
47
|
+
not allow nesting: `Optional[Optional[T]]` flattens to `Optional[T]`, while
|
|
48
|
+
`Maybe[Maybe[T]]` is a whole new type. This is a difference that rarely
|
|
49
|
+
matters in practice, and I don't any anyone is clearly superior to the other.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
Install Optionz using pip/uv/poetry whatever you like. For example:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install optionz
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Optionz consists of a single file, so you can also just copy `opt.py` to your
|
|
61
|
+
project and import it from there. It do not define any new type so there is
|
|
62
|
+
no conflict with code that import vs ones that vendorize it.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
Import `opt` and use the functions as needed.
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import opt
|
|
71
|
+
|
|
72
|
+
opt.unwrap(42) # 42
|
|
73
|
+
opt.unwrap(None) # raises ValueError
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Documentation
|
|
77
|
+
|
|
78
|
+
The documentation is available at https://optionz.rtfd.io/ and includes more
|
|
79
|
+
examples and explanations of the functions provided by the library.
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
Optionz is licensed under the MIT License. See [LICENSE](LICENSE) for more details.
|
optionz-0.1.0/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Optionz
|
|
2
|
+
|
|
3
|
+
A nullable type is needed when there can be an absence of a value. Python uses
|
|
4
|
+
`None` to represent the empty value and `Optional[T]`, i.e., `T | None` to
|
|
5
|
+
represent a nullable `T`. The other option is to use exceptions, but they are
|
|
6
|
+
not expressed as values in the type system, which can be brittle and error-prone.
|
|
7
|
+
|
|
8
|
+
Python approach is a compromise between the "million dollar mistake",
|
|
9
|
+
in which `null` is a valid member of every type and the more structured
|
|
10
|
+
`Maybe[T]`, that models nullables as a tagged union of `Just[T]` and `Nothing`.
|
|
11
|
+
|
|
12
|
+
This library provides some utility functions for working with `Optional` values
|
|
13
|
+
in a more functional style, inspired by the `Maybe` monad in Haskell and Rust's
|
|
14
|
+
equivalent `Option` type.
|
|
15
|
+
|
|
16
|
+
The main philosophy is that we *do not* want to introduce a new type like
|
|
17
|
+
[returns](https://returns.readthedocs.io/) and other similar libraries.
|
|
18
|
+
Instead, we want to provide a similar functionality using plain `Optional` values
|
|
19
|
+
so that your code can adopt it incrementally without feeling like an alien in
|
|
20
|
+
the Python ecosystem.
|
|
21
|
+
|
|
22
|
+
As much as I like functional programming and the `Maybe` monad, I think Python's
|
|
23
|
+
approach is fine and offers most of the same static guarantees. The crucial
|
|
24
|
+
difference is that `Maybe` is a **tagged union** of two types and Python's
|
|
25
|
+
`Optional` is a **union of sets**. They behave mostly the same, but the latter do
|
|
26
|
+
not allow nesting: `Optional[Optional[T]]` flattens to `Optional[T]`, while
|
|
27
|
+
`Maybe[Maybe[T]]` is a whole new type. This is a difference that rarely
|
|
28
|
+
matters in practice, and I don't any anyone is clearly superior to the other.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
Install Optionz using pip/uv/poetry whatever you like. For example:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install optionz
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Optionz consists of a single file, so you can also just copy `opt.py` to your
|
|
40
|
+
project and import it from there. It do not define any new type so there is
|
|
41
|
+
no conflict with code that import vs ones that vendorize it.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
Import `opt` and use the functions as needed.
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import opt
|
|
50
|
+
|
|
51
|
+
opt.unwrap(42) # 42
|
|
52
|
+
opt.unwrap(None) # raises ValueError
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Documentation
|
|
56
|
+
|
|
57
|
+
The documentation is available at https://optionz.rtfd.io/ and includes more
|
|
58
|
+
examples and explanations of the functions provided by the library.
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
Optionz is licensed under the MIT License. See [LICENSE](LICENSE) for more details.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
# You can set these variables from the command line, and also
|
|
5
|
+
# from the environment for the first two.
|
|
6
|
+
SPHINXOPTS ?=
|
|
7
|
+
SPHINXBUILD ?= uv run sphinx-build
|
|
8
|
+
SOURCEDIR = source
|
|
9
|
+
BUILDDIR = build
|
|
10
|
+
|
|
11
|
+
# Put it first so that "make" without argument is like "make help".
|
|
12
|
+
help:
|
|
13
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
14
|
+
|
|
15
|
+
.PHONY: help Makefile
|
|
16
|
+
|
|
17
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
18
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
19
|
+
%: Makefile
|
|
20
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@ECHO OFF
|
|
2
|
+
|
|
3
|
+
pushd %~dp0
|
|
4
|
+
|
|
5
|
+
REM Command file for Sphinx documentation
|
|
6
|
+
|
|
7
|
+
if "%SPHINXBUILD%" == "" (
|
|
8
|
+
set SPHINXBUILD=sphinx-build
|
|
9
|
+
)
|
|
10
|
+
set SOURCEDIR=source
|
|
11
|
+
set BUILDDIR=build
|
|
12
|
+
|
|
13
|
+
%SPHINXBUILD% >NUL 2>NUL
|
|
14
|
+
if errorlevel 9009 (
|
|
15
|
+
echo.
|
|
16
|
+
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
|
17
|
+
echo.installed, then set the SPHINXBUILD environment variable to point
|
|
18
|
+
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
|
19
|
+
echo.may add the Sphinx directory to PATH.
|
|
20
|
+
echo.
|
|
21
|
+
echo.If you don't have Sphinx installed, grab it from
|
|
22
|
+
echo.https://www.sphinx-doc.org/
|
|
23
|
+
exit /b 1
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if "%1" == "" goto help
|
|
27
|
+
|
|
28
|
+
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
29
|
+
goto end
|
|
30
|
+
|
|
31
|
+
:help
|
|
32
|
+
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
33
|
+
|
|
34
|
+
:end
|
|
35
|
+
popd
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
API Reference
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
.. warning::
|
|
5
|
+
|
|
6
|
+
Sphinx autodoc is used to generate this documentation. It does not do a
|
|
7
|
+
particularly good job at rendering type annotations, so trust your API
|
|
8
|
+
or the code itself over the documentation shown here.
|
|
9
|
+
|
|
10
|
+
All functions are fully typed and the type annotations are mostly correct.
|
|
11
|
+
|
|
12
|
+
Unwrapping options
|
|
13
|
+
------------------
|
|
14
|
+
|
|
15
|
+
.. autofunction:: opt.unwrap
|
|
16
|
+
.. autofunction:: opt.unwrap_or
|
|
17
|
+
.. autofunction:: opt.unwrap_or_else
|
|
18
|
+
.. autofunction:: opt.expect
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Mapping over options
|
|
22
|
+
--------------------
|
|
23
|
+
|
|
24
|
+
.. autofunction:: opt.map
|
|
25
|
+
.. autofunction:: opt.call
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
Zipping and combining options
|
|
29
|
+
-----------------------------
|
|
30
|
+
|
|
31
|
+
.. autofunction:: opt.zip
|
|
32
|
+
.. autofunction:: opt.together
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
Iterating over options
|
|
36
|
+
----------------------
|
|
37
|
+
|
|
38
|
+
.. autofunction:: opt.iter
|
|
39
|
+
.. autofunction:: opt.elements
|
|
40
|
+
.. autofunction:: opt.values
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
|
2
|
+
#
|
|
3
|
+
# For the full list of built-in configuration values, see the documentation:
|
|
4
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
5
|
+
|
|
6
|
+
# -- Project information -----------------------------------------------------
|
|
7
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
8
|
+
|
|
9
|
+
project = "optionz"
|
|
10
|
+
copyright = "2026, Fábio Macêdo Mendes"
|
|
11
|
+
author = "Fábio Macêdo Mendes"
|
|
12
|
+
release = "0.1.0"
|
|
13
|
+
|
|
14
|
+
# -- General configuration ---------------------------------------------------
|
|
15
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
16
|
+
|
|
17
|
+
extensions = [
|
|
18
|
+
"sphinx_mdinclude",
|
|
19
|
+
"sphinx.ext.autodoc",
|
|
20
|
+
"sphinx.ext.napoleon",
|
|
21
|
+
"sphinx_autodoc_typehints",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
autodoc_typehints = "none"
|
|
25
|
+
napoleon_google_docstring = True
|
|
26
|
+
napoleon_numpy_docstring = False
|
|
27
|
+
typehints_document_overloads = False
|
|
28
|
+
|
|
29
|
+
templates_path = ["_templates"]
|
|
30
|
+
exclude_patterns = [] # type: ignore
|
|
31
|
+
source_suffix = [".rst", ".md"]
|
|
32
|
+
|
|
33
|
+
# -- Options for HTML output -------------------------------------------------
|
|
34
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
|
35
|
+
|
|
36
|
+
html_theme = "alabaster"
|
|
37
|
+
html_static_path = ["_static"]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Development
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
Local setup
|
|
5
|
+
-----------
|
|
6
|
+
|
|
7
|
+
You must have `uv` installed and everything else follows seamlessly. From project root:
|
|
8
|
+
|
|
9
|
+
.. code-block:: bash
|
|
10
|
+
|
|
11
|
+
uv sync --group dev
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Pull requests and contributing
|
|
15
|
+
------------------------------
|
|
16
|
+
|
|
17
|
+
This library is simple enough that you can vendorize and implement your own
|
|
18
|
+
changes to it. If you want to contribute, please open a pull request with your
|
|
19
|
+
changes and we can discuss them there.
|
|
20
|
+
|
|
21
|
+
We have a strict **NO CODING AGENT** policy. If it looks like you are Claude
|
|
22
|
+
or any other agent, we will ignore your PR.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
Routine tasks and commands
|
|
26
|
+
--------------------------
|
|
27
|
+
|
|
28
|
+
We use `uv` + `taskipy` to define and run common tasks.
|
|
29
|
+
|
|
30
|
+
**Build documentation**
|
|
31
|
+
|
|
32
|
+
.. code-block:: bash
|
|
33
|
+
|
|
34
|
+
uv run task docs
|
|
35
|
+
|
|
36
|
+
**Run tests**
|
|
37
|
+
|
|
38
|
+
.. code-block:: bash
|
|
39
|
+
|
|
40
|
+
uv run task test
|
|
41
|
+
|
|
42
|
+
**Linter**
|
|
43
|
+
|
|
44
|
+
.. code-block:: bash
|
|
45
|
+
|
|
46
|
+
uv run task lint
|
|
47
|
+
|
|
48
|
+
**Build the package**
|
|
49
|
+
|
|
50
|
+
.. code-block:: bash
|
|
51
|
+
|
|
52
|
+
uv run task build
|
|
53
|
+
|
|
54
|
+
**List tasks**
|
|
55
|
+
|
|
56
|
+
.. code-block:: bash
|
|
57
|
+
|
|
58
|
+
uv run task -l
|
|
59
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.. optionz documentation master file, created by
|
|
2
|
+
sphinx-quickstart on Sat Jun 13 14:26:03 2026.
|
|
3
|
+
You can adapt this file completely to your liking, but it should at least
|
|
4
|
+
contain the root `toctree` directive.
|
|
5
|
+
|
|
6
|
+
Optionz documentation
|
|
7
|
+
=====================
|
|
8
|
+
|
|
9
|
+
.. toctree::
|
|
10
|
+
:maxdepth: 1
|
|
11
|
+
:caption: Contents:
|
|
12
|
+
|
|
13
|
+
api
|
|
14
|
+
development
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Introduction
|
|
18
|
+
------------
|
|
19
|
+
|
|
20
|
+
.. mdinclude:: ../../README.md
|
|
21
|
+
:start-line: 2
|