unpact


Nameunpact JSON
Version 0.0.19 PyPI version JSON
download
home_pageNone
SummaryA lightweight library for tabulating dictionaries
upload_time2024-11-12 05:43:11
maintainerNone
docs_urlNone
authorMoph Toyer
requires_python<4.0,>=3.9
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
from typing import List

import polars as pl

from unpact import ColumnDef, ColumnSpec, unwind


def format_coordinate_pair(
    coords: list[int], index: int | None
) -> dict:  # Formatter functions must return a dictionary
    # Terminal value is passed to the "formatter" function
    # "index" is optionally injected if the value is a member of a list

    return {"x": coords[0], "y": coords[1], "frame": index} if coords else {"x": None, "y": None, "frame": index}


# 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] = [
    ColumnSpec(path="calendar.year", name="Year"),  # You can rename the column using the optional `name` kwarg
    ColumnSpec(path="calendar.date"),  # Otherwise the column will be named after the last part of the path
    ColumnSpec(path="locations.location", name="location name"),
    ColumnSpec(path="locations.coords", formatter=lambda coords: {"x": coords[0], "y": coords[1]}),
    ColumnSpec(path="locations.coords", formatter=format_coordinate_pair),
]

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, 6)
┌──────┬────────┬───────────────┬─────┬─────┬───────┐
│ Year ┆ date   ┆ location name ┆ x   ┆ y   ┆ frame │
│ ---  ┆ ---    ┆ ---           ┆ --- ┆ --- ┆ ---   │
│ i64  ┆ str    ┆ str           ┆ i64 ┆ i64 ┆ i64   │
╞══════╪════════╪═══════════════╪═════╪═════╪═══════╡
│ 2022 ┆ Aug 14 ┆ Loc1          ┆ 1   ┆ 1   ┆ 0     │
│ 2022 ┆ Aug 14 ┆ Loc1          ┆ 2   ┆ 2   ┆ 1     │
│ 2022 ┆ Aug 14 ┆ Loc1          ┆ 3   ┆ 3   ┆ 2     │
│ 2022 ┆ Aug 14 ┆ Loc2          ┆ 1   ┆ 1   ┆ 0     │
│ 2022 ┆ Aug 14 ┆ Loc2          ┆ 2   ┆ 2   ┆ 1     │
│ 2022 ┆ Aug 14 ┆ Loc2          ┆ 3   ┆ 3   ┆ 2     │
│ 2022 ┆ Aug 14 ┆ Loc3          ┆ 1   ┆ 1   ┆ 0     │
│ 2022 ┆ Aug 14 ┆ Loc3          ┆ 2   ┆ 2   ┆ 1     │
│ 2022 ┆ Aug 14 ┆ Loc3          ┆ 3   ┆ 3   ┆ 2     │
└──────┴────────┴───────────────┴─────┴─────┴───────┘

```

## API Documentation

### ColumnSpec

`ColumnSpec` is a dataclass used to define the specifications for a column in the output dataframe. It includes the following attributes:

- `path` (str): Dot-delimited path to the column in the input data.
- `name` (Optional[str]): Name of the column in the output dataframe. If not provided, the terminal path is used.
- `formatter` (Optional[ColumnFormatter]): Formatter to apply to the column data.
- `default` (Optional[Any]): Value to use if the column is missing from the input data. If not provided, `None` is used.

#### Methods

- `from_tuple(column_def: Tuple[str, ColumnSpecDict]) -> ColumnSpec`: Creates a `ColumnSpec` instance from a tuple.
- `from_str(path: str) -> ColumnSpec`: Creates a `ColumnSpec` instance from a string path.
- `from_def(column_def: ColumnDef) -> ColumnSpec`: Creates a `ColumnSpec` instance from a `ColumnDef` which can be a string, tuple, or `ColumnSpec` instance.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "unpact",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.9",
    "maintainer_email": null,
    "keywords": "tables, formatting, flat, flattening, json",
    "author": "Moph Toyer",
    "author_email": "chris@telemetry.fm",
    "download_url": "https://files.pythonhosted.org/packages/44/fc/349af674c56a1fb62df50797b1203cc8a81fc5d36fbde67792e127222fe0/unpact-0.0.19.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\ufffd\ufffd\ufffd\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\nfrom typing import List\n\nimport polars as pl\n\nfrom unpact import ColumnDef, ColumnSpec, unwind\n\n\ndef format_coordinate_pair(\n    coords: list[int], index: int | None\n) -> dict:  # Formatter functions must return a dictionary\n    # Terminal value is passed to the \"formatter\" function\n    # \"index\" is optionally injected if the value is a member of a list\n\n    return {\"x\": coords[0], \"y\": coords[1], \"frame\": index} if coords else {\"x\": None, \"y\": None, \"frame\": index}\n\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    ColumnSpec(path=\"calendar.year\", name=\"Year\"),  # You can rename the column using the optional `name` kwarg\n    ColumnSpec(path=\"calendar.date\"),  # Otherwise the column will be named after the last part of the path\n    ColumnSpec(path=\"locations.location\", name=\"location name\"),\n    ColumnSpec(path=\"locations.coords\", formatter=lambda coords: {\"x\": coords[0], \"y\": coords[1]}),\n    ColumnSpec(path=\"locations.coords\", formatter=format_coordinate_pair),\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\n---\nshape: (9, 6)\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\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Year \u2506 date   \u2506 location name \u2506 x   \u2506 y   \u2506 frame \u2502\n\u2502 ---  \u2506 ---    \u2506 ---           \u2506 --- \u2506 --- \u2506 ---   \u2502\n\u2502 i64  \u2506 str    \u2506 str           \u2506 i64 \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\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1          \u2506 1   \u2506 1   \u2506 0     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1          \u2506 2   \u2506 2   \u2506 1     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc1          \u2506 3   \u2506 3   \u2506 2     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2          \u2506 1   \u2506 1   \u2506 0     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2          \u2506 2   \u2506 2   \u2506 1     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc2          \u2506 3   \u2506 3   \u2506 2     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc3          \u2506 1   \u2506 1   \u2506 0     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc3          \u2506 2   \u2506 2   \u2506 1     \u2502\n\u2502 2022 \u2506 Aug 14 \u2506 Loc3          \u2506 3   \u2506 3   \u2506 2     \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\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n```\n\n## API Documentation\n\n### ColumnSpec\n\n`ColumnSpec` is a dataclass used to define the specifications for a column in the output dataframe. It includes the following attributes:\n\n- `path` (str): Dot-delimited path to the column in the input data.\n- `name` (Optional[str]): Name of the column in the output dataframe. If not provided, the terminal path is used.\n- `formatter` (Optional[ColumnFormatter]): Formatter to apply to the column data.\n- `default` (Optional[Any]): Value to use if the column is missing from the input data. If not provided, `None` is used.\n\n#### Methods\n\n- `from_tuple(column_def: Tuple[str, ColumnSpecDict]) -> ColumnSpec`: Creates a `ColumnSpec` instance from a tuple.\n- `from_str(path: str) -> ColumnSpec`: Creates a `ColumnSpec` instance from a string path.\n- `from_def(column_def: ColumnDef) -> ColumnSpec`: Creates a `ColumnSpec` instance from a `ColumnDef` which can be a string, tuple, or `ColumnSpec` instance.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A lightweight library for tabulating dictionaries",
    "version": "0.0.19",
    "project_urls": null,
    "split_keywords": [
        "tables",
        " formatting",
        " flat",
        " flattening",
        " json"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "95beb8b5936e84f318881f7f941c3ec15055e6fa56762e99b62f5df6262d4e62",
                "md5": "cd247e5e02d5029d12668443237d0cdb",
                "sha256": "7b5ee09572a559cff2d651c1d4a5523fddcb41545fcf1dd3bf99a6ef729df6f6"
            },
            "downloads": -1,
            "filename": "unpact-0.0.19-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "cd247e5e02d5029d12668443237d0cdb",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.9",
            "size": 12217,
            "upload_time": "2024-11-12T05:43:10",
            "upload_time_iso_8601": "2024-11-12T05:43:10.876542Z",
            "url": "https://files.pythonhosted.org/packages/95/be/b8b5936e84f318881f7f941c3ec15055e6fa56762e99b62f5df6262d4e62/unpact-0.0.19-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "44fc349af674c56a1fb62df50797b1203cc8a81fc5d36fbde67792e127222fe0",
                "md5": "3788e3f14fd7c9bad72f06ef5dda79b1",
                "sha256": "f5bb2c9a5d3592b79daf8bbc378055ce0b9b1b884c58a6e4e63b8c1ee32521c0"
            },
            "downloads": -1,
            "filename": "unpact-0.0.19.tar.gz",
            "has_sig": false,
            "md5_digest": "3788e3f14fd7c9bad72f06ef5dda79b1",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.9",
            "size": 10459,
            "upload_time": "2024-11-12T05:43:11",
            "upload_time_iso_8601": "2024-11-12T05:43:11.770482Z",
            "url": "https://files.pythonhosted.org/packages/44/fc/349af674c56a1fb62df50797b1203cc8a81fc5d36fbde67792e127222fe0/unpact-0.0.19.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-12 05:43:11",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "unpact"
}
        
Elapsed time: 2.14533s