Skip to main content

if_

Optional chaining for Python

Installation

pip install if_optional

The distribution is named if_optional; the module it installs is if_. Requires Python 3.10 or later.

Usage

Call if_() with a Python expression, and chain attribute, item and call accessors on the return value, ending with ._. If the initial expression evaluates to None, so will the whole chain. Otherwise each accessor runs normally, and if a step is missing the chain returns None. A step is missing when:

  • the attribute does not exist on the value,
  • the key or index is not found (KeyError / IndexError),
  • the value is not subscriptable, or
  • the value is not callable.

Errors raised inside a property, a __getitem__ method or a called function are not caught, so bugs in your own code still raise. A key of the wrong type, such as a string index into a list, also raises TypeError.

All other operators act on the wrapped value, so you can leave off the ._ in comparisons, arithmetic, bool(), len(), str(), iteration, in and so on. These return the plain result, not an if_. On a failed chain they act on None, so if_(d)['missing'] + 1 raises TypeError just as None + 1 does.

Limitations

  • A missing value cannot be told apart from a value that is actually None: if_({'a': None})['a']._ and if_({})['a']._ are both None. Likewise, in a boolean test a missing value and a falsy value (False, 0, '') both count as false.
  • The chain does not short-circuit. In if_(None).f(expensive()), expensive() is still evaluated.
  • Attributes named _ and dunder attributes such as __name__ can't be accessed through the chain.

Examples

In [1]: from if_ import if_

In [2]: d = {
   ...:     'a': 123,
   ...:     'c': None,
   ...:     'd': {'this': 456},
   ...:     'l': [1, 2, 3],
   ...:     'f': lambda x: x * 11,
   ...: }

In [3]: if_(None).anything._ is None
Out[3]: True

In [4]: if_(d).anything._ is None
Out[4]: True

In [5]: if_(d)['a']._ == 123
Out[5]: True

In [6]: if_(d)['c']['anything']._ is None
Out[6]: True

In [7]: if_(d)['l'][1]._ == 2
Out[7]: True

In [8]: if_(d)['l'][5]._ is None
Out[8]: True

In [9]: if_(d)['f'](4) == 44
Out[9]: True

In [10]: if_(d)['a'] + 1
Out[10]: 124

In [11]: list(if_(d)['l'])
Out[11]: [1, 2, 3]

Running the tests

python -m unittest

Metadata

Release files for if-optional 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for if-optional 0.1.0
File Size Uploaded Provenance Actions
if_optional-0.1.0.tar.gz 6.2 kB Without provenance Details for if_optional-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for if-optional 0.1.0
File Interpreter ABI Platform Actions
if_optional-0.1.0-py3-none-any.whl Python 3 none any Details for if_optional-0.1.0-py3-none-any.whl

Total release size: 10.9 kB

Release files / if_optional-0.1.0.tar.gz

Download URL if_optional-0.1.0.tar.gz
Size 6.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f1b9c69c95b484b876ead98437e28b4c67d26feabeacb98fd783c74cfdb33f4d
BLAKE2b-256 checksum
How to use checksums
4592e612f7b2bd0d8f2418130c592fe4759f0c589b7831c450c4903530d24040
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / if_optional-0.1.0-py3-none-any.whl

Download URL if_optional-0.1.0-py3-none-any.whl
Size 4.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2c580628f82d20612c6c4c82e3e08e05d4d89ff6535eabfc055db762ed3433eb
BLAKE2b-256 checksum
How to use checksums
8125987a382be9b9a1043e6a043e2df8ecd3feb6e164b5c7d72eb6c8b93157fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Security for if-optional 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page