Skip to main content

rsdict

Actions Badge - Python package PyPI version Downloads

rsdict is a restricted and resetable dictionary, a subclass of dict (inherits from built-in dictionary).

>>> from rsdict import rsdict

>>> d = {"foo": 0, "bar": "baz"}
>>> rd = rsdict(d)
>>> rd
rsdict({'foo': 0, 'bar': 'baz'}, frozen=False, fixkey=True, fixtype=True, cast=False)

# fixkey=True: key restriction
>>> rd["newkey"] = 1
AttributeError
# fixtype=True: type restriction
>>> rd["foo"] = "str.value"
TypeError

>>> rd["foo"] = 999
>>> rd == d
False
# reset values to initial
>>> rd.reset()
>>> rd == d
True

Installation

pip install rsdict

Features

  • Type-restrict(able): If activated, every type of value is fixed to its initial type.
  • Key-restrict(able): If activated, cannot add or delete keys.
  • Resettable: to initial value(s).

Arguments

rsdict(items, frozen=False, fixkey=True, fixtype=True, cast=False)

  • items (dict): Initial items (data). Built-in dictionary only. kwargs are not supported.
  • frozen (bool, optional): If True, the instance will be frozen (immutable).
  • fixkey (bool, optional): If True, cannot add or delete keys.
  • fixtype (bool, optional): If True, cannot change type of keys.
  • cast (bool, optional): If False, cast to initial type (if possible). If True, allow only the same type of initial value.

Subclasses

# rsdict(frozen=True) as default
from rsdict import rsdict_frozen as rsdict

# rsdict(fixkey=False, fixtype=False) as default
from rsdict import rsdict_unfix as rsdict

# rsdict(fixkey=True, fixtype=False) as default
from rsdict import rsdict_fixkey as rsdict

# rsdict(fixkey=False, fixtype=True) as default
from rsdict import rsdict_fixtype as rsdict

Additional methods

  • set(key, value): Alias of __setitem__.
  • to_dict() -> dict: Convert to dict instance.
  • reset(key: Optional[Any]) -> None: Reset value to the initial value. If key is None, reset all values.
  • is_changed(key: Optional[Any]) -> bool: If True, the values are changed from initial. If key is not None, check the key only.
  • get_initial(key: Optional[Any]) -> dict | Any: Return initial value(s). If key is None, Return dict of all initial values.

Examples

Create (Initialize)

>>> from rsdict import rsdict

>>> d = dict(
...     name = "John",
...     enable = True,
...     count = 0,
... )
>>> rd = rsdict(d)
>>> rd
rsdict({'name': 'John', 'enable': True, 'count': 0},
        frozen=False, fixkey=True, fixtype=False)

>>> type(rd) is dict
False
>>> isinstance(rd, dict)
True
>>> rd.frozen
False

Get

Same as dict.

>>> rd["count"] == d["count"]
True
>>> rd["xyz"]
KeyError

>>> rd.get("count") == d.get("count")
True
>>> rd.get("xyz")
None

Set

>>> rd["enable"] = False
>>> rd.set("enable", False)
# If frozen, always raise an exception.
>>> rd_frozen = rsdict(d, frozen=True)
>>> rd_frozen["count"] = 2
AttributeError
# If fixtype and not cast, different-type value raise an exception.
>>> rd["count"] = "2"
TypeError

# If fixtype and cast, cast value to initial type.
>>> rd_cast = rsdict(d, cast=True)
>>> rd_cast["count"] = "2"
>>> rd_cast["count"]
2
>>> rd_cast["count"] = "abc"
ValueError

# If not fixtype, anything can be set.
>>> rd_typefree = rsdict(d, fixtype=False)
>>> rd_typefree["count"] = "2"
>>> rd_typefree["count"]
'2'
# If fixkey, setting with a new key raises an exception.
>>> rd["location"] = 9
AttributeError

# If not fixkey, a new key can be set.
>>> rd_keyfree = rsdict(d, fixkey=False)
>>> rd_keyfree["location"] = 9
>>> rd_keyfree["location"]
9

Delete

# If frozen or fixkey, deleting key raises an exception.
>>> del rd["count"]
AttributeError

