Skip to main content

Type or key restricted and resettable dictionary

Project description

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() -> bool: If True, the values are changed from initial.
  • get_initial(key: Optional[Any]) -> dict | Any: Return initial value(s). If key is None, Return dict of all initial values.

Disabled methods

  • fromkeys()

Notes

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)

Get

Same as dict.

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

Set

>>> rd["enable"] = False
>>> rd.set("enable", False)
# If frozen, always raise an exception.
>>> rd_frozen = rsdict(dict(count=1), 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["count"] = "2"
>>> rd["count"]
2
>>> rd["count"] = "abc"
ValueError

# If not fixtype, anything can be set.
>>> rd["count"] = "2"
>>> rd["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["location"] = 9
>>> rd["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}

Speed

rsdict is slower than dict due to its additional checking.

speed.png

Changelog

-> CHANGELOG.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rsdict-0.1.6.tar.gz (9.0 kB view hashes)

Uploaded Source

Built Distribution

rsdict-0.1.6-py3-none-any.whl (7.5 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page