Skip to main content
DictRegister
============

|Build Status| |Version| |PyPi Downloads|

Documentation
-------------

`dictregister
documentation <https://dictregister.readthedocs.org/en/latest/>`__

**dictregister** provides an object that contains an ordered list of
dictionaries with some functions to search and manage them.

Dictionaries are useful objects, as they can easily represent complex
objects; being a basic language structure in Python they are very handy:
as an instance, they are serialiable, and if you ever worked with JSON
you are accustomed to see them around.

When dealing with more than one dictionary, namely a list of them, a
problem arises: searching the list for dictionaries is complex and you
usually write a bunch of repeated code to get the information you need.

**dictregister** acts as a standard Python list but can contain only
dictionaries (actually objects implementing collections.Mapping);
additionally, it provides functions to search and manage dictionaries by
key, to manage single keys and to store more than one value for each
key.

**dictregister** is a pure Python package, but its syntax has been
heavily influenced by Django's query syntax, so Django users will find
at home.

Indeed, **dictregister** acts like a small key/value database. Please
note that there it stores values in memory and there is no optimization,
so use it for small collections.

Basic usage
-----------

The ``DictRegister`` object acts as a ``list``, so you can either
initialize it empty

.. code:: python

import dictregister
dr = dictregister.DictRegister()

or with an iterable object as an argument

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}])

and you can use any method of ``list`` like ``append()``

.. code:: python

import dictregister
dr = dictregister.DictRegister()
dr.append({'x':1, 'y':2})

``DictRegister`` accepts only objects that inherit from the
``collections.Mapping`` Abstract Base Class. If you try to insert an
object that does not stick with this rule you will receive a
``TypeError``.

Managing keys
-------------

You can manage keys in batch mode with ``kadd()``, ``kreplace()``, and
``kremove()``.

Adding a key to each element is easy with ``kadd()``

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}])
dr == [{'x':1, 'y':2}, {'x':3, 'y':4}]
dr.kadd('z', 5)
dr == [{'x':1, 'y':2, 'z':5}, {'x':3, 'y':4, 'z':5}]

Please note that if you add more than a value to the same key you get a
multiple-value element, which is treated in a special way. See the
Multiple values section below.

When you remove keys you can do it unconditionally

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}])
dr == [{'x':1, 'y':2}, {'x':3, 'y':4}]
dr.kremove('y')
dr == [{'x':1}, {'x':3}]

which removes all keys with that name. or you can specify a value, in
which case only the elments that match both the key and the value will
be removed.

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}])
dr == [{'x':1, 'y':2}, {'x':3, 'y':4}]
dr.kremove('y',4)
dr == [{'x':1, 'y':2}, {'x':3}]

Last, you can replace the value of a key

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}])
dr == [{'x':1, 'y':2}, {'x':3, 'y':4}]
dr.kreplace('x',6)
dr == [{'x':6, 'y':2}, {'x':6, 'y':4}]

Advanced usage
--------------

You can find a subset of dictionaries using ``dfilter()``

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}])
filtdr = dr.dfilter(x=1)
filtdr == [{'x':1, 'y':2}]

You can pass as many conditions as you want to ``dfilter()``

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}])
filtdr = dr.dfilter(x=1)
filtdr == [{'x':1, 'y':2}, {'x':1, 'y':6}]
filtdr = dr.dfilter(x=1, y=2)
filtdr == [{'x':1, 'y':2}]

You can easily get only the first element of the filtering with
``dget()``. Remember that while ``dfilter()`` silently accepts a search
that returns no values, returning an empty ``DictRegister``, ``dget()``
raises an ``IndexError`` exception.

You can remove elements from a ``DictRegister`` object with
``dremove()``, which returns a ``DictRegister`` containing the removed
elements.

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}])
filtdr = dr.dremove(x=1)
dr == [{'x':3, 'y':4}]
filtdr == [{'x':1, 'y':2}, {'x':1, 'y':6}]

Otherwise you obtain a new object with the elements removed
``dremove_copy()``

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}])
filtdr = dr.dremove_copy(x=1)
dr == [{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}]
filtdr == [{'x':3, 'y':4}]

Last you can pop an element with ``dpop()``, which returns the first
element matching the given conditions. Remember that ``dpop()`` raises
``IndexError`` if no matching element is found.

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}])
filtdr = dr.dpop(x=1)
dr == [{'x':3, 'y':4}, {'x':1, 'y':6}]

Remember that, being a list, ``DictRegister`` also provides you a
``pop([i])`` method that pops the element at index ``i`` or the first
element if ``i`` is not specified.

Note that ``dfilter()``, ``dremove()``, and ``dremove_copy()`` return a
``DictRegister`` so you can easily chain calls.

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}])
filtdr = dr.dfilter(x=1).dremove_copy(y=2)
dr == [{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}]
filtdr == [{'x':1, 'y':6}]

Matching elements
-----------------