# Else, delete both current and initial values.
>>> rd_keyfree = rsdict(dict(a=1, b=2, c=3), fixkey=False)
>>> del rd_keyfree["b"]
>>> rd_keyfree.keys()
dict_keys(['a', 'c'])
>>> rd_keyfree.get_initial().keys()
dict_keys(['a', 'c'])

Reset

# Check whether the values are changed from initial.
>>> rd.is_changed()
False
# (Change some values.)
>>> rd["enable"] = False
>>> rd["count"] = 5
>>> rd.is_changed()
True

# Reset with a key.
>>> rd.reset("count")
>>> rd["count"]
0
>>> rd.is_changed()
True

# Reset all values.
>>> rd.reset()
>>> rd.is_changed()
False

Copy

# Create a new rsdict with different optional arguments.
# If reset, copy initial values only.
>>> rd["name"] = "Mike"
>>> rd2 = rd.copy(reset=True)
>>> rd2 == rd.get_initial()
True

# If frozen and not reset, copy current values as new initial values.
>>> rd3 = rd.copy(frozen=True)
>>> rd3
rsdict({'name': 'Mike', 'enable': True, 'count': 0},
    frozen=True, fixkey=True, fixtype=False, cast=False)
>>> rd3 == rd
True
>>> rd3.get_initial() == rd.get_initial()
False

Compare

>>> rd1 = rsdict({"key1": 10, "key2": "abc"})
>>> rd2 = rsdict({"key1": 20, "key2": "abc"})
# Change current value.
>>> rd2["key1"] = 10

# Current values are equal.
>>> rd1 == rd2
True

# Initial values are not equal.
>>> rd1.get_initial() == rd2.get_initial()
False

# If compare with dict, use current values.
>>> d2 = rd2.to_dict()
>>> rd2 == d2

Union

(Python3.9 or later)

>>> rd = rsdict({"key1": 10, "key2": "abc"}, fixkey=False)
>>> d = {"key2": 20, "key3": False}

# Return: dict
>>> rd | d
{'key1': 10, 'key2': 20, 'key3': False}
>>> d | rd
{'key2': 'abc', 'key3': False, 'key1': 10}

>>> rd |= d
>>> rd
rsdict({'key1': 10, 'key2': 20, 'key3': False},
    frozen=False, fixkey=False, fixtype=True, cast=False)
# Add initial values of new keys only.
>>> rd.get_initial()
{'key1': 10, 'key2': 'abc', 'key3': False}

Note

>>> d = dict(a=[1])
>>> rd = rsdict(d)
>>> rd["a"].append(2)
>>> rd
rsdict({'a': [1, 2]}, frozen=False, fixkey=True, fixtype=True, cast=False)
>>> d
{'a': [1, 2]}
>>> rd.get_initial()
{'a': [1]}

Performance

rsdict is slower than dict due to its additional checking.

Image: https://github.com/kihiyuki/python-rsdict/blob/main/docs/img/speed.png

Changelog

-> CHANGELOG.md

Release files for rsdict 0.1.8

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

Source distribution (sdist)

Source distribution for rsdict 0.1.8
File Size Uploaded
rsdict-0.1.8.tar.gz 9.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rsdict 0.1.8
File Interpreter ABI Platform
rsdict-0.1.8-py3-none-any.whl Python 3 none any Details

Total release size: 17.7 kB

Release files / rsdict-0.1.8.tar.gz

Download URL rsdict-0.1.8.tar.gz
Size 9.6 kB
Tags Source
SHA-256 checksum
How to use checksums
d2990fc787da362c913508492bb3ddff66c683c4a725a3c28022242a8d79c797
BLAKE2b-256 checksum
How to use checksums
0b67ecd3489b3daf011d4f82ed7331e1b66ccbbadefeefb203ce1ac541dadd4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.10

Release files / rsdict-0.1.8-py3-none-any.whl

Download URL rsdict-0.1.8-py3-none-any.whl
Size 8.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
746c12d16ac7015bd4f9c3817f4d858811b9f5ed5c55c2783c68fce4328401e2
BLAKE2b-256 checksum
How to use checksums
787b17022e37a08bcfa95bb0a5508881796d65befbf28c9f0bbfa59fd9013539
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.10

Release history Release notifications | RSS feed

This release

0.1.8 This release

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

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