#!/usr/bin/env python
from setuptools import setup
setup(
  name = 'cs.mappings',
  description = 'Facilities for mappings and objects associated with mappings.',
  author = 'Cameron Simpson',
  author_email = 'cs@cskk.id.au',
  version = '20191120',
  url = 'https://bitbucket.org/cameron_simpson/css/commits/all',
  classifiers = ['Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'Operating System :: OS Independent', 'Topic :: Software Development :: Libraries :: Python Modules', 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)'],
  include_package_data = True,
  install_requires = ['cs.lex', 'cs.logutils', 'cs.pfx', 'cs.py3', 'cs.seq', 'cs.sharedfile'],
  keywords = ['python2', 'python3'],
  license = 'GNU General Public License v3 or later (GPLv3+)',
  long_description = '*Latest release 20191120*:\nnamed_row_tuple: support None in a column name, as from Excel unfilled heading row entries\n\nFacilities for mappings and objects associated with mappings.\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## Class `AttributableList`\n\nMRO: `builtins.list`  \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)`\n\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## Class `FallbackDict`\n\nMRO: `collections.defaultdict`, `builtins.dict`  \nA dictlike object that inherits from another dictlike object;\nthis is a convenience subclass of `defaultdict`.\n\n### Method `FallbackDict.__init__(self, otherdict)`\n\n\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)`\n\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`\n\nMRO: `AttributableList`, `builtins.list`  \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)`\n\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)`\n\nProcess an iterable of data rows, usually with the first row being\ncolumn names.\nReturn a generated namedtuple factory and an iterable\nof 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`: attribute with 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\nRows may be flat iterables in the same order as the column\nnames or 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    >>> cls, 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    >>> cls, 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    >>> cls, 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    >>> cls, 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    >>> cls, 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, **kw)`\n\nReturn a namedtuple subclass factory derived from `column_names`.\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 `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\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 `UC_Sequence`\n\nMRO: `builtins.list`  \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)`\n\nInitialise from an iterable sequence.\n\n\n\n# Release Log\n\n*Release 20191120*:\nnamed_row_tuple: support None in a column name, as from Excel unfilled heading row entries\n\n*Release 20190617*:\nStackableValues.push now returns the previous value.\nStackableValues.update has a signature like dict.update.\nStackableValues.pop removes entries when their stack becomes empty.\nStackableValues.stack: clean implementation of save/restore.\nStackableValues: avoid infinite recursion through ._fallback.\nStackableValues.keys now returns a list of the nonempty keys.\nUpdate doctests.\n\n*Release 20190103*:\nDocumentation update.\n\n*Release 20181231*:\nBugfix for mapping of column names to row indices.\nNew 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.',
  long_description_content_type = 'text/markdown',
  package_dir = {'': 'lib/python'},
  py_modules = ['cs.mappings'],
)
