Source code for coscon.io_helper

import gzip
import json
from functools import partial
from logging import getLogger
from pathlib import Path
from typing import Union

import toml
import yaml
import yamlloader

logger = getLogger('coscon')

H5_CREATE_KW = {
    'compression': 'gzip',
    # shuffle minimize the output size
    'shuffle': True,
    # checksum for data integrity
    'fletcher32': True,
    # turn off track_times so that identical output gives the same md5sum
    'track_times': False
}


[docs]def dumper( data: dict, path: Union[Path, str], overwrite: bool = False, compress: bool = None ): """Write dict to a TOML/YAML/JSON file. Dump data to a TOML/YAML/JSON format file, optionally compressing the contents with gzip and optionally overwriting the file. Args: data (dict): The dictionary to be written. path (str): The file to write. Valid extensions are .toml, .json, .yaml with optional extension .gz. overwrite (bool): If True, overwrite the file if it exists. If False, then existing files will cause an exception. compress (bool): If True, compress the data with gzip on write. If None, dispatch by its extension. Returns: None """ path = Path(path) if path.exists(): if overwrite: if path.is_file(): path.unlink() else: raise FileExistsError(f'{path} exists and is not a file, abort overwriting...') else: raise FileExistsError(f"{path} exists. Consider using `overwrite` option.") ext = path.suffix.lower() if compress is None: if ext == '.gz': logger.info(f'Setting compression to on according to extension {ext}') compress = True elif compress is True: if ext != '.gz': raise ValueError(f'Compression is on but the extension {ext} is not .gz. Consider changing that to .gz.') if compress: # ext must be .gz now exts = path.suffixes if len(exts) != 2: raise ValueError(f'Entension {exts} not understood. Expect for example .toml.gz') ext = exts[0].lower() dumper_dict = { '.json': partial(json.dumps, indent=4, sort_keys=True), '.toml': partial(toml.dumps, encoder=toml.TomlNumpyEncoder()), '.yaml': yaml.dump if yamlloader is None else partial(yaml.dump, Dumper=yamlloader.ordereddict.CDumper), } try: data_str = dumper_dict[ext](data) except AttributeError: raise ValueError('Do not understand extension {ext}. Consider choosing .json, .toml, or .yaml.') if compress: with gzip.open(path, "wb") as f: f.write(data_str.encode()) else: with open(path, "w") as f: f.write(data_str) return
[docs]def loader(path: Union[Path, str]) -> dict: """Read data from a TOML/YAML/JSON file. The file can either be regular text or a gzipped version of a TOML file. Args: path (str): The file to read. Returns: data (dict): The data read. """ path = Path(path) ext = path.suffix.lower() if ext == '.gz': logger.info(f'Extension is .gz, assume gzip compression is used.') compress = True exts = path.suffixes if len(exts) != 2: raise ValueError(f'Entension {exts} not understood. Expect for example .toml.gz') ext = exts[0].lower() else: compress = False if compress: with gzip.open(path, "rb") as f: data_str = f.read().decode() else: with open(path, "r") as f: data_str = f.read() loader_dict = { '.json': json.loads, '.toml': toml.loads, '.yaml': yaml.load if yamlloader is None else partial(yaml.load, Loader=yamlloader.ordereddict.CLoader), } try: data = loader_dict[ext](data_str) except AttributeError: raise ValueError('Do not understand extension {ext}. Consider choosing .json, .toml, or .yaml.') return data