Skip to main content

I/O facility for Idefix/Pluto configuration files

Project description

inifix

PyPI PyPI pre-commit.ci status Code style: black Ruff

inifix is a small Python library of I/O functions to read and write 'ini' configuration files in the style of Pluto and Idefix.

While its primary goal is to follow Idefix's 'ini' format specification, it supports a small superset of it.

The key differences are:

  • inifix supports section-free definitions. This means configuration files from FARGO 3D are also supported.
  • in inifix, strings can be escaped using ' or ". This allows to have whitespaces in string values and to force string type decoding where numeric and boolean types would work.

In rare cases where Idefix's 'ini' format doesn't match Pluto's, inifix will follow the former. Known differences are:

  • Idefix allows booleans to be written as yes and no.
  • Idefix allows integers to be written using scientific notation (e.g. 1e3)

File format specifications details

Unroll ! - parameter names are strings - names and values are separated by non-newline white spaces - values are represented in unicode characters - all values are considered numbers if possible (e.g., `1e3` is read as `1000`) - number values are read as integers if no loss of precision ensues, and floats otherwise - `true` and `false` (resp. `yes` and `no`) are cast to booleans (case-insensitive) - values that can't be read as number or booleans are read as strings. - string delimiters `"` and `'` can be used for strings containing whitespace, or to force string type for values that would otherwise be read as numbers and booleans. - a parameter can be associated to a single value or a list of whitespace-separated values - sections titles start with `[` and end with `]` - comments start with `#` and are ignored

A file is considered valid if calling inifix.load(<filename>) doesn't raise an error.

Examples

The following content is considered valid

# My awesome experiment
[Grid]
x   1 2 u 10    # a comment
y   4 5 l 100
[Time Integrator]
CFL  1e-3
tstop 1E3

and maps to

{
    "Grid": {
        "x": [1, 2, "u", 10],
        "y": [4, 5, "l", 100]
    },
    "Time Integrator": {
        "CFL": 0.001,
        "tstop": 1000.0
    }
}

The following section-less format doesn't comply to Pluto/Idefix's specifications, but it is considered valid for inifix. This is the one intentional differences in specifications, which makes inifix format a superset of Pluto's inifile format.

mode   fargo

# Time integrator
CFL    1e-3
tstop  1e3

and maps to

{
    "mode": "fargo",
    "CFL": 0.001,
    "tstop": 1000.0
}

Note that strings using e-notation (e.g. 1e-3 or 1E3 here) are decoded as floats. Reversely, when writing files, floats are re-encoded using e-notation if it leads to a more compact representation. For instance, 100000.0 is encoded as 1e5, but 189.0 is left unchanged because 1.89e2 takes one more character. In cases where both reprensations are equally compact (e.g. 1.0 VS 1e0), decimal is prefered in encoding.

While decoding, e can be lower or upper case, but they are always encoded as lower case.

Installation

python -m pip install inifix

Usage

The public API mimicks that of Python's standard library json, and consists in four main functions:

  • inifix.load and inifix.dump read from and write to files respectively
  • inifix.loads reads from a str and returns a dict, while inifix.dumps does the reverse operation.

Reading data

inifix.load reads from a file and returns a dict

import inifix

with open("pluto.ini", "rb") as fh:
    conf = inifix.load(fh)

# or equivalently
conf = inifix.load("pluto.ini")

Files are assumed to be encoded as UTF-8.

inifix.load and inifix.loads accept a optional boolean flag parse_scalars_as_list (new in inifix v4.0.0), that is useful to simplify handling unknown data: all values can be safely treated as arrays, and iterated over, even in the presence of scalar strings. For illustration

>>> import inifix
>>> from pprint import pprint
>>> pprint(inifix.load("example.ini"))
{'Grid': {'x': [1, 2, 'u', 10], 'y': [4, 5, 'l', 100]},
 'Time Integrator': {'CFL': 0.001, 'tstop': 1000.0}}
>>> pprint(inifix.load("ex.ini", parse_scalars_as_lists=True))
{'Grid': {'x': [1, 2, 'u', 10], 'y': [4, 5, 'l', 100]},
 'Time Integrator': {'CFL': [0.001], 'tstop': [1000.0]}}

