Input and Output Utilities#
immlib provides a simple pair of utilities for defining input and output
formats. Any format that has been declared can be used to either save data to
files/streams (using immlib.save()) or to load data from files/streams (using
immlib.load()).
immlib.load: Importing Data#
To declare an input format, one can use the @immlib.load.register decorator on
a function that loads the associated data. For example, the following code
declares an importer for the JSON file format:
import immlib as il
@il.load.register('json', '.json', mode='t')
def load_json(stream, /, **kwargs):
"""Loads an object from a JSON stream or path and returns the object.
All keywords are passed along to the `json.load` function.
"""
import json
return json.load(stream, **kwargs)
The @il.load.register call above includes three arguments. The first is the
name of the format; this name must be unique across all formats registered to
immlib’s load utility. If one calls il.load(filename, 'json') then the
load_json() function would always be called no matter what ending the filename
has. The second argument is a filename ending (or list of endings) that
typically indicate this format. The final option (mode='t') indicates that the
stream should be opened in text mode.
Once this load function has been registered, the il.load() function can be
used to load json data automatically. il.load accepts paths, including
non-local paths such as S3 paths.
For example:
import immlib as il
filename = il.doc.__file__
print("Catting file", filename, "...")
lines = il.load(filename, 'text')
for ln in lines:
print(ln)
Catting file /home/runner/work/immlib/immlib/src/immlib/doc/__init__.py ...
# -*- coding: utf-8 -*-
###############################################################################
# immlib/doc/__init__.py
"""Documentation tools that operate via decorators.
The module ``immlib.doc`` primarily contains a decorator, ``docwrap``, which
can be used to parse the inputs, outputs, parameters, and return values in a
function's docstring and to save them in a global cache of all such docstring
components. These components can then be referenced in the docstring of another
function decorated with ``@docwrap`` such that the text needn't be repeated in
every related function.
Attributes
----------
docproc: docrep.DocstringProcessor
This object is used to process all of the doc-strings in the ``immlib``
library; it should be used only with the ``immlib.docwrap`` decorator,
which can safely be applied anywhere in a sequence of decorators and which
correctly applies the ``wraps`` decorator to its argument. Function
documentation is always processed using the ``sections=('Parameters',
'Returns', 'Raises', 'Examples', 'Inputs', 'Outputs')`` parameter and the
``with_indent(4)`` decorator. The base-name for the function ``f`` is
``f.__module__ + '.' + f.__name__``.
"""
from ._core import (
docwrap, make_docproc, default_docproc,
detect_indentation, reindent)
# make_docproc lives in this subpackage (the others live in the immlib package
# and will be reclaimed there).
make_docproc.__module__ = __name__
__all__ = ("docwrap", "default_docproc")
from .._init import reclaim
reclaim(__name__, del_reclaim=True)
immlib.save: Exporting Data#
Similar to immlib.load, the immlib.save function can be accessed using the
immlib.save.register function.
import immlib as il
@il.save.register('json', '.json', mode='t')
def save_json(stream, obj, /, default=json_default, **kwargs):
"""Saves an object as a JSON string or raises a TypeError if not possible.
All keywords are passed along to the `json.dump` function. The `default`
option uses the `immlib.iolib.json_default` function, which is different
than the default used by `json.dump`, but all other options are unaltered.
"""
import json
json.dump(obj, stream, default=default, **kwargs)
Note that in this example and the previous example, additional keyword arguments
are accepted after the stream argument (and the obj object that is being
saved). Any arguments given to the save or load functions are passed along.
Here is an example of using save and load together to first save a YAML file and then to load and print it out:
import immlib as il
from tempfile import TemporaryDirectory
from pathlib import Path
yaml_data = [{'header1': [1, 2, 3], 'header2': [{'a': 10, 'b': 20}, 'end']}]
# Do these operations in a temporary directory:
with TemporaryDirectory() as tmpdir:
tmpdir = Path(tmpdir)
# Save the YAML data out to a file:
il.save(tmpdir / 'file.yaml', yaml_data)
# Now load it as text and print it line by line:
lines = il.load(tmpdir / 'file.yaml')
for ln in lines:
print(ln)
{'header1': [1, 2, 3], 'header2': [{'a': 10, 'b': 20}, 'end']}
Predefined Formats#
The following formats are predefined in immlib:
'str'. Reads or writes a plain string as text. If an object that is not a string is saved, then it isstr(obj)is written.'bytes'. Reads or writes a plain byte string as binary.'repr'. Writesrepr(obj)as a text string.'text'(*.txt). Reads or writes a list of strings.'pickle'(*.pickle,*.pcl,*.pkl). Reads or writes a pickle file.'numpy'(*.npy,*.np,*.numpy,*.npz). Reads or writes a numpy file.'json'(*.json). Reads or writes a JSON file.'yaml'(*.ylm,*.yaml). Reads or writes a YAML file.'csv'(*.csv). Reads or writes a comma-separated-value file usingpandas.'tsv'(*.tsv). Reads or writes a tab-separated-value file usingpandas.