Module shaystack.haysondumper
Save a Grid
in Hayson file, conform with the specification describe
here (https://project-haystack.org/forum/topic/792)
Expand source code
# -*- coding: utf-8 -*-
# JSON Grid dumper
# See the accompanying LICENSE file.
# (C) 2018 VRT Systems
# (C) 2021 Engie Digital
#
# vim: set ts=4 sts=4 et tw=78 sw=4 si:
"""
Save a `Grid` in Hayson file, conform with the specification describe
here (https://project-haystack.org/forum/topic/792)
"""
from __future__ import unicode_literals
import datetime
import functools
import json
from typing import Dict, Optional, Tuple, List, Any, Union
from .datatypes import Quantity, Coordinate, Ref, Bin, Uri, \
MARKER, NA, REMOVE, XStr
from .grid import Grid
from .haysonparser import MARKER_STR, REMOVE_STR
from .metadata import MetadataObject
from .sortabledict import SortableDict
from .type import Entity
from .version import LATEST_VER, VER_3_0, Version
from .zoneinfo import timezone_name
def dump_grid(grid: Grid) -> str:
"""
Dump a grid to JSON
Args:
grid: The grid.
Returns:
A json string
"""
return json.dumps(_dump_grid_to_hayson(grid))
def _dump_grid_to_hayson(grid: Grid) -> Dict[str, Union[List[str], Dict[str, str]]]:
"""
Convert a grid to JSON object
Args:
grid: The grid to dump
Returns:
A json object.
"""
return {
'meta': _dump_meta(grid.metadata, version=grid.version, for_grid=True),
'cols': _dump_columns(grid.column, version=grid.version),
'rows': _dump_rows(grid),
}
def _dump_meta(meta: MetadataObject,
version: Version = LATEST_VER,
for_grid: Optional[bool] = False) -> Dict[str, str]:
_dump = functools.partial(_dump_meta_item, version=version)
_meta = dict(map(_dump, list(meta.items())))
if for_grid:
_meta['ver'] = str(version)
return _meta
def _dump_meta_item(item: str, version: Version = LATEST_VER) \
-> Tuple[str, Union[None, bool, str, float, List[str], Entity]]:
(item_id, item_value) = item
return (_dump_id(item_id),
_dump_scalar(item_value, version=version))
def _dump_columns(cols: SortableDict, version: Version = LATEST_VER) -> List[str]:
_dump = functools.partial(_dump_column, version=version)
_cols = list(zip(*list(cols.items())))
if not _cols:
raise ValueError("Empty columns is not valide. Use `grid.extends_columns()`")
return list(map(_dump, *_cols))
def _dump_column(col: str, col_meta: MetadataObject, version: Version = LATEST_VER) -> Dict[str, str]:
if bool(col_meta):
_meta = _dump_meta(col_meta, version=version)
else:
_meta = {}
_meta['name'] = col
return _meta
def _dump_rows(grid: Grid) -> List[str]:
return list(map(functools.partial(_dump_row, grid), grid))
def _dump_row(grid: Grid, row: Entity) -> Dict[str, str]:
return {
c: _dump_scalar(row.get(c), version=grid.version)
for c in list(grid.column.keys()) if c in row
}
def _dump_scalar(scalar: Any, version: Version = LATEST_VER) \
-> Union[None, str, bool, float, List[str], Entity]:
if scalar is None:
return None
if scalar is MARKER:
return _dump_marker()
if scalar is REMOVE:
return _dump_remove()
if scalar is NA:
if version < VER_3_0:
raise ValueError('Project Haystack %s '
'does not support NA' % version)
return _dump_na()
if isinstance(scalar, list):
return _dump_list(scalar, version=version)
if isinstance(scalar, dict):
return _dump_dict(scalar, version=version)
if isinstance(scalar, bool):
return _dump_bool(scalar)
if isinstance(scalar, Ref):
return _dump_ref(scalar)
if isinstance(scalar, Bin):
return _dump_bin(scalar)
if isinstance(scalar, XStr):
return _dump_xstr(scalar)
if isinstance(scalar, Uri):
return _dump_uri(scalar)
if isinstance(scalar, str):
return _dump_str(scalar)
if isinstance(scalar, datetime.datetime):
return _dump_date_time(scalar)
if isinstance(scalar, datetime.time):
return _dump_time(scalar)
if isinstance(scalar, datetime.date):
return _dump_date(scalar)
if isinstance(scalar, Coordinate):
return _dump_coord(scalar)
if isinstance(scalar, Quantity):
return _dump_quantity(scalar)
if isinstance(scalar, (float, int)):
return _dump_decimal(scalar)
if isinstance(scalar, Grid):
return _dump_grid_to_hayson(scalar)
raise NotImplementedError('Unhandled case: %r' % scalar)
def _dump_id(id_str: str) -> str:
return id_str
def _dump_na() -> Dict:
return {'_kind': 'NA'}
def _dump_marker() -> Dict:
return {'_kind': MARKER_STR}
def _dump_str(str_value: str) -> str:
return str_value
def _dump_uri(uri_value: Uri) -> Dict:
return {
"_kind": "Uri",
"val": uri_value
}
# TO CHALLENGE
def _dump_bin(bin_value: Bin) -> Dict:
return {
"_kind": "Bin",
"val": bin_value
}
def _dump_remove() -> Dict:
return {"_kind": REMOVE_STR}
def _dump_xstr(xstr_value: XStr) -> Dict:
return {
"_kind": "XStr",
"type": xstr_value.encoding,
"val": xstr_value.data_to_string()
}
def _dump_quantity(quantity: Quantity) -> Union[Dict, float]:
if (quantity.units is None) or (quantity.units == ''):
return _dump_decimal(quantity.m)
return {
"_kind": "Num",
"val": quantity.m,
"unit": str(quantity.symbol)
}
def _dump_decimal(decimal: float) -> float:
return decimal
def _dump_bool(bool_value: bool) -> bool:
return bool_value
def _dump_coord(coordinate: Coordinate) -> Dict:
return {
"_kind": "Coord",
"lat": coordinate.latitude,
"lng": coordinate.longitude
}
def _dump_ref(ref: Ref) -> Dict:
if ref.has_value:
return {
"_kind": "Ref",
"val": ref.name,
"dis": ref.value
}
return {
"_kind": "Ref",
"val": ref.name
}
def _dump_date(date: datetime.date) -> Dict:
return {
"_kind": "Date",
"val": date.isoformat()
}
def _dump_time(time: datetime.time) -> Dict:
return {
"_kind": "Time",
"val": time.isoformat()
}
def _dump_date_time(date_time: datetime.datetime) -> Dict:
tz_name = timezone_name(date_time)
return {
"_kind": "DateTime",
"val": date_time.isoformat(),
"tz": tz_name
}
def _dump_list(lst: List[Any], version: Version = LATEST_VER) -> List[str]:
if version < VER_3_0:
raise ValueError('Project Haystack %s '
'does not support lists' % version)
return list(map(functools.partial(_dump_scalar, version=version), lst))
def _dump_dict(dic: Dict[str, Any], version: Version = LATEST_VER) -> Dict[str, str]:
if version < VER_3_0:
raise ValueError('Project Haystack %s '
'does not support dict' % version)
return {k: _dump_scalar(v, version=version) for (k, v) in dic.items()}
def dump_scalar(scalar: Any, version: Version = LATEST_VER) -> str:
"""
Dump a scalar to JSON
Args:
scalar: The scalar value
version: The Haystack version
Returns:
The JSON string
"""
return json.dumps(_dump_scalar(scalar, version))
Functions
def dump_grid(grid: shaystack.grid.Grid) ‑> str
-
Dump a grid to JSON
Args
grid
- The grid.
Returns
A json string
Expand source code
def dump_grid(grid: Grid) -> str: """ Dump a grid to JSON Args: grid: The grid. Returns: A json string """ return json.dumps(_dump_grid_to_hayson(grid))
def dump_scalar(scalar: Any, version: shaystack.version.Version = <shaystack.version.Version object>) ‑> str
-
Dump a scalar to JSON
Args
scalar
- The scalar value
version
- The Haystack version
Returns
The JSON string
Expand source code
def dump_scalar(scalar: Any, version: Version = LATEST_VER) -> str: """ Dump a scalar to JSON Args: scalar: The scalar value version: The Haystack version Returns: The JSON string """ return json.dumps(_dump_scalar(scalar, version))