cs.mappings


Namecs.mappings JSON
Version 20231129 PyPI version JSON
download
home_pagehttps://bitbucket.org/cameron_simpson/css/commits/all
SummaryFacilities for mappings and objects associated with mappings.
upload_time2023-11-29 09:10:10
maintainer
docs_urlNone
authorCameron Simpson
requires_python
licenseGNU General Public License v3 or later (GPLv3+)
keywords python2 python3
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            Facilities for mappings and objects associated with mappings.

*Latest release 20231129*:
AttrableMappingMixin: look up ATTRABLE_MAPPING_DEFAULT on the class, not the instance.

In particular `named_column_tuple(column_names)`,
a function returning a factory
for namedtuples subclasses derived from the supplied column names,
and `named_column_tuples(rows)`,
a function returning a namedtuple factory and an iterable of instances
containing the row data.
These are used by the `csv_import` and `xl_import` functions
from `cs.csvutils`.

## Function `attrable(o)`

Like `jsonable`, return `o` with `dicts` replaced by `AttrableMapping`s.

## Class `AttrableMapping(builtins.dict, AttrableMappingMixin)`

A `dict` subclass using `AttrableMappingMixin`.

## Class `AttrableMappingMixin`

Provides a `__getattr__` which accesses the mapping value.

## Class `AttributableList(builtins.list)`

An `AttributableList` maps unimplemented attributes
onto the list members and returns you a new `AttributableList`
with the results, ready for a further dereference.

Example:

    >>> class C(object):
    ...   def __init__(self, i):
    ...     self.i = i
    >>> Cs = [ C(1), C(2), C(3) ]
    >>> AL = AttributableList( Cs )
    >>> print(AL.i)
    [1, 2, 3]

*Method `AttributableList.__init__(self, initlist=None, strict=False)`*:
Initialise the list.

The optional parameter `initlist` initialises the list
as for a normal list.

The optional parameter `strict`, if true, causes list elements
lacking the attribute to raise an AttributeError. If false,
list elements without the attribute are omitted from the results.

## Function `column_name_to_identifier(column_name, snake_case=False)`

The default function used to convert raw column names in
`named_row_tuple`, for example from a CSV file, into Python
indentifiers.

If `snake_case` is true (default `False`) produce snake cased
identifiers instead of merely lowercased identifiers.
This means that something like 'redLines' will become `red_lines`
instead of `redlines`.

## Function `dicts_to_namedtuples(dicts, class_name, keys=None)`

Scan an iterable of `dict`s,
yield a sequence of `namedtuple`s derived from them.

Parameters:
* `dicts`: the `dict`s to scan and convert, an iterable
* `class_name`: the name for the new `namedtuple` class
* `keys`: optional iterable of `dict` keys of interest;
  if omitted then the `dicts` are scanned in order to learn the keys

Note that if `keys` is not specified
this generator prescans the `dicts` in order to learn their keys.
As a consequence, all the `dicts` will be kept in memory
and no `namedtuple`s will be yielded until after that prescan completes.

## Class `FallbackDict(collections.defaultdict, builtins.dict)`

A dictlike object that inherits from another dictlike object;
this is a convenience subclass of `defaultdict`.

## Class `IndexedMapping(IndexedSetMixin)`

Interface to a mapping with `IndexedSetMixin` style `.by_*` attributes.

*Method `IndexedMapping.__init__(self, mapping=None, pk='id')`*:
Initialise the `IndexedMapping`.

Parameters:
* `mapping`: the mapping to wrap; a new `dict` will be made if not specified
* `pk`: the primary key of the mapping, default `'id'`

## Class `IndexedSetMixin`

A base mixin to provide `.by_`* attributes
which index records from an autoloaded backing store,
which might be a file or might be another related data structure.
The records are themselves key->value mappings, such as `dict`s.

The primary key name is provided by the `.IndexedSetMixin__pk`
class attribute, to be provided by subclasses.

Note that this mixin keeps the entire loadable mapping in memory.

Note that this does not see subsequent changes to loaded records
i.e. changing the value of some record[k]
does not update the index associated with the .by_k attribute.

Subclasses must provide the following attributes and methods:
* `IndexedSetMixin__pk`: the name of the primary key;
  it is an error for multiple records to have the same primary key
* `scan`: a generator method to scan the backing store
  and yield records, used for the inital load of the mapping
* `add_backend(record)`: add a new record to the backing store;
  this is called from the `.add(record)` method
  after indexing to persist the record in the backing store

See `UUIDNDJSONMapping` and `UUIDedDict` for an example subclass
indexing records from a newline delimited JSON file.

## Class `JSONableMappingMixin`

Provide `.from_json()`, `.as_json()` and `.append_ndjson()` methods,
and `__str__=as_json` and a `__repr__`.

## Class `MappingChain`

A mapping interface to a sequence of mappings.

It does not support `__setitem__` at present;
that is expected to be managed via the backing mappings.

*Method `MappingChain.__init__(self, mappings=None, get_mappings=None)`*:
Initialise the MappingChain.

Parameters:
* `mappings`: initial sequence of mappings, default None.
* `get_mappings`: callable to obtain the initial sequence of

Exactly one of `mappings` or `get_mappings` must be provided.

## Class `MethodicalList(AttributableList, builtins.list)`

A MethodicalList subclasses a list and maps unimplemented attributes
into a callable which calls the corresponding method on each list members
and returns you a new `MethodicalList` with the results, ready for a
further dereference.

Example:

    >>> n = 1
    >>> class C(object):
    ...   def __init__(self):
    ...     global n
    ...     self.n = n
    ...     n += 1
    ...   def x(self):
    ...     return self.n
    ...
    >>> Cs=[ C(), C(), C() ]
    >>> ML = MethodicalList( Cs )
    >>> print(ML.x())
    [1, 2, 3]

