unpact


Nameunpact JSON
Version 0.0.13 PyPI version JSON
download
home_page
SummaryA lightweight library for tabulating dictionaries
upload_time2024-02-23 19:56:19
maintainer
docs_urlNone
authorMoph Toyer
requires_python>=3.9,<4.0
licenseMIT
keywords tables formatting flat flattening json
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # unpact

A lightweight library for tabulating dictionaries.

![Coverage](https://unpact.s3.amazonaws.com/coverage.svg)

## Usage

A basic example:

```python
from unpact import unwind, ColumnDef

columns: List[ColumnDef] = [
    'calendar.year',
    'calendar.date',
    'locations.location',
    'locations.x',
    'locations.y'
]

 # columns of the same child and the same length are considered 'adjacent'
 # adjacent columns are zipped together.
 # here, 'x' and 'y' are considered 'adjacent'
data = {
    'calendar': {'year': 2022, 'date': 'Aug 14'},
    'locations': [
        {'location': 'Loc1', 'x': [1,2,3,4], 'y': [1,2,3,4]},
        {'location': 'Loc2', 'x': [11,22,33,44], 'y': [11,22,33,44]},
        {'location': 'Loc3', 'x': [11], 'y': [11]},
    ],
    'ignored': "This isn't in the ColumDefs so won't be included"
}

table = unwind(data, columns)
print(pl.from_dicts(table))

--
shape: (9, 5)
┌──────┬────────┬──────────┬─────┬─────┐
│ year ┆ date   ┆ location ┆ x   ┆ y   │
│ ---  ┆ ---    ┆ ---      ┆ --- ┆ --- │
│ i64  ┆ str    ┆ str      ┆ i64 ┆ i64 │
╞══════╪════════╪══════════╪═════╪═════╡
│ 2022 ┆ Aug 14 ┆ Loc1     ┆ 1   ┆ 1   │
│ 2022 ┆ Aug 14 ┆ Loc1     ┆ 2   ┆ 2   │
│ 2022 ┆ Aug 14 ┆ Loc1     ┆ 3   ┆ 3   │
│ 2022 ┆ Aug 14 ┆ Loc1     ┆ 4   ┆ 4   │
│ 2022 ┆ Aug 14 ┆ Loc2     ┆ 11  ┆ 11  │
│ 2022 ┆ Aug 14 ┆ Loc2     ┆ 22  ┆ 22  │
│ 2022 ┆ Aug 14 ┆ Loc2     ┆ 33  ┆ 33  │
│ 2022 ┆ Aug 14 ┆ Loc2     ┆ 44  ┆ 44  │
│ 2022 ┆ Aug 14 ┆ Loc2     ┆ 11  ┆ 11  │
└──────┴────────┴──────────┴─────┴─────┘
```

A more complex example using ColumnSpecs:

```python
import polars as pl
from unpact import unwind, ColumnDef

# You can pass in a pass in a 'ColumnSpec' to change the behavior of a column
# current values are 'formatter' which accepts a callable and 'name', a string which will rename the column
columns: List[ColumnDef] = [
    'calendar.year',
    'calendar.date',
    ('locations.location', {'name': 'loc'}),
    ('locations.coords', {'formatter': lambda coords: {'x': coords[0], 'y': coords[1]}})
]

data = {
    'calendar': {'year': 2022, 'date': 'Aug 14'},
    'locations': [
        {'location': 'Loc1', 'coords': [[1,1], [2,2], [3,3]]},
        {'location': 'Loc2', 'coords': [[1,1], [2,2], [3,3]]},
        {'location': 'Loc3', 'coords': [[1,1], [2,2], [3,3]]},
    ],
    'ignored': "This isn't in the ColumDefs so won't be included"
}

table = unwind(data, columns)
print(pl.from_dicts(table))

---
shape: (9, 5)
┌──────┬────────┬──────┬─────┬─────┐
│ year ┆ date   ┆ loc  ┆ x   ┆ y   │
│ ---  ┆ ---    ┆ ---  ┆ --- ┆ --- │
│ i64  ┆ str    ┆ str  ┆ i64 ┆ i64 │
╞══════╪════════╪══════╪═════╪═════╡
│ 2022 ┆ Aug 14 ┆ Loc1 ┆ 1   ┆ 1   │
│ 2022 ┆ Aug 14 ┆ Loc1 ┆ 2   ┆ 2   │
│ 2022 ┆ Aug 14 ┆ Loc1 ┆ 3   ┆ 3   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 1   ┆ 1   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 2   ┆ 2   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 3   ┆ 3   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 1   ┆ 1   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 2   ┆ 2   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 3   ┆ 3   │
└──────┴────────┴──────┴─────┴─────┘

```

A demonstration showing 'adjacency' at multiple levels of nesting:

```python

columns: List[ColumnDef] = [
    'calendar.year',
    'calendar.date',
    ('locations_1.location', {'name': 'loc'}),
    ('locations_1.coords', {'formatter': lambda coords: {'x': coords[0], 'y': coords[1]}}),
    ('locations_2.location', {'name': 'loc'}),
    ('locations_2.coords', {'formatter': lambda coords: {'x': coords[0], 'y': coords[1]}})
]

data = {
    'calendar': {'year': 2022, 'date': 'Aug 14'},
    'locations_1': [
        {'location': 'Loc1', 'coords': [[1,1], [2,2], [3,3]]},
        {'location': 'Loc2', 'coords': [[1,1], [2,2], [3,3]]},
    ],
    'locations_2': [
        {'location': 'Loc3', 'coords': [[1,1], [2,2], [3,3]]},
        {'location': 'Loc4', 'coords': [[1,1], [2,2], [3,3]]},
    ],
    'ignored': "This isn't in the ColumDefs so won't be included"
}

table = unwind(data, columns)
assert len(table) == 12 # 3 rows per record, 4 records
print(pl.from_dicts(table))

---
shape: (12, 5)
┌──────┬────────┬──────┬─────┬─────┐
│ year ┆ date   ┆ loc  ┆ x   ┆ y   │
│ ---  ┆ ---    ┆ ---  ┆ --- ┆ --- │
│ i64  ┆ str    ┆ str  ┆ i64 ┆ i64 │
╞══════╪════════╪══════╪═════╪═════╡
│ 2022 ┆ Aug 14 ┆ Loc1 ┆ 1   ┆ 1   │
│ 2022 ┆ Aug 14 ┆ Loc1 ┆ 2   ┆ 2   │
│ 2022 ┆ Aug 14 ┆ Loc1 ┆ 3   ┆ 3   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 1   ┆ 1   │
│ …    ┆ …      ┆ …    ┆ …   ┆ …   │
│ 2022 ┆ Aug 14 ┆ Loc1 ┆ 3   ┆ 3   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 1   ┆ 1   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 2   ┆ 2   │
│ 2022 ┆ Aug 14 ┆ Loc2 ┆ 3   ┆ 3   │
└──────┴────────┴──────┴─────┴─────┘

```

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "unpact",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9,<4.0",
    "maintainer_email": "",
    "keywords": "tables,formatting,flat,flattening,json",
    "author": "Moph Toyer",
    "author_email": "chris@telemetry.fm",
    "download_url": "https://files.pythonhosted.org/packages/76/ed/16f36a107b6c3e69b531dda039442b53b1ed5fae11e1bffde5757d849c77/unpact-0.0.13.tar.gz",
    "platform": null,
    "description": "# unpact\n\nA lightweight library for tabulating dictionaries.\n\n![Coverage](https://unpact.s3.amazonaws.com/coverage.svg)\n\n## Usage\n\nA basic example:\n\n```python\nfrom unpact import unwind, ColumnDef\n\ncolumns: List[ColumnDef] = [\n    'calendar.year',\n    'calendar.date',\n    'locations.location',\n    'locations.x',\n    'locations.y'\n]\n\n # columns of the same child and the same length are considered 'adjacent'\n # adjacent columns are zipped together.\n # here, 'x' and 'y' are considered 'adjacent'\ndata = {\n    'calendar': {'year': 2022, 'date': 'Aug 14'},\n    'locations': [\n        {'location': 'Loc1', 'x': [1,2,3,4], 'y': [1,2,3,4]},\n        {'location': 'Loc2', 'x': [11,22,33,44], 'y': [11,22,33,44]},\n        {'location': 'Loc3', 'x': [11], 'y': [11]},\n    ],\n    'ignored': \"This isn't in the ColumDefs so won't be included\"\n}\n\ntable = unwind(data, columns)\nprint(pl.from_dicts(table))\n\n--\nshape: (9, 5)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 year \u2506 date   \u2506 location \u2506 x   \u2506 y   \u2502\n\u2502 ---  \u2506 ---    \u2506 ---      \u2506 --- \u2506 --- \u2502\n\u2502 i64  \u2506 str    \u2506 str      \u2506 i64 \u2506 i64 \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1     \u2506 1   \u2506 1   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1     \u2506 2   \u2506 2   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1     \u2506 3   \u2506 3   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1     \u2506 4   \u2506 4   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2     \u2506 11  \u2506 11  \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2     \u2506 22  \u2506 22  \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2     \u2506 33  \u2506 33  \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2     \u2506 44  \u2506 44  \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2     \u2506 11  \u2506 11  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\nA more complex example using ColumnSpecs:\n\n```python\nimport polars as pl\nfrom unpact import unwind, ColumnDef\n\n# You can pass in a pass in a 'ColumnSpec' to change the behavior of a column\n# current values are 'formatter' which accepts a callable and 'name', a string which will rename the column\ncolumns: List[ColumnDef] = [\n    'calendar.year',\n    'calendar.date',\n    ('locations.location', {'name': 'loc'}),\n    ('locations.coords', {'formatter': lambda coords: {'x': coords[0], 'y': coords[1]}})\n]\n\ndata = {\n    'calendar': {'year': 2022, 'date': 'Aug 14'},\n    'locations': [\n        {'location': 'Loc1', 'coords': [[1,1], [2,2], [3,3]]},\n        {'location': 'Loc2', 'coords': [[1,1], [2,2], [3,3]]},\n        {'location': 'Loc3', 'coords': [[1,1], [2,2], [3,3]]},\n    ],\n    'ignored': \"This isn't in the ColumDefs so won't be included\"\n}\n\ntable = unwind(data, columns)\nprint(pl.from_dicts(table))\n\n---\nshape: (9, 5)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 year \u2506 date   \u2506 loc  \u2506 x   \u2506 y   \u2502\n\u2502 ---  \u2506 ---    \u2506 ---  \u2506 --- \u2506 --- \u2502\n\u2502 i64  \u2506 str    \u2506 str  \u2506 i64 \u2506 i64 \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1 \u2506 1   \u2506 1   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1 \u2506 2   \u2506 2   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1 \u2506 3   \u2506 3   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 1   \u2506 1   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 2   \u2506 2   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 3   \u2506 3   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 1   \u2506 1   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 2   \u2506 2   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 3   \u2506 3   \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2518\n\n```\n\nA demonstration showing 'adjacency' at multiple levels of nesting:\n\n```python\n\ncolumns: List[ColumnDef] = [\n    'calendar.year',\n    'calendar.date',\n    ('locations_1.location', {'name': 'loc'}),\n    ('locations_1.coords', {'formatter': lambda coords: {'x': coords[0], 'y': coords[1]}}),\n    ('locations_2.location', {'name': 'loc'}),\n    ('locations_2.coords', {'formatter': lambda coords: {'x': coords[0], 'y': coords[1]}})\n]\n\ndata = {\n    'calendar': {'year': 2022, 'date': 'Aug 14'},\n    'locations_1': [\n        {'location': 'Loc1', 'coords': [[1,1], [2,2], [3,3]]},\n        {'location': 'Loc2', 'coords': [[1,1], [2,2], [3,3]]},\n    ],\n    'locations_2': [\n        {'location': 'Loc3', 'coords': [[1,1], [2,2], [3,3]]},\n        {'location': 'Loc4', 'coords': [[1,1], [2,2], [3,3]]},\n    ],\n    'ignored': \"This isn't in the ColumDefs so won't be included\"\n}\n\ntable = unwind(data, columns)\nassert len(table) == 12 # 3 rows per record, 4 records\nprint(pl.from_dicts(table))\n\n---\nshape: (12, 5)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 year \u2506 date   \u2506 loc  \u2506 x   \u2506 y   \u2502\n\u2502 ---  \u2506 ---    \u2506 ---  \u2506 --- \u2506 --- \u2502\n\u2502 i64  \u2506 str    \u2506 str  \u2506 i64 \u2506 i64 \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1 \u2506 1   \u2506 1   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1 \u2506 2   \u2506 2   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1 \u2506 3   \u2506 3   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 1   \u2506 1   \u2502\n\u2502 \u2026    \u2506 \u2026      \u2506 \u2026    \u2506 \u2026   \u2506 \u2026   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1 \u2506 3   \u2506 3   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 1   \u2506 1   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 2   \u2506 2   \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2 \u2506 3   \u2506 3   \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2518\n\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A lightweight library for tabulating dictionaries",
    "version": "0.0.13",
    "project_urls": null,
    "split_keywords": [
        "tables",
        "formatting",
        "flat",
        "flattening",
        "json"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4be4cf76b524125e6f3ac032bfac42b8736635272345bcabf4f28634ae2f27f8",
                "md5": "742cd08bf9fe65988360c86e931b025b",
                "sha256": "ae337d3b5056afe5f022ee148d1dc80bdbea1a4893f5c3647bfb3e9895375f11"
            },
            "downloads": -1,
            "filename": "unpact-0.0.13-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "742cd08bf9fe65988360c86e931b025b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9,<4.0",
            "size": 6650,
            "upload_time": "2024-02-23T19:56:17",
            "upload_time_iso_8601": "2024-02-23T19:56:17.878340Z",
            "url": "https://files.pythonhosted.org/packages/4b/e4/cf76b524125e6f3ac032bfac42b8736635272345bcabf4f28634ae2f27f8/unpact-0.0.13-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "76ed16f36a107b6c3e69b531dda039442b53b1ed5fae11e1bffde5757d849c77",
                "md5": "8e51964309c0653b2d86dfcc2bdc7898",
                "sha256": "fd7f540c09fd17d3d6db8cee6f3490f03ca6d22d6df4a8e579a2344a2f177b43"
            },
            "downloads": -1,
            "filename": "unpact-0.0.13.tar.gz",
            "has_sig": false,
            "md5_digest": "8e51964309c0653b2d86dfcc2bdc7898",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9,<4.0",
            "size": 5840,
            "upload_time": "2024-02-23T19:56:19",
            "upload_time_iso_8601": "2024-02-23T19:56:19.930370Z",
            "url": "https://files.pythonhosted.org/packages/76/ed/16f36a107b6c3e69b531dda039442b53b1ed5fae11e1bffde5757d849c77/unpact-0.0.13.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-23 19:56:19",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "unpact"
}
        
Elapsed time: 0.18544s