Skip to content

Commit

Permalink
write toml
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgsavage committed Feb 23, 2025
1 parent 13dcccd commit f0f86f1
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 34 deletions.
16 changes: 9 additions & 7 deletions pint/delegates/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
"""
pint.delegates
~~~~~~~~~~~~~~
pint.delegates
~~~~~~~~~~~~~~
Defines methods and classes to handle autonomous tasks.
Defines methods and classes to handle autonomous tasks.
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from __future__ import annotations

from . import txt_defparser
from .base_defparser import ParserConfig, build_disk_cache_class
from .formatter import Formatter
from .toml_parser import toml_parser
from .toml_parser import toml_defparser, write_definitions

__all__ = [
"txt_defparser",
"ParserConfig",
"build_disk_cache_class",
"Formatter",
"toml_parser",
"toml_defparser",
"write_definitions",
]
15 changes: 9 additions & 6 deletions pint/delegates/toml_parser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
"""
pint.delegates.toml_parser
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pint.delegates.toml_parser
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Parser for the toml Pint Definition file.
Parser for the toml Pint Definition file.
:copyright: 2025 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
:copyright: 2025 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from __future__ import annotations

from .toml_parser import TomlParser
from .toml_defparser import TomlParser
from .toml_writer import write_definitions

__all__ = [
"TomlParser",
"write_definitions",
]
51 changes: 51 additions & 0 deletions pint/delegates/toml_parser/toml_defparser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from __future__ import annotations

import copy
import pathlib

import flexcache as fc

from ...compat import tomllib
from ..base_defparser import ParserConfig
from . import plain


class TomlParser:
def __init__(self, default_config: ParserConfig, diskcache: fc.DiskCache):
self._default_config = default_config
self._diskcache = diskcache

def iter_parsed_project(self, parsed_project: dict):
stmts = {
"unit": plain.UnitDefinition,
"prefix": plain.PrefixDefinition,
"dimension": plain.DerivedDimensionDefinition,
"system": plain.SystemDefinition,
"context": plain.ContextDefinition,
"group": plain.GroupDefinition,
}
for definition_type in parsed_project.keys():
for key, value in parsed_project[definition_type].items():
d = copy.copy(value)
d["name"] = key
stmt = stmts[definition_type].from_dict_and_config(
d, self._default_config
)
yield stmt

def parse_file(
self, filename: pathlib.Path | str, cfg: ParserConfig | None = None
) -> dict:
with open(filename, "rb") as f:
data = tomllib.load(f)
return data

# def parse_string(self, content: str, cfg: ParserConfig | None = None):
# return fp.parse_bytes(
# content.encode("utf-8"),
# _PintParser,
# cfg or self._default_config,
# diskcache=self._diskcache,
# strip_spaces=True,
# delimiters=_PintParser._delimiters,
# )
103 changes: 103 additions & 0 deletions pint/delegates/toml_parser/toml_writer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from __future__ import annotations

from dataclasses import fields

import tomli_w

from ...facets.plain import GenericPlainRegistry

keep_fields = [
"value",
"defined_symbol",
"aliases",
]


def add_key_if_not_empty(dat, key, value):
if value == () or value is None:
return dat
else:
dat[key] = value
return dat


def parse_simple_definition(definition, definition_type):
attrs = [field.name for field in fields(definition) if field.name in keep_fields]
dat = {}
for attr in attrs:
dat = add_key_if_not_empty(dat, attr, getattr(definition, attr))
if definition_type in ["units", "dimensions", "prefixes"] and hasattr(
definition, "raw"
):
dat["value"] = definition.raw.split("=")[1].strip()
return dat


def prefixes_units_dimensions(ureg):
data = {
"prefix": {},
"unit": {},
"dimension": {},
}
for definition_type, ureg_attr in zip(
["unit", "prefix", "dimension"],
["_units", "_prefixes", "_dimensions"],
):
definitions = getattr(ureg, ureg_attr).values()
for definition in definitions:
for name, definition in getattr(ureg, ureg_attr).items():
if hasattr(definition, "raw"):
data[definition_type][definition.name] = parse_simple_definition(
definition, definition_type
)
return data


def groups(ureg):
group_data = {}
for group in ureg._group_definitions:
dat = {}
for attr in ["using_group_names"]:
dat = add_key_if_not_empty(dat, attr, getattr(group, attr))
dat["definitions"] = {}
for definition in group.definitions:
dat["definitions"][definition.name] = parse_simple_definition(
definition, "_units"
)
group_data[group.name] = dat
return group_data


def systems(ureg):
system_data = {}
for group in ureg._system_definitions:
dat = {}
for attr in ["using_group_names"]:
dat = add_key_if_not_empty(dat, attr, getattr(group, attr))
dat["rules"] = []
for rule in group.rules:
dat["rules"].append(rule.raw)
system_data[group.name] = dat
return system_data


def contexts(ureg):
context_data = {}
for group in ureg._context_definitions:
dat = {}
for attr in ["aliases", "defaults", "redefinitions"]:
dat = add_key_if_not_empty(dat, attr, getattr(group, attr))
dat["relations"] = []
for rule in group.relations:
dat["relations"].append(rule.raw)
context_data[group.name] = dat
return context_data


def write_definitions(filename: str, ureg: GenericPlainRegistry):
data = prefixes_units_dimensions(ureg)
data["group"] = groups(ureg)
data["system"] = systems(ureg)
data["context"] = contexts(ureg)
with open("test.toml", "wb") as f:
tomli_w.dump(data, f)
43 changes: 22 additions & 21 deletions pint/facets/plain/registry.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
"""
pint.facets.plain.registry
~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
The registry contains the following important methods:
- parse_unit_name: Parse a unit to identify prefix, unit name and suffix
by walking the list of prefix and suffix.
Result is cached: NO
- parse_units: Parse a units expression and returns a UnitContainer with
the canonical names.
The expression can only contain products, ratios and powers of units;
prefixed units and pluralized units.
Result is cached: YES
- parse_expression: Parse a mathematical expression including units and
return a quantity object.
Result is cached: NO
pint.facets.plain.registry
~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
The registry contains the following important methods:
- parse_unit_name: Parse a unit to identify prefix, unit name and suffix
by walking the list of prefix and suffix.
Result is cached: NO
- parse_units: Parse a units expression and returns a UnitContainer with
the canonical names.
The expression can only contain products, ratios and powers of units;
prefixed units and pluralized units.
Result is cached: YES
- parse_expression: Parse a mathematical expression including units and
return a quantity object.
Result is cached: NO
"""

Expand Down Expand Up @@ -250,9 +250,10 @@ def __init__(
self._def_parser = delegates.txt_defparser.DefParser(
delegates.ParserConfig(non_int_type), diskcache=self._diskcache
)
self._toml_parser = delegates.toml_parser.TomlParser(
self._toml_parser = delegates.toml_defparser.TomlParser(
delegates.ParserConfig(non_int_type), diskcache=self._diskcache
)
self.write_definitions = lambda x: delegates.write_definitions(x, self)
self.formatter = delegates.Formatter(self)
self._filename = filename
self.force_ndarray = force_ndarray
Expand Down Expand Up @@ -495,7 +496,7 @@ def _helper_dispatch_adder(self, definition: Any) -> None:
break
else:
raise TypeError(
f"No loader function defined " f"for {definition.__class__.__name__}"
f"No loader function defined for {definition.__class__.__name__}"
)

adder_func(definition)
Expand Down

0 comments on commit f0f86f1

Please sign in to comment.