By default, inifix.load and inifix.loads validate input data. This step can be skipped by specifying skip_validation=True.

... and writing back to disk

inifix.dump writes data back to a file.

This allows to change a value on the fly and create new configuration files programmatically, for instance.

conf["Time"]["CFL"] = 0.1

with open("pluto-mod.ini", "wb") as fh:
    inifix.dump(conf, fh)

# or equivalently
inifix.dump(conf, "pluto-mod.ini")

Data will be validated against inifix's format specification at write time. Files are always encoded as UTF-8.

inifix.dumps is the same as inifix.dump except that it returns a string instead of writing to a file.

By default, inifix.dump and inifix.dumps validate input data. This step can be skipped by specifying skip_validation=True.

Schema Validation

inifix.validate_inifile_schema can be used to validate an arbitrary dictionary as writable to an inifile, following Pluto/Idefix's format. This will raise an exception (ValueError) if the dictionnary data is invalid.

inifix.validate_inifile_schema(data)

CLI

Command line tools are shipped with the package to validate or format compatible inifiles.

Validation

This checks that your inifiles can be loaded with inifix.load from the command line

$ inifix-validate pluto.ini
Validated pluto.ini

Formatting

To format a file in place, use

$ inifix-format pluto.ini

inifix-format is guaranteed to preserve comments and to only edit (add or remove) whitespace characters.

Files are always encoded as UTF-8.

To print a diff patch to stdout instead of editing the file, use the --diff flag

$ inifix-format pluto.ini --diff

By default, inifix-format also validates input data. This step can be skipped with the --skip-validation flag

pre-commit hooks

inifix-validate and inifix-format can be used as pre-commit hooks with the following configuration (add to .pre-commit-config.yaml)

  - repo: https://github.com/neutrinoceros/inifix.git
    rev: v4.3.0
    hooks:
      - id: inifix-validate

or

  - repo: https://github.com/neutrinoceros/inifix.git
    rev: v4.3.0
    hooks:
      - id: inifix-format

Note that inifix-format also validates data by default, so it is redundant to utilize both hooks. Validation and formatting may nonetheless be decoupled as

  - repo: https://github.com/neutrinoceros/inifix.git
    rev: v4.3.0
    hooks:
    - id: inifix-validate
    - id: inifix-format
+     args: [--skip-validation]

By default, both hooks target files matching the regular expression (\.ini)$. It is possible to override this expression as, e.g.,

   hooks:
   - id: inifix-format
+    files: (\.ini|\.par)$

Testing

We use the pytest framework to test inifix. The test suite can be run from the top level with a simple pytest invocation.

$ python -m pip install --requirement requirements/tests.txt
$ pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

inifix-4.3.0.tar.gz (32.6 kB view details)

Uploaded Source

Built Distribution

inifix-4.3.0-py3-none-any.whl (26.5 kB view details)

Uploaded Python 3

File details

Details for the file inifix-4.3.0.tar.gz.

File metadata

  • Download URL: inifix-4.3.0.tar.gz
  • Upload date:
  • Size: 32.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.2

File hashes

Hashes for inifix-4.3.0.tar.gz
Algorithm Hash digest
SHA256 09c0c118ace69d7a1e5ce0fd0ccdabb24cc4a2e4774ba86f9cd3da37da3eb450
MD5 c35d2c33409987efe6bcba59beb344d0
BLAKE2b-256 ed797749fcac93b237815f9a9b0cde8391150e99caeb9ab82a85b371fe862dc6

See more details on using hashes here.

File details

Details for the file inifix-4.3.0-py3-none-any.whl.

File metadata

  • Download URL: inifix-4.3.0-py3-none-any.whl
  • Upload date:
  • Size: 26.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.2

File hashes

Hashes for inifix-4.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8c35fe8d10b091c0976917ff9b54fd0d0b6b24a2b1a768b387e229c2a43b41ed
MD5 62143a92045a242c9a8b308a3a6832b9
BLAKE2b-256 4e67daba173ece89f25988521c0fbd7fca36de09bb56d4e35a5b20b75c8fc9d8

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page