*Method `MethodicalList.__init__(self, initlist=None, strict=False)`*:
Initialise the list.

The optional parameter `initlist` initialises the list
as for a normal list.

The optional parameter `strict`, if true, causes list elements
lacking the attribute to raise an AttributeError. If false,
list elements without the attribute are omitted from the results.

## Function `named_column_tuples(rows, class_name=None, column_names=None, computed=None, preprocess=None, mixin=None, snake_case=False)`

Process an iterable of data rows, usually with the first row being
column names.
Return a generated `namedtuple` factory (the row class)
and an iterable of instances of the namedtuples for each row.

Parameters:
* `rows`: an iterable of rows, each an iterable of data values.
* `class_name`: option class name for the namedtuple class
* `column_names`: optional iterable of column names used as the basis for
  the namedtuple. If this is not provided then the first row from
  `rows` is taken to be the column names.
* `computed`: optional mapping of str to functions of `self`
* `preprocess`: optional callable to modify CSV rows before
  they are converted into the namedtuple.  It receives a context
  object an the data row.
  It should return the row (possibly modified), or `None` to drop the
  row.
* `mixin`: an optional mixin class for the generated `namedtuple` subclass
  to provide extra methods or properties

The context object passed to `preprocess` has the following attributes:
* `.cls`: the generated namedtuple subclass;
  this is useful for obtaining things like the column names
  or column indices;
  this is `None` when preprocessing the header row, if any
* `.index`: attribute with the row's enumeration, which counts from `0`
* `.previous`: the previously accepted row's `namedtuple`,
  or `None` if there is no previous row;
  this is useful for differencing

Rows may be flat iterables in the same order as the column names
or mappings keyed on the column names.

If the column names contain empty strings they are dropped
and the corresponding data row entries are also dropped. This
is very common with spreadsheet exports with unused padding
columns.

Typical human readable column headings, also common in
speadsheet exports, are lowercased and have runs of whitespace
or punctuation turned into single underscores; trailing
underscores then get dropped.

Basic example:

    >>> data1 = [
    ...   ('a', 'b', 'c'),
    ...   (1, 11, "one"),
    ...   (2, 22, "two"),
    ... ]
    >>> rowtype, rows = named_column_tuples(data1)
    >>> print(list(rows))
    [NamedRow(a=1, b=11, c='one'), NamedRow(a=2, b=22, c='two')]

Human readable column headings:

    >>> data1 = [
    ...   ('Index', 'Value Found', 'Descriptive Text'),
    ...   (1, 11, "one"),
    ...   (2, 22, "two"),
    ... ]
    >>> rowtype, rows = named_column_tuples(data1)
    >>> print(list(rows))
    [NamedRow(index=1, value_found=11, descriptive_text='one'), NamedRow(index=2, value_found=22, descriptive_text='two')]

Rows which are mappings:

    >>> data1 = [
    ...   ('a', 'b', 'c'),
    ...   (1, 11, "one"),
    ...   {'a': 2, 'c': "two", 'b': 22},
    ... ]
    >>> rowtype, rows = named_column_tuples(data1)
    >>> print(list(rows))
    [NamedRow(a=1, b=11, c='one'), NamedRow(a=2, b=22, c='two')]

CSV export with unused padding columns:

    >>> data1 = [
    ...   ('a', 'b', 'c', '', ''),
    ...   (1, 11, "one"),
    ...   {'a': 2, 'c': "two", 'b': 22},
    ...   [3, 11, "three", '', 'dropped'],
    ... ]
    >>> rowtype, rows = named_column_tuples(data1, 'CSV_Row')
    >>> print(list(rows))
    [CSV_Row(a=1, b=11, c='one'), CSV_Row(a=2, b=22, c='two'), CSV_Row(a=3, b=11, c='three')]

A mixin class providing a `test1` method and a `test2` property:

    >>> class Mixin(object):
    ...   def test1(self):
    ...     return "test1"
    ...   @property
    ...   def test2(self):
    ...     return "test2"
    >>> data1 = [
    ...   ('a', 'b', 'c'),
    ...   (1, 11, "one"),
    ...   {'a': 2, 'c': "two", 'b': 22},
    ... ]
    >>> rowtype, rows = named_column_tuples(data1, mixin=Mixin)
    >>> rows = list(rows)
    >>> rows[0].test1()
    'test1'
    >>> rows[0].test2
    'test2'

## Function `named_row_tuple(*column_names, class_name=None, computed=None, column_map=None, snake_case=False, mixin=None)`

Return a `namedtuple` subclass factory derived from `column_names`.
The primary use case is using the header row of a spreadsheet
to key the data from the subsequent rows.

Parameters:
* `column_names`: an iterable of `str`, such as the heading columns
  of a CSV export
* `class_name`: optional keyword parameter specifying the class name
* `computed`: optional keyword parameter providing a mapping
  of `str` to functions of `self`; these strings are available
  via `__getitem__`
* `mixin`: an optional mixin class for the generated namedtuple subclass
  to provide extra methods or properties

