fictive.patterns.mappings module

Common patterns for working with mapping objects

Functions

as_tuple

Converts a mapping to a collections.namedtuple

bisect

split mapping into two mappings based on key

collated

create mapping from a (sortable) iterable, grouping by key

merged

create a new mapping by combining maps

Classes

NormalizedMap

Concrete implementation of NormalizedMapMixin for ease of use

NormalizedMapMixin

A mixin to automatically normalize mapping keys

class fictive.patterns.mappings.NormalizedMapMixin(*args, **kwargs)[source]

Bases: object

A mixin to automatically normalize mapping keys

When this mixin is included in an implementation of collections.abc.Mapping, a user-defined normalizing function (i.e., normalized_key()) will be applied to keys before values are stored, read, deleted, or searched in the mapping. E.g.:

import collections
from fictive.patterns.mappings import NormalizedMapMixin

class UpperCaseMapping(NormalizedMapMixin, collections.UserDict):

    @staticmethod
    def normalized_key(key):
        return key.upper()
>>> normalized = UpperCaseMapping({'foo': 'bar'})
>>> list(normalized.items())
[('FOO', 'bar')]
>>> 'fOO' in normalized
True
>>> normalized['FoO']
'bar'
__init__(*args, **kwargs)[source]

Initialize a mapping with an optional normalization function

In addition to the base mapping class’s arguments, this mixin can accept an additional positional argument that specifies the normalization function to use for this instance. The normalization function must be passed as the last positional argument and should take a single key positional argument. E.g.:

import collections
from fictive.patterns.mappings import NormalizedMapMixin

class AdHocNormalizing(NormalizedMapMixin, collections.UserDict):
    pass
>>> normalized = AdHocNormalizing({'FOO': 'bar'}, str.lower)
>>> list(normalized.items())
[('foo', 'bar')]
>>> 'fOO' in normalized
True
>>> normalized['FoO']
'bar'
get(key, default=None)[source]

re-implementation standard dict.get() behavior

Some built in collections.Mapping classes don’t use __getitem__ (e.g., collections.OrderedDict) and thus would not apply the noralization function this method were not overridden.

static normalized_key(key)[source]

Function applied to all keys on read / write / search of the mapping

Parameters

key – The key to normalize

By default, this is the identify function (i.e., return key unchanged), but this can be overridden by subclassing, or on a per-sinstance basis as an argument to the __init__() method

class fictive.patterns.mappings.NormalizedMap(*args, **kwargs)[source]

Bases: fictive.patterns.mappings.NormalizedMapMixin, collections.UserDict

Concrete implementation of NormalizedMapMixin for ease of use

This class can be directly initialized by providing a normalization function to the NormalizedMapMixin.__init__() method. E.g.:

>>> from fictive.patterns.mappings import NormalizedMap
>>> normalized = NormalizedMap({'foo': 'bar'}, str.upper)
>>> list(normalized.items())
[('FOO', 'bar')]
>>> 'fOO' in normalized
True
>>> normalized['FoO']
'bar'
fictive.patterns.mappings.merged(*maps, merged_class=<class 'dict'>)[source]

create a new mapping by combining maps

E.g.:

>>> map_1 = {'name': 'Adam', 'occupation': 'farmer'}
>>> map_2 = {'name': 'Bill', 'height': 'tall'}
>>> import pprint
>>> pprint.pprint(merged(map_1, map_2))
{'height': 'tall', 'name': 'Adam', 'occupation': 'farmer'}
Parameters
fictive.patterns.mappings.collated(sortable, key=None, group_key=None)[source]

create mapping from a (sortable) iterable, grouping by key

E.g.:

import operator
import pprint
from fictive.patterns.mappings import collated

data = [
   ('colors', 'red'),
   ('vegetables', 'carrot'),
   ('cities', 'Paris'),
   ('vegetables', 'celery'),
   ('colors', 'blue'),
   ('colors', 'green'),
   ('cities', 'London'),
]
>>> pprint.pprint(collated(data, key=operator.itemgetter(0)))
{'cities': [('cities', 'London'), ('cities', 'Paris')],
 'colors': [('colors', 'blue'), ('colors', 'green'), ('colors', 'red')],
 'vegetables': [('vegetables', 'carrot'), ('vegetables', 'celery')]}
Parameters
  • sortable (collections.abc.Iterable) – an iterable to be collated

  • key (collections.abc.Callable) – specifies a function of one argument that is used to extract a collation key from each element in sortable. If not specified or is None, key defaults to an identity function and returns the element unchanged. The function should be suitable as the key parameter to sorted() and itertools.groupby().

  • group_key (collections.abc.Callable) – key specifies a function of one argument that is used to extract a comparison key from each element in each collation group (for example, group_key=str.lower). The default value is None (compare the elements directly).

fictive.patterns.mappings.bisect(mapping, key)[source]

split mapping into two mappings based on key

E.g.:

import pprint
from fictive.patterns.mappings import bisect

data = {
    'color': 'red',
    'vegetable': 'carrot',
    'cities': 'new york',
    'size': 'small',
    'temperature': 'hot',
    'age': 'old',
}
>>> key_func = lambda key, value: len(value) < 4
>>> pprint.pprint(bisect(mapping=data, key=key_func))
({'age': 'old', 'color': 'red', 'temperature': 'hot'},
 {'cities': 'new york', 'size': 'small', 'vegetable': 'carrot'})
Parameters
  • mapping (collections.abc.Mapping) – the mapping to bisect

  • key (collections.abc.Callable) – specifies a function of two positional arguments that is used to extract a bisection key from each item in mapping. The arguments to the key function are the key and value for each item in mapping

fictive.patterns.mappings.as_tuple(mapping, name='as_tuple')[source]

Converts a mapping to a collections.namedtuple

E.g.:

from fictive.patterns.mappings import as_tuple

mapping = {
    'city': 'New York',
    'color': 'red',
    'vegetable': 'celery',
}
>>> as_tuple(mapping)
as_tuple(city='New York', color='red', vegetable='celery')
>>> as_tuple(mapping, name='custom_type')
custom_type(city='New York', color='red', vegetable='celery')