When using the advanced features of ``DictRegister`` like filtering you
can use a special syntax for keys, namely a ``key__operator`` syntax.

The implicit operator is ``eq``, which matches all dictionaries with the
given key with the given value.

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}])
filtdr = dr.dfilter(x__eq=3)
filtdr == [{'x':3, 'y':4}]
filtdr = dr.dfilter(x=3)
filtdr == [{'x':3, 'y':4}]

The inequality can be matched with ``ne``

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6}])
filtdr = dr.dfilter(x__ne=1)
filtdr == [{'x':3, 'y':4}]

You can match dictionaries that contain or not a given key

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}, {'x':1, 'y':6, 'z':8}])
filtdr = dr.dfilter(z__iskey=True)
filtdr == [{'x':1, 'y':6, 'z':8}]
filtdr = dr.dfilter(z__iskey=False)
filtdr == [{'x':1, 'y':2}, {'x':3, 'y':4}]

Multiple values
---------------

The ``DictRegister`` object can contain any dictionary with a single
value for each key, like

.. code:: python

import dictregister
dr = dictregister.DictRegister()
dr.append({'x':1, 'y':2})

If you store more than a value for a key, ``DictRegister`` uses a set to
host the values. You are free to append dictionaries with generic
sequences, most notably lists and sets, as values. However remeber that
``DictRegister`` does not consider the sequence itself as the value of
the key, but the contained elements; so if you need to store a sequence
as a value you have to store a ``set`` that contains the sequence.

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':1, 'y':2}, {'x':3, 'y':4}])
dr == [{'x':1, 'y':2}, {'x':3, 'y':4}]
dr.kadd('x', 2)
dr == [{'x':set([1, 2]), 'y':2}, {'x':set([2, 3]), 'y':4}]

You can match multiple values with the ``in`` and ``nin`` operators. The
first matches all dictionaries that contain the given key with the given
value among its values, while ``nin`` performs the opposite match.

.. code:: python

import dictregister
dr = dictregister.DictRegister([{'x':set([1, 2]), 'y':2}, {'x':2, 'y':4}])
filtdr = dr.dfilter(x__in=2)
filtdr == [{'x':set([1, 2]), 'y':2}, {'x':2, 'y':4}]

As you can see ``DictRegister`` treats keys with a single value and with
multiple values in the same way.

Installation
------------

.. code:: sh

pip install dictregister

Contributions
-------------

Any form of contribution is warmly welcomed. Feel free to submit issues
of to make changes and submit a pull request. being the first Python
package I ship with all the bells and whistles like distutils, tests and
friends, I gladly accept suggestions or corrections on this topic.

Thanks
------

Many thanks to `Jeff Knupp <http://www.jeffknupp.com/about-me/>`__ for
his post `Open Sourcing a Python Project the Right
Way <http://www.jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/>`__.

Many thanks to `Audrey M. Roy <http://www.audreymroy.com/>`__ for her
`cookiecutter <https://github.com/audreyr/cookiecutter>`__ and
`cookiecutter-pypackage <https://github.com/audreyr/cookiecutter-pypackage>`__
tools, which heavily simplified the implementation of the whole thing.

.. |Build Status| image:: https://travis-ci.org/lgiordani/dictregister.png?branch=master
:target: https://travis-ci.org/lgiordani/dictregister
.. |Version| image:: https://badge.fury.io/py/dictregister.png
:target: http://badge.fury.io/py/dictregister
.. |PyPi Downloads| image:: https://pypip.in/d/dictregister/badge.png
:target: https://crate.io/packages/dictregister?version=latest




History
-------

0.9.0 (2013-11-08)
++++++++++++++++++

* First implementation

0.9.0.post1 (2013-11-08)
++++++++++++++++++

* Fixed PyPI classifiers

0.9.1 (2013-11-14)
++++++++++++++++++

* Added a direct import of DictRegister in __init__.py (thanks to https://github.com/Jeff17Robbins)

0.9.2 (2013-11-14)
++++++++++++++++++

* Fixed import in __init__.py for Python 3, now all tox tests pass

1.0.0 (2013-12-04)
++++++++++++++++++

* Raise TypeError instead of ValueError if invalid object is passed (pull request from joshgeller)

Release files for dictregister 1.0.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 dictregister 1.0.0
File Size Uploaded
dictregister-1.0.0.tar.gz 10.0 kB Details

Release files / dictregister-1.0.0.tar.gz

Download URL dictregister-1.0.0.tar.gz
Size 10.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9bb2b996ae96c74890b6f8c59081ac1fe22b0d9e638a8d625b181ce4825fb962
BLAKE2b-256 checksum
How to use checksums
6ddfeaa1cd1bed1382c15c68fbd2c87b1f852cb876c50f7414a50a4367fdb8c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release history Release notifications | RSS feed

This release

1.0.0 This release

1 release file

0.9.2

1 release file

0.9.1

1 release file

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