Package: inifix
inifixinifixis a small Python library of I/O functions to read and write 'ini'
configuration files in the style ofPlutoandIdefix.While its primary goal is to follow Idefix's 'ini' format specification, it
supports a small superset of it.The key differences are:inifixsupports section-free definitions. This means configuration files
fromFARGO 3Dare also supported.ininifix, 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,inifixwill
follow the former. Known differences are:Idefix allows booleans to be written asyesandno.Idefix allows integers to be written using scientific notation (e.g.1e3)File format specifications detailsUnroll !- 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 ignoredA file is considered valid if callinginifix.load(<filename>)doesn't raise an
error.ExamplesThe following content is considered valid# My awesome experiment[Grid]x   1 2 u 10    # a commenty   4 5 l 100[Time Integrator]CFL  1e-3tstop 1E3and 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 integratorCFL    1e-3tstop  1e3and maps to{"mode":"fargo","CFL":0.001,"tstop":1000.0}Note that strings using e-notation (e.g.1e-3or1E3here) 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.0is encoded
as1e5, but189.0is left unchanged because1.89e2takes one more character.
In cases where both reprensations are equally compact (e.g.1.0VS1e0),
decimal is prefered in encoding.While decoding,ecan be lower or upper case, but they are always encoded as
lower case.Installationpython-mpipinstallinifixUsageThe public API mimicks that of Python's standard libraryjson,
and consists in four main functions:inifix.loadandinifix.dumpread from and write to files respectivelyinifix.loadsreads from astrand returns adict, whileinifix.dumpsdoes the reverse operation.Reading datainifix.loadreads from a file and returns adictimportinifixwithopen("pluto.ini","rb")asfh:conf=inifix.load(fh)# or equivalentlyconf=inifix.load("pluto.ini")Files are assumed to be encoded as UTF-8.inifix.loadandinifix.loadsaccept a optional boolean flagparse_scalars_as_list(new ininifixv4.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>>>importinifix>>>frompprintimportpprint>>>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("example.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.loadandinifix.loadsvalidate input data. This step can
be skipped by specifyingskip_validation=True.... and writing back to diskinifix.dumpwrites 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.1withopen("pluto-mod.ini","wb")asfh:inifix.dump(conf,fh)# or equivalentlyinifix.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.dumpsis the same asinifix.dumpexcept that it returns a string
instead of writing to a file.By default,inifix.dumpandinifix.dumpsvalidate input data. This step can
be skipped by specifyingskip_validation=True.Schema Validationinifix.validate_inifile_schemacan 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 dictionnarydatais invalid.inifix.validate_inifile_schema(data)CLICommand line tools are shipped with the package to validate or format compatible
inifiles.ValidationThis checks that your inifiles can be loaded withinifix.loadfrom the command line$inifix-validatepluto.ini
Validatedpluto.iniFormattingTo format a file in place, use$inifix-formatpluto.iniinifix-format is guaranteed to preserve comments and toonlyedit (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--diffflag$inifix-formatpluto.ini--diffBy default,inifix-formatalso validates input data. This step can be skipped with the--skip-validationflagpre-commit hooksinifix-validateandinifix-formatcan be used aspre-commithooks with the
following configuration (add to.pre-commit-config.yaml)-repo:https://github.com/neutrinoceros/inifix.gitrev:v4.4.2hooks:-id:inifix-validateor-repo:https://github.com/neutrinoceros/inifix.gitrev:v4.4.2hooks:-id:inifix-formatNote thatinifix-formatalso 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.2
    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)$TestingWe use thepytestframework to testinifix. The test suite can be run from the top level with a simplepytestinvocation.$python-mpipinstall--requirementrequirements/tests.txt
$pytest