Little python package implementing optional chaining
Project description
safebag
Safebag is a little python package implementing optional chaining.
Installation
pip install safebag
Usage
Code we want to avoid
if (
obj is not None
and obj.attr is not None
and obj.attr.attr is not None
and obj.attr.attr.attr is not None
and obj.attr.attr.attr.attr is not None
):
# Do something useful with obj.attr.attr.attr.attr
...
Pythonic solution
try:
print(obj.attr.attr.attr.attr)
# Do something useful with obj.attr.attr.attr.attr
except(NameError, AttributeError) as e:
# Do something useful with an error
Still it's not very clean way in case of multiple attribute handling in one place
try:
print(obj.attr.attr.attr.attr)
# Do something useful with obj.attr.attr.attr.attr
except(NameError, AttributeError) as e:
...
try:
print(obj.attr.attr)
# Do something useful with obj.attr.attr
except(NameError, AttributeError) as e:
...
try:
print(obj.attr)
# Do something useful with obj.attr
except(NameError, AttributeError) as e:
...
Usage example:
from safebag import chain, get_value
if attr := chain(obj).attr.attr.attr.attr:
# Do something useful with obj.attr.attr.attr.attr
print(get_value(attr))
if attr := chain(obj).attr.attr:
# Do something useful with obj.attr.attr
print(get_value(attr))
if attr := chain(obj).attr:
# Do something useful with obj.attr
print(get_value(attr))
Examples
chain [source]
Optional chain constructor, may be constructed from any object
Chain is used for building sequence of null-safe attribute calls
from __future__ import annotations
import dataclasses as dt
import typing
@dt.dataclass
class Node:
data: int
node: typing.Optional[Node]
nodes = Node(data=1, node=Node(data=2, node=None))
from safebag import chain
third_node_proxy = chain(nodes).node.node.node
print(third_node_proxy) # ChainProxy(data_object=None, bool_hook=False)
get_value [source]
Final value getter for optional chain.
Optional chain constructed from any object. Chain is used for building sequence of null-safe attribute calls.
from __future__ import annotations
import dataclasses as dt
import typing
@dt.dataclass
class Node:
data: int
node: typing.Optional[Node]
nodes = Node(data=1, node=Node(data=2, node=None))
from safebag import chain, get_value
third_node_proxy = chain(nodes).node.node.node
value = get_value(third_node_proxy)
assert value is None
next_node = chain(nodes).node
value = get_value(next_node) # Node(data=2, node=None)
Possible way of getting value
if next_node := chain(nodes).node:
print(next_node.get_value()) # Node(data=2, node=None)
Default can be passed as argument
if next_node := chain(nodes).node.node:
print(next_node.get_value(default='Default')) # 'Default'
Useful in combination with walrus operator:
if next_node := chain(nodes).node.node:
print(get_value(next_node))
if next_node := chain(nodes).node:
print(get_value(next_node)) # Node(data=2, node=None)
ChainProxy [source]
ChainProxy
container:
- stores
data_object
- proxying
data_object
attribute value into newChainProxy
instance when attribute is invoked. If attribute does not exist or attribute value isNone
.ChainProxy
instancedata_object
will beNone
andbool_hook
will beFalse
. ChainProxy
instance always returning when attribute is invoked.
Release: 0.2.0
Performance update
Increase performance by adding empty_proxy instead of real ChainProxy
For case below Numbers: # 0.100 -> 0.046
import timeit
from dataclasses import dataclass
@dataclass
class Node:
data: int
node: typing.Optional[Node]
node = Node(1, None)
executable = lambda: get_value(chain(node).node.node.node.node.node.node.node.node.node.node)
perf = timeit.timeit(executable, number=10000)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file safebag-0.2.0.tar.gz
.
File metadata
- Download URL: safebag-0.2.0.tar.gz
- Upload date:
- Size: 4.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.13 CPython/3.10.2 Linux/5.13.0-1031-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 88ad201513276fe32dd3ab975e9ae2eee8edcd819d5bf4a6f2894a52c76be756 |
|
MD5 | aafdcb74a2676fdfe770d4748f35625b |
|
BLAKE2b-256 | 18b2fc127bc602aa2ca95f4e6170a13bdaaafaa4f6a6b86dcd4c6b62574f923a |
File details
Details for the file safebag-0.2.0-py3-none-any.whl
.
File metadata
- Download URL: safebag-0.2.0-py3-none-any.whl
- Upload date:
- Size: 5.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.13 CPython/3.10.2 Linux/5.13.0-1031-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e43e6d7bfa441fb00b3baaf0dec058f4ed2094c7b38c191b90785b49ab63926f |
|
MD5 | 82544940b5405553c311164cff50ebb4 |
|
BLAKE2b-256 | b52e23274c9ebb6e5b0c91a29da05a743889447c8737a0cb7c4b467f311f8d15 |