privex.helpers.collections

Functions, classes and/or types which either are, or are related to Python variable storage types (dict, tuple, list, set etc.)

Object-like Dictionaries (dict’s)

Have you ever wanted a dictionary that works like an object, where you can get/set dictionary keys using attributes (x.something) as easily as you can with items (x['something'])?

We did. So we invented DictObject, a sub-class of the built-in dict, making it compatible with most functions/methods which expect a dict (e.g. json.dumps()).

You can create a new DictObject and use it just like a dict, or you can convert an existing dict into a DictObject much like you’d cast any other builtin type.

It can also easily be cast back into a standard dict when needed, without losing any data.

Creating a new DictObject and using it

Since DictObject is a subclass of the builtin dict, you can instantiate a new DictObject in the same way you would use the standard dict class:

>>> d = DictObject(hello='world')
>>> d
{'hello': 'world'}
>>> d['hello']
'world'
>>> d.hello
'world'
>>> d.lorem = 'ipsum'
>>> d['orange'] = 'banana'
>>> d
{'hello': 'world', 'lorem': 'ipsum', 'orange': 'banana'}

Converting an existing dictionary (dict) into a DictObject

You can convert an existing dict into a DictObject in the same way you’d convert any other object into a dict:

>>> y = {"hello": "world", "example": 123}
>>> x = DictObject(y)
>>> x.example
123
>>> x['hello']
'world'
>>> x.hello = 'replaced'
>>> x
{'hello': 'replaced', 'example': 123}

It also works vice versa, you can convert a DictObject instance back into a dict just as easily as you converted the dict into a DictObject.

>>> z = dict(x)
>>> z
{'hello': 'replaced', 'example': 123}

Dict-able NamedTuple’s

While collections.namedtuple()’s can be useful, they have some quirks, such as not being able to access fields by item/key (x['something']). They also expose a method ._asdict(), but cannot be directly casted into a dict using dict(x).

Our dictable_namedtuple() collection is designed to fix these quirks.

What is a dictable_namedtuple and why use it?

Unlike the normal namedtuple() types, ``dictable_namedtuple``s add extra convenience functionality:

  • Can access fields via item/key: john['first_name']

  • Can convert instance into a dict simply by casting: dict(john)

  • Can set new items/attributes on an instance, even if they weren’t previously defined.

  • NOTE: You cannot edit an original namedtuple field defined on the type, those remain read only

There are three functions available for working with dictable_namedtuple classes/instances, each for different purposes.

Importing dictable_namedtuple functions

from collections import namedtuple
from privex.helpers import dictable_namedtuple, convert_dictable_namedtuple, subclass_dictable_namedtuple

Creating a NEW dictable_namedtuple type and instance

If you’re creating a new Named Tuple, and you want it to support dictionary-like access, and have it able to be converted into a dict simply through dict(my_namedtuple), then you want dictable_namedtuple()

Person = dictable_namedtuple('Person', 'first_name last_name')
john = Person('John', 'Doe')
dave = Person(first_name='Dave', last_name='Smith')
print(dave['first_name'])       # Prints:  Dave
print(dave.first_name)          # Prints:  Dave
print(john[1])                  # Prints:  Doe
print(dict(john))               # Prints:  {'first_name': 'John', 'last_name': 'Doe'}

Converting an existing namedtuple instance into a dictable_namedtuple instance

If you have existing Named Tuple instances, e.g. returned from a python library, then you can use convert_dictable_namedtuple() to convert them into dictable_namedtuple’s and gain all the functionality mentioned at the start of this section.

Person = namedtuple('Person', 'first_name last_name')  # This is an existing namedtuple "type" or "class"
john = Person('John', 'Doe')  # This is an existing namedtuple instance
john.first_name               # This works on a standard namedtuple. Returns: John
john[1]                       # This works on a standard namedtuple. Returns: Doe
john['first_name']            # However, this would throw a TypeError.
dict(john)                    # And this would throw a ValueError.

# We can now convert 'john' into a dictable_namedtuple, which will retain the functionality of a
# namedtuple, but add to the functionality by allowing dict-like key access, updating/creating new
# fields, as well as painlessly casting to a dictionary.

d_john = convert_dictable_namedtuple(john)
d_john.first_name               # Returns: John
d_john[1]                       # Returns: Doe
d_john['first_name']            # Returns: 'John'
dict(d_john)                    # Returns: {'first_name': 'John', 'last_name': 'Doe'}

Converting an existing namedtuple type/class into a dictable_namedtuple type/class

If you have existing Named Tuple type/class then you can use subclass_dictable_namedtuple() to convert the type/class into a dictable_namedtuple type/class and gain all the functionality mentioned at the start of this section. (NOTE: it’s usually easier to just replace your namedtuple calls with dictable_namedtuple)

Person = namedtuple('Person', 'first_name last_name')  # This is an existing namedtuple "type" or "class"
# We can now convert the 'Person' type into a dictable_namedtuple type.
d_Person = subclass_dictable_namedtuple(Person)
# Then we can use this converted type to create instances of Person with dictable_namedtuple functionality.
john = d_Person('John', 'Doe')
john.first_name               # Returns: John
john[1]                       # Returns: Doe
john['first_name']            # Returns: 'John'
dict(john)                    # Returns: {'first_name': 'John', 'last_name': 'Doe'}

Copyright:

    +===================================================+
    |                 © 2019 Privex Inc.                |
    |               https://www.privex.io               |
    +===================================================+
    |                                                   |
    |        Originally Developed by Privex Inc.        |
    |        License: X11 / MIT                         |
    |                                                   |
    |        Core Developer(s):                         |
    |                                                   |
    |          (+)  Chris (@someguy123) [Privex]        |
    |          (+)  Kale (@kryogenic) [Privex]          |
    |                                                   |
    +===================================================+

Copyright 2019     Privex Inc.   ( https://www.privex.io )

Functions

convert_dictable_namedtuple(nt_instance[, …])

Convert an existing collections.namedtuple() instance into a dictable_namedtuple instance.

dictable_namedtuple(typename, field_names, …)

Creates a dictable_namedtuple type for instantiation (same usage as collections.namedtuple()) - unlike namedtuple, dictable_namedtuple instances allow item (dict-like) field access, support writing and can be painlessly converted into dictionaries via dict(my_namedtuple).

is_namedtuple(*objs)

Takes one or more objects as positional arguments, and returns True if ALL passed objects are namedtuple instances

make_dict_tuple(typename, field_names, …)

Generates a collections.namedtuple() type, with added / modified methods injected to make it into a dictable_namedtuple.

subclass_dictable_namedtuple(named_type[, …])

Convert an existing collections.namedtuple() type into a dictable_namedtuple.

Classes

DictObject

A very simple dict wrapper, which allows you to read and write dictionary keys using attributes (dot notation) PLUS standard item (key / square bracket notation) access.

Dictable()

A small abstract class for use with Python 3.7 dataclasses.

Mocker(modules, attributes)

This mock class is designed to be used either to act as a stand-in “noop” (no operation) object, which could be used either as a drop-in replacement for a failed module / class import, or for certain unit tests.

OrderedDictObject

Ordered version of DictObject - dictionary with attribute access.