The tuple's attributes are computed by converting all runs
of nonalphanumerics
(as defined by the `re` module's "\W" sequence)
to an underscore, lowercasing and then stripping
leading and trailing underscores.

In addition to the normal numeric indices, the tuple may
also be indexed by the attribute names or the column names.

The new class has the following additional attributes:
* `attributes_`: the attribute names of each tuple in order
* `names_`: the originating name strings
* `name_attributes_`: the computed attribute names corresponding to the
  `names`; there may be empty strings in this list
* `attr_of_`: a mapping of column name to attribute name
* `name_of_`: a mapping of attribute name to column name
* `index_of_`: a mapping of column names and attributes their tuple indices

Examples:

    >>> T = named_row_tuple('Column 1', '', 'Column 3', ' Column 4', 'Column 5 ', '', '', class_name='Example')
    >>> T.attributes_
    ['column_1', 'column_3', 'column_4', 'column_5']
    >>> row = T('val1', 'dropped', 'val3', 4, 5, 6, 7)
    >>> row
    Example(column_1='val1', column_3='val3', column_4=4, column_5=5)

## Class `PrefixedMappingProxy(RemappedMappingProxy)`

A proxy for another mapping
operating on keys commencing with a prefix.

## Class `RemappedMappingProxy`

A proxy for another mapping
with translation functions between the external keys
and the keys used inside the other mapping.

Example:

    >>> proxy = RemappedMappingProxy(
    ...   {},
    ...   lambda key: 'prefix.' + key,
    ...   lambda subkey: cutprefix('prefix.', subkey))
    >>> proxy['key'] = 1
    >>> proxy['key']
    1
    >>> proxy.mapping
    {'prefix.key': 1}
    >>> list(proxy.keys())
    ['key']
    >>> proxy.subkey('key')
    'prefix.key'
    >>> proxy.key('prefix.key')
    'key'

## Class `SeenSet`

A set-like collection with optional backing store file.

## Class `SeqMapUC_Attrs`

A wrapper for a mapping from keys
(matching the regular expression `^[A-Z][A-Z_0-9]*$`)
to tuples.

Attributes matching such a key return the first element
of the sequence (and requires the sequence to have exactly on element).
An attribute `FOOs` or `FOOes`
(ending in a literal 's' or 'es', a plural)
returns the sequence (`FOO` must be a key of the mapping).

## Class `StackableValues`

A collection of named stackable values with the latest value
available as an attribute.

*DEPRECATED*: I now recommend my `cs.context.stackattrs` context
manager for most uses; it may be applied to any object instead of
requiring use of this class.

Note that names conflicting with methods are not available
as attributes and must be accessed via `__getitem__`.
As a matter of practice, in addition to the mapping methods,
avoid names which are verbs or which begin with an underscore.

Example:

    >>> S = StackableValues()
    >>> print(S)
    StackableValues()
    >>> S.push('x', 1)
    >>> print(S)
    StackableValues(x=1)
    >>> print(S.x)
    1
    >>> S.push('x', 2)
    1
    >>> print(S.x)
    2
    >>> S.x = 3
    >>> print(S.x)
    3
    >>> S.pop('x')
    3
    >>> print(S.x)
    1
    >>> with S.stack(x=4):
    ...   print(S.x)
    ...
    4
    >>> print(S.x)
    1
    >>> S.update(x=5)
    {'x': 1}

## Class `StrKeyedDefaultDict(TypedKeyMixin, collections.defaultdict, builtins.dict)`

Subclass of `defaultdict` which ensures that its
keys are of type `str` using `TypedKeyMixin`.

*Method `StrKeyedDefaultDict.__init__(self, *a, **kw)`*:
Initialise the `TypedKeyDict`. The first positional parameter
is the type for keys.

## Class `StrKeyedDict(TypedKeyMixin, builtins.dict)`

Subclass of `dict` which ensures that its
keys are of type `str` using `TypedKeyMixin`.

*Method `StrKeyedDict.__init__(self, *a, **kw)`*:
Initialise the `TypedKeyDict`. The first positional parameter
is the type for keys.

## Function `TypedKeyClass(key_type, superclass, name=None)`

Factory to create a new mapping class subclassing
`(TypedKeyMixin,superclass)` which checks that keys are of type
`key_type`.

## Class `TypedKeyMixin`

A mixin to check that the keys of a mapping are of a particular type.

The triggering use case is the constant UUID vs str(UUID) tension
in a lot of database code.

## Class `UC_Sequence(builtins.list)`

A tuple-of-nodes on which `.ATTRs` indirection can be done,
yielding another tuple-of-nodes or tuple-of-values.

*Method `UC_Sequence.__init__(self, Ns)`*:
Initialise from an iterable sequence.

## Class `UUIDedDict(builtins.dict, JSONableMappingMixin, AttrableMappingMixin)`

A handy `dict` subtype providing the basis for mapping classes
indexed by `UUID`s.

The `'uuid'` attribute is always a `UUID` instance.

*Method `UUIDedDict.__init__(self, _d=None, **kw)`*:
Initialise the `UUIDedDict`,
generating a `'uuid'` key value if omitted.

## Class `UUIDKeyedDefaultDict(TypedKeyMixin, collections.defaultdict, builtins.dict)`

Subclass of `defaultdict` which ensures that its
keys are of type `UUID` using `TypedKeyMixin`.

*Method `UUIDKeyedDefaultDict.__init__(self, *a, **kw)`*:
Initialise the `TypedKeyDict`. The first positional parameter
is the type for keys.

## Class `UUIDKeyedDict(TypedKeyMixin, builtins.dict)`

Subclass of `dict` which ensures that its
keys are of type `UUID` using `TypedKeyMixin`.

*Method `UUIDKeyedDict.__init__(self, *a, **kw)`*:
Initialise the `TypedKeyDict`. The first positional parameter
is the type for keys.

# Release Log



*Release 20231129*:
AttrableMappingMixin: look up ATTRABLE_MAPPING_DEFAULT on the class, not the instance.

*Release 20230612*:
* AttrableMappingMixin.__getattr__: fast path the check for "ATTRABLE_MAPPING_DEFAULT", fixes unbound recursion.
* New attrable() function returning an object with dicts transmuted to AttrableMapping instances.

*Release 20220912.4*:
* TypedKeyMixin: add .get() and .setdefault().
* Provide names for UUIDKeyedDict, StrKeyedDefaultDict, UUIDKeyedDefaultDict.

*Release 20220912.3*:
* New TypedKeyClass class factory.
* Redo StrKeyedDict and UUIDKeyedDict using TypedKeyClass.
* New StrKeyedDefaultDict and UUIDKeyedDefaultDict convenience classes.

*Release 20220912.2*:
TypedKeyMixin: fix another typo.

*Release 20220912.1*:
TypedKeyMixin: remove debug, bugfix super() calls.

*Release 20220912*:
* New TypedKeyMixin to check that the keys of a mapping are of a particular type.
* New TypedKeyDict(TypedKeyMixin,dict) subclass.
* New StrKeyedDict and UUIDKeyedDict factories.

*Release 20220626*:
Expose the default column name mapping function of named_row_tuple as column_name_to_identifier for reuse.

*Release 20220605*:
* named_row_tuple et al: plumb a new optional snake_case parameter to snake case mixed case attribute names.
* Drop Python 2 support and the cs.py3 shims.

*Release 20220318*:
Bump cs.sharedfile requirement to get an import fix.

*Release 20211208*:
* PrefixedMappingProxy: swap to_subkey/from_subkey prefix/unprefix actions, were backwards.
* PrefixedMappingProxy: make the key and subkey conversion methods public static methods for reuse.
* Assorted minor internal changes.

*Release 20210906*:
New RemappedMappingProxy with general subkey(key) and key(subkey) methods.

*Release 20210717*:
* New IndexedMapping: wrapper for another mapping providing LoadableMappingMixin stype .by_* attributes.
* Rename LoadableMappingMixin to IndexedSetMixin and make it abstract, rename .scan_mapping to .scan, .add_to_mapping to .add etc.

*Release 20210306*:
StackableValues: fix typo, make deprecation overt.

*Release 20210123*:
AttrableMappingMixin.__getattr__: some bugfixes.

*Release 20201228*:
New PrefixedMappingProxy presenting the keys of another mapping commencing with a prefix.

*Release 20201102*:
* StackableValues is obsolete, add recommendation for cs.context.stackattrs to the docstring.
* New AttrableMappingMixin with a __getattr__ which looks up unknown attributes as keys.
* New JSONableMappingMixin with methods for JSON actions: from_json, as_json, append_ndjson and a __str__ and __repr__.
* New LoadableMappingMixin to load .by_* attributes on demand.
* New AttrableMapping(dict, AttrableMappingMixin).

*Release 20200130*:
New dicts_to_namedtuples function to yield namedtuples from an iterable of dicts.

*Release 20191120*:
named_row_tuple: support None in a column name, as from Excel unfilled heading row entries

*Release 20190617*:
* StackableValues.push now returns the previous value.
* StackableValues.update has a signature like dict.update.
* StackableValues.pop removes entries when their stack becomes empty.
* StackableValues.stack: clean implementation of save/restore.
* StackableValues: avoid infinite recursion through ._fallback.
* StackableValues.keys now returns a list of the nonempty keys.
* Update doctests.

*Release 20190103*:
Documentation update.

*Release 20181231*:
* Bugfix for mapping of column names to row indices.
* New subclass._fallback method for when a stack is empty.

*Release 20180720*:
Initial PyPI release specificly for named_column_tuple and named_column_tuples.

            

Raw data

            {
    "_id": null,
    "home_page": "https://bitbucket.org/cameron_simpson/css/commits/all",
    "name": "cs.mappings",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "python2,python3",
    "author": "Cameron Simpson",
    "author_email": "Cameron Simpson <cs@cskk.id.au>",
    "download_url": "https://files.pythonhosted.org/packages/40/01/5e821b7ed750d9e20a89b67180931eb58c5cc76260fdf9b4250e4d0d06af/cs.mappings-20231129.tar.gz",
    "platform": null,
    "description": "Facilities for mappings and objects associated with mappings.\n\n*Latest release 20231129*:\nAttrableMappingMixin: look up ATTRABLE_MAPPING_DEFAULT on the class, not the instance.\n\nIn particular `named_column_tuple(column_names)`,\na function returning a factory\nfor namedtuples subclasses derived from the supplied column names,\nand `named_column_tuples(rows)`,\na function returning a namedtuple factory and an iterable of instances\ncontaining the row data.\nThese are used by the `csv_import` and `xl_import` functions\nfrom `cs.csvutils`.\n\n## Function `attrable(o)`\n\nLike `jsonable`, return `o` with `dicts` replaced by `AttrableMapping`s.\n\n## Class `AttrableMapping(builtins.dict, AttrableMappingMixin)`\n\nA `dict` subclass using `AttrableMappingMixin`.\n\n## Class `AttrableMappingMixin`\n\nProvides a `__getattr__` which accesses the mapping value.\n\n## Class `AttributableList(builtins.list)`\n\nAn `AttributableList` maps unimplemented attributes\nonto the list members and returns you a new `AttributableList`\nwith the results, ready for a further dereference.\n\nExample:\n\n    >>> class C(object):\n    ...   def __init__(self, i):\n    ...     self.i = i\n    >>> Cs = [ C(1), C(2), C(3) ]\n    >>> AL = AttributableList( Cs )\n    >>> print(AL.i)\n    [1, 2, 3]\n\n*Method `AttributableList.__init__(self, initlist=None, strict=False)`*:\nInitialise the list.\n\nThe optional parameter `initlist` initialises the list\nas for a normal list.\n\nThe optional parameter `strict`, if true, causes list elements\nlacking the attribute to raise an AttributeError. If false,\nlist elements without the attribute are omitted from the results.\n\n## Function `column_name_to_identifier(column_name, snake_case=False)`\n\nThe default function used to convert raw column names in\n`named_row_tuple`, for example from a CSV file, into Python\nindentifiers.\n\nIf `snake_case` is true (default `False`) produce snake cased\nidentifiers instead of merely lowercased identifiers.\nThis means that something like 'redLines' will become `red_lines`\ninstead of `redlines`.\n\n## Function `dicts_to_namedtuples(dicts, class_name, keys=None)`\n\nScan an iterable of `dict`s,\nyield a sequence of `namedtuple`s derived from them.\n\nParameters:\n* `dicts`: the `dict`s to scan and convert, an iterable\n* `class_name`: the name for the new `namedtuple` class\n* `keys`: optional iterable of `dict` keys of interest;\n  if omitted then the `dicts` are scanned in order to learn the keys\n\nNote that if `keys` is not specified\nthis generator prescans the `dicts` in order to learn their keys.\nAs a consequence, all the `dicts` will be kept in memory\nand no `namedtuple`s will be yielded until after that prescan completes.\n\n## Class `FallbackDict(collections.defaultdict, builtins.dict)`\n\nA dictlike object that inherits from another dictlike object;\nthis is a convenience subclass of `defaultdict`.\n\n## Class `IndexedMapping(IndexedSetMixin)`\n\nInterface to a mapping with `IndexedSetMixin` style `.by_*` attributes.\n\n*Method `IndexedMapping.__init__(self, mapping=None, pk='id')`*:\nInitialise the `IndexedMapping`.\n\nParameters:\n* `mapping`: the mapping to wrap; a new `dict` will be made if not specified\n* `pk`: the primary key of the mapping, default `'id'`\n\n## Class `IndexedSetMixin`\n\nA base mixin to provide `.by_`* attributes\nwhich index records from an autoloaded backing store,\nwhich might be a file or might be another related data structure.\nThe records are themselves key->value mappings, such as `dict`s.\n\nThe primary key name is provided by the `.IndexedSetMixin__pk`\nclass attribute, to be provided by subclasses.\n\nNote that this mixin keeps the entire loadable mapping in memory.\n\nNote that this does not see subsequent changes to loaded records\ni.e. changing the value of some record[k]\ndoes not update the index associated with the .by_k attribute.\n\nSubclasses must provide the following attributes and methods:\n* `IndexedSetMixin__pk`: the name of the primary key;\n  it is an error for multiple records to have the same primary key\n* `scan`: a generator method to scan the backing store\n  and yield records, used for the inital load of the mapping\n* `add_backend(record)`: add a new record to the backing store;\n  this is called from the `.add(record)` method\n  after indexing to persist the record in the backing store\n\nSee `UUIDNDJSONMapping` and `UUIDedDict` for an example subclass\nindexing records from a newline delimited JSON file.\n\n## Class `JSONableMappingMixin`\n\nProvide `.from_json()`, `.as_json()` and `.append_ndjson()` methods,\nand `__str__=as_json` and a `__repr__`.\n\n## Class `MappingChain`\n\nA mapping interface to a sequence of mappings.\n\nIt does not support `__setitem__` at present;\nthat is expected to be managed via the backing mappings.\n\n*Method `MappingChain.__init__(self, mappings=None, get_mappings=None)`*:\nInitialise the MappingChain.\n\nParameters:\n* `mappings`: initial sequence of mappings, default None.\n* `get_mappings`: callable to obtain the initial sequence of\n\nExactly one of `mappings` or `get_mappings` must be provided.\n\n## Class `MethodicalList(AttributableList, builtins.list)`\n\nA MethodicalList subclasses a list and maps unimplemented attributes\ninto a callable which calls the corresponding method on each list members\nand returns you a new `MethodicalList` with the results, ready for a\nfurther dereference.\n\nExample:\n\n    >>> n = 1\n    >>> class C(object):\n    ...   def __init__(self):\n    ...     global n\n    ...     self.n = n\n    ...     n += 1\n    ...   def x(self):\n    ...     return self.n\n    ...\n    >>> Cs=[ C(), C(), C() ]\n    >>> ML = MethodicalList( Cs )\n    >>> print(ML.x())\n    [1, 2, 3]\n\n*Method `MethodicalList.__init__(self, initlist=None, strict=False)`*:\nInitialise the list.\n\nThe optional parameter `initlist` initialises the list\nas for a normal list.\n\nThe optional parameter `strict`, if true, causes list elements\nlacking the attribute to raise an AttributeError. If false,\nlist elements without the attribute are omitted from the results.\n\n## Function `named_column_tuples(rows, class_name=None, column_names=None, computed=None, preprocess=None, mixin=None, snake_case=False)`\n\nProcess an iterable of data rows, usually with the first row being\ncolumn names.\nReturn a generated `namedtuple` factory (the row class)\nand an iterable of instances of the namedtuples for each row.\n\nParameters:\n* `rows`: an iterable of rows, each an iterable of data values.\n* `class_name`: option class name for the namedtuple class\n* `column_names`: optional iterable of column names used as the basis for\n  the namedtuple. If this is not provided then the first row from\n  `rows` is taken to be the column names.\n* `computed`: optional mapping of str to functions of `self`\n* `preprocess`: optional callable to modify CSV rows before\n  they are converted into the namedtuple.  It receives a context\n  object an the data row.\n  It should return the row (possibly modified), or `None` to drop the\n  row.\n* `mixin`: an optional mixin class for the generated `namedtuple` subclass\n  to provide extra methods or properties\n\nThe context object passed to `preprocess` has the following attributes:\n* `.cls`: the generated namedtuple subclass;\n  this is useful for obtaining things like the column names\n  or column indices;\n  this is `None` when preprocessing the header row, if any\n* `.index`: attribute with the row's enumeration, which counts from `0`\n* `.previous`: the previously accepted row's `namedtuple`,\n  or `None` if there is no previous row;\n  this is useful for differencing\n\nRows may be flat iterables in the same order as the column names\nor mappings keyed on the column names.\n\nIf the column names contain empty strings they are dropped\nand the corresponding data row entries are also dropped. This\nis very common with spreadsheet exports with unused padding\ncolumns.\n\nTypical human readable column headings, also common in\nspeadsheet exports, are lowercased and have runs of whitespace\nor punctuation turned into single underscores; trailing\nunderscores then get dropped.\n\nBasic example:\n\n    >>> data1 = [\n    ...   ('a', 'b', 'c'),\n    ...   (1, 11, \"one\"),\n    ...   (2, 22, \"two\"),\n    ... ]\n    >>> rowtype, rows = named_column_tuples(data1)\n    >>> print(list(rows))\n    [NamedRow(a=1, b=11, c='one'), NamedRow(a=2, b=22, c='two')]\n\nHuman readable column headings:\n\n    >>> data1 = [\n    ...   ('Index', 'Value Found', 'Descriptive Text'),\n    ...   (1, 11, \"one\"),\n    ...   (2, 22, \"two\"),\n    ... ]\n    >>> rowtype, rows = named_column_tuples(data1)\n    >>> print(list(rows))\n    [NamedRow(index=1, value_found=11, descriptive_text='one'), NamedRow(index=2, value_found=22, descriptive_text='two')]\n\nRows which are mappings:\n\n    >>> data1 = [\n    ...   ('a', 'b', 'c'),\n    ...   (1, 11, \"one\"),\n    ...   {'a': 2, 'c': \"two\", 'b': 22},\n    ... ]\n    >>> rowtype, rows = named_column_tuples(data1)\n    >>> print(list(rows))\n    [NamedRow(a=1, b=11, c='one'), NamedRow(a=2, b=22, c='two')]\n\nCSV export with unused padding columns:\n\n    >>> data1 = [\n    ...   ('a', 'b', 'c', '', ''),\n    ...   (1, 11, \"one\"),\n    ...   {'a': 2, 'c': \"two\", 'b': 22},\n    ...   [3, 11, \"three\", '', 'dropped'],\n    ... ]\n    >>> rowtype, rows = named_column_tuples(data1, 'CSV_Row')\n    >>> print(list(rows))\n    [CSV_Row(a=1, b=11, c='one'), CSV_Row(a=2, b=22, c='two'), CSV_Row(a=3, b=11, c='three')]\n\nA mixin class providing a `test1` method and a `test2` property:\n\n    >>> class Mixin(object):\n    ...   def test1(self):\n    ...     return \"test1\"\n    ...   @property\n    ...   def test2(self):\n    ...     return \"test2\"\n    >>> data1 = [\n    ...   ('a', 'b', 'c'),\n    ...   (1, 11, \"one\"),\n    ...   {'a': 2, 'c': \"two\", 'b': 22},\n    ... ]\n    >>> rowtype, rows = named_column_tuples(data1, mixin=Mixin)\n    >>> rows = list(rows)\n    >>> rows[0].test1()\n    'test1'\n    >>> rows[0].test2\n    'test2'\n\n## Function `named_row_tuple(*column_names, class_name=None, computed=None, column_map=None, snake_case=False, mixin=None)`\n\nReturn a `namedtuple` subclass factory derived from `column_names`.\nThe primary use case is using the header row of a spreadsheet\nto key the data from the subsequent rows.\n\nParameters:\n* `column_names`: an iterable of `str`, such as the heading columns\n  of a CSV export\n* `class_name`: optional keyword parameter specifying the class name\n* `computed`: optional keyword parameter providing a mapping\n  of `str` to functions of `self`; these strings are available\n  via `__getitem__`\n* `mixin`: an optional mixin class for the generated namedtuple subclass\n  to provide extra methods or properties\n\nThe tuple's attributes are computed by converting all runs\nof nonalphanumerics\n(as defined by the `re` module's \"\\W\" sequence)\nto an underscore, lowercasing and then stripping\nleading and trailing underscores.\n\nIn addition to the normal numeric indices, the tuple may\nalso be indexed by the attribute names or the column names.\n\nThe new class has the following additional attributes:\n* `attributes_`: the attribute names of each tuple in order\n* `names_`: the originating name strings\n* `name_attributes_`: the computed attribute names corresponding to the\n  `names`; there may be empty strings in this list\n* `attr_of_`: a mapping of column name to attribute name\n* `name_of_`: a mapping of attribute name to column name\n* `index_of_`: a mapping of column names and attributes their tuple indices\n\nExamples:\n\n    >>> T = named_row_tuple('Column 1', '', 'Column 3', ' Column 4', 'Column 5 ', '', '', class_name='Example')\n    >>> T.attributes_\n    ['column_1', 'column_3', 'column_4', 'column_5']\n    >>> row = T('val1', 'dropped', 'val3', 4, 5, 6, 7)\n    >>> row\n    Example(column_1='val1', column_3='val3', column_4=4, column_5=5)\n\n## Class `PrefixedMappingProxy(RemappedMappingProxy)`\n\nA proxy for another mapping\noperating on keys commencing with a prefix.\n\n## Class `RemappedMappingProxy`\n\nA proxy for another mapping\nwith translation functions between the external keys\nand the keys used inside the other mapping.\n\nExample:\n\n    >>> proxy = RemappedMappingProxy(\n    ...   {},\n    ...   lambda key: 'prefix.' + key,\n    ...   lambda subkey: cutprefix('prefix.', subkey))\n    >>> proxy['key'] = 1\n    >>> proxy['key']\n    1\n    >>> proxy.mapping\n    {'prefix.key': 1}\n    >>> list(proxy.keys())\n    ['key']\n    >>> proxy.subkey('key')\n    'prefix.key'\n    >>> proxy.key('prefix.key')\n    'key'\n\n## Class `SeenSet`\n\nA set-like collection with optional backing store file.\n\n## Class `SeqMapUC_Attrs`\n\nA wrapper for a mapping from keys\n(matching the regular expression `^[A-Z][A-Z_0-9]*$`)\nto tuples.\n\nAttributes matching such a key return the first element\nof the sequence (and requires the sequence to have exactly on element).\nAn attribute `FOOs` or `FOOes`\n(ending in a literal 's' or 'es', a plural)\nreturns the sequence (`FOO` must be a key of the mapping).\n\n## Class `StackableValues`\n\nA collection of named stackable values with the latest value\navailable as an attribute.\n\n*DEPRECATED*: I now recommend my `cs.context.stackattrs` context\nmanager for most uses; it may be applied to any object instead of\nrequiring use of this class.\n\nNote that names conflicting with methods are not available\nas attributes and must be accessed via `__getitem__`.\nAs a matter of practice, in addition to the mapping methods,\navoid names which are verbs or which begin with an underscore.\n\nExample:\n\n    >>> S = StackableValues()\n    >>> print(S)\n    StackableValues()\n    >>> S.push('x', 1)\n    >>> print(S)\n    StackableValues(x=1)\n    >>> print(S.x)\n    1\n    >>> S.push('x', 2)\n    1\n    >>> print(S.x)\n    2\n    >>> S.x = 3\n    >>> print(S.x)\n    3\n    >>> S.pop('x')\n    3\n    >>> print(S.x)\n    1\n    >>> with S.stack(x=4):\n    ...   print(S.x)\n    ...\n    4\n    >>> print(S.x)\n    1\n    >>> S.update(x=5)\n    {'x': 1}\n\n## Class `StrKeyedDefaultDict(TypedKeyMixin, collections.defaultdict, builtins.dict)`\n\nSubclass of `defaultdict` which ensures that its\nkeys are of type `str` using `TypedKeyMixin`.\n\n*Method `StrKeyedDefaultDict.__init__(self, *a, **kw)`*:\nInitialise the `TypedKeyDict`. The first positional parameter\nis the type for keys.\n\n## Class `StrKeyedDict(TypedKeyMixin, builtins.dict)`\n\nSubclass of `dict` which ensures that its\nkeys are of type `str` using `TypedKeyMixin`.\n\n*Method `StrKeyedDict.__init__(self, *a, **kw)`*:\nInitialise the `TypedKeyDict`. The first positional parameter\nis the type for keys.\n\n## Function `TypedKeyClass(key_type, superclass, name=None)`\n\nFactory to create a new mapping class subclassing\n`(TypedKeyMixin,superclass)` which checks that keys are of type\n`key_type`.\n\n## Class `TypedKeyMixin`\n\nA mixin to check that the keys of a mapping are of a particular type.\n\nThe triggering use case is the constant UUID vs str(UUID) tension\nin a lot of database code.\n\n## Class `UC_Sequence(builtins.list)`\n\nA tuple-of-nodes on which `.ATTRs` indirection can be done,\nyielding another tuple-of-nodes or tuple-of-values.\n\n*Method `UC_Sequence.__init__(self, Ns)`*:\nInitialise from an iterable sequence.\n\n## Class `UUIDedDict(builtins.dict, JSONableMappingMixin, AttrableMappingMixin)`\n\nA handy `dict` subtype providing the basis for mapping classes\nindexed by `UUID`s.\n\nThe `'uuid'` attribute is always a `UUID` instance.\n\n*Method `UUIDedDict.__init__(self, _d=None, **kw)`*:\nInitialise the `UUIDedDict`,\ngenerating a `'uuid'` key value if omitted.\n\n## Class `UUIDKeyedDefaultDict(TypedKeyMixin, collections.defaultdict, builtins.dict)`\n\nSubclass of `defaultdict` which ensures that its\nkeys are of type `UUID` using `TypedKeyMixin`.\n\n*Method `UUIDKeyedDefaultDict.__init__(self, *a, **kw)`*:\nInitialise the `TypedKeyDict`. The first positional parameter\nis the type for keys.\n\n## Class `UUIDKeyedDict(TypedKeyMixin, builtins.dict)`\n\nSubclass of `dict` which ensures that its\nkeys are of type `UUID` using `TypedKeyMixin`.\n\n*Method `UUIDKeyedDict.__init__(self, *a, **kw)`*:\nInitialise the `TypedKeyDict`. The first positional parameter\nis the type for keys.\n\n# Release Log\n\n\n\n*Release 20231129*:\nAttrableMappingMixin: look up ATTRABLE_MAPPING_DEFAULT on the class, not the instance.\n\n*Release 20230612*:\n* AttrableMappingMixin.__getattr__: fast path the check for \"ATTRABLE_MAPPING_DEFAULT\", fixes unbound recursion.\n* New attrable() function returning an object with dicts transmuted to AttrableMapping instances.\n\n*Release 20220912.4*:\n* TypedKeyMixin: add .get() and .setdefault().\n* Provide names for UUIDKeyedDict, StrKeyedDefaultDict, UUIDKeyedDefaultDict.\n\n*Release 20220912.3*:\n* New TypedKeyClass class factory.\n* Redo StrKeyedDict and UUIDKeyedDict using TypedKeyClass.\n* New StrKeyedDefaultDict and UUIDKeyedDefaultDict convenience classes.\n\n*Release 20220912.2*:\nTypedKeyMixin: fix another typo.\n\n*Release 20220912.1*:\nTypedKeyMixin: remove debug, bugfix super() calls.\n\n*Release 20220912*:\n* New TypedKeyMixin to check that the keys of a mapping are of a particular type.\n* New TypedKeyDict(TypedKeyMixin,dict) subclass.\n* New StrKeyedDict and UUIDKeyedDict factories.\n\n*Release 20220626*:\nExpose the default column name mapping function of named_row_tuple as column_name_to_identifier for reuse.\n\n*Release 20220605*:\n* named_row_tuple et al: plumb a new optional snake_case parameter to snake case mixed case attribute names.\n* Drop Python 2 support and the cs.py3 shims.\n\n*Release 20220318*:\nBump cs.sharedfile requirement to get an import fix.\n\n*Release 20211208*:\n* PrefixedMappingProxy: swap to_subkey/from_subkey prefix/unprefix actions, were backwards.\n* PrefixedMappingProxy: make the key and subkey conversion methods public static methods for reuse.\n* Assorted minor internal changes.\n\n*Release 20210906*:\nNew RemappedMappingProxy with general subkey(key) and key(subkey) methods.\n\n*Release 20210717*:\n* New IndexedMapping: wrapper for another mapping providing LoadableMappingMixin stype .by_* attributes.\n* Rename LoadableMappingMixin to IndexedSetMixin and make it abstract, rename .scan_mapping to .scan, .add_to_mapping to .add etc.\n\n*Release 20210306*:\nStackableValues: fix typo, make deprecation overt.\n\n*Release 20210123*:\nAttrableMappingMixin.__getattr__: some bugfixes.\n\n*Release 20201228*:\nNew PrefixedMappingProxy presenting the keys of another mapping commencing with a prefix.\n\n*Release 20201102*:\n* StackableValues is obsolete, add recommendation for cs.context.stackattrs to the docstring.\n* New AttrableMappingMixin with a __getattr__ which looks up unknown attributes as keys.\n* New JSONableMappingMixin with methods for JSON actions: from_json, as_json, append_ndjson and a __str__ and __repr__.\n* New LoadableMappingMixin to load .by_* attributes on demand.\n* New AttrableMapping(dict, AttrableMappingMixin).\n\n*Release 20200130*:\nNew dicts_to_namedtuples function to yield namedtuples from an iterable of dicts.\n\n*Release 20191120*:\nnamed_row_tuple: support None in a column name, as from Excel unfilled heading row entries\n\n*Release 20190617*:\n* StackableValues.push now returns the previous value.\n* StackableValues.update has a signature like dict.update.\n* StackableValues.pop removes entries when their stack becomes empty.\n* StackableValues.stack: clean implementation of save/restore.\n* StackableValues: avoid infinite recursion through ._fallback.\n* StackableValues.keys now returns a list of the nonempty keys.\n* Update doctests.\n\n*Release 20190103*:\nDocumentation update.\n\n*Release 20181231*:\n* Bugfix for mapping of column names to row indices.\n* New subclass._fallback method for when a stack is empty.\n\n*Release 20180720*:\nInitial PyPI release specificly for named_column_tuple and named_column_tuples.\n",
    "bugtrack_url": null,
    "license": "GNU General Public License v3 or later (GPLv3+)",
    "summary": "Facilities for mappings and objects associated with mappings.",
    "version": "20231129",
    "project_urls": {
        "Homepage": "https://bitbucket.org/cameron_simpson/css/commits/all",
        "URL": "https://bitbucket.org/cameron_simpson/css/commits/all"
    },
    "split_keywords": [
        "python2",
        "python3"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d6a8019e5e9998480e73e1d66e8f17bf111b47051fbaf64d0097cea7a6570f1a",
                "md5": "fc8a366f750a3bd49f0bb949ea69cb7c",
                "sha256": "14b62424c6126146ba8be86986a9a86a420ef01542a4a6da8eed23e1b310bc83"
            },
            "downloads": -1,
            "filename": "cs.mappings-20231129-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fc8a366f750a3bd49f0bb949ea69cb7c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 20227,
            "upload_time": "2023-11-29T09:10:08",
            "upload_time_iso_8601": "2023-11-29T09:10:08.351065Z",
            "url": "https://files.pythonhosted.org/packages/d6/a8/019e5e9998480e73e1d66e8f17bf111b47051fbaf64d0097cea7a6570f1a/cs.mappings-20231129-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "40015e821b7ed750d9e20a89b67180931eb58c5cc76260fdf9b4250e4d0d06af",
                "md5": "f35c2e7679c26760118a1a306cfc888c",
                "sha256": "7d0a9dcfbbd8e088c8e610174d21ac6a9ef3e3e9d06b80011e7adeb48ccc979e"
            },
            "downloads": -1,
            "filename": "cs.mappings-20231129.tar.gz",
            "has_sig": false,
            "md5_digest": "f35c2e7679c26760118a1a306cfc888c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 26150,
            "upload_time": "2023-11-29T09:10:10",
            "upload_time_iso_8601": "2023-11-29T09:10:10.940728Z",
            "url": "https://files.pythonhosted.org/packages/40/01/5e821b7ed750d9e20a89b67180931eb58c5cc76260fdf9b4250e4d0d06af/cs.mappings-20231129.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-29 09:10:10",
    "github": false,
    "gitlab": false,
    "bitbucket": true,
    "codeberg": false,
    "bitbucket_user": "cameron_simpson",
    "bitbucket_project": "css",
    "lcname": "cs.mappings"
}
        
Elapsed time: 3.38270s