Name | unpact JSON |
Version |
0.0.19
JSON |
| download |
home_page | None |
Summary | A lightweight library for tabulating dictionaries |
upload_time | 2024-11-12 05:43:11 |
maintainer | None |
docs_url | None |
author | Moph Toyer |
requires_python | <4.0,>=3.9 |
license | MIT |
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"
}