diff --git a/.gitignore b/.gitignore index 6071354..8e77aea 100644 --- a/.gitignore +++ b/.gitignore @@ -142,3 +142,7 @@ jsonid-integration-files/ # Secreta token.pypi jsonid_pronom.xml +*.csv +*.json +*.diff +token-pypi diff --git a/README.md b/README.md index 1a23ed0..cacd77d 100644 --- a/README.md +++ b/README.md @@ -405,9 +405,39 @@ within the `sops` object/value. ### Local rules -The plan is to allow local rules to be run alongside the global ruleset. I -expect this will be a bit further down the line when the ruleset and -metaddata is more stabilised. +You can define local rules in a local registry object. Local registries are +defined in TOML, and look as follows: + +```toml +[[entries]] + +name = "doctype1" +identifier = "local0001" +localref = "http://example.com/doctype/spec/ID" + +[[entries.markers]] + +key = "key1" +is = "value1" + +[[entries]] + +name = "doctype2" +identifier = "local0002" +localref = "http://example.com/doctype/spec/ID + +[[entries.markers]] + +key = "key2" +is = "value2" +``` + +Markers follow the same pattern as the standard registry. + +#### Local only + +Use the `--localonly` flag to use _just_ your custom markers in your format +identification workflow. ## PRONOM diff --git a/local/registry.toml b/local/registry.toml new file mode 100644 index 0000000..a0c36eb --- /dev/null +++ b/local/registry.toml @@ -0,0 +1,25 @@ +[[entries]] + +name = "doctype1" +identifier = "local0001" +localref = "http://example.com/repository/ID" + +[[entries.markers]] + +key = "key1" +is = "value1" + +[[entries.markers]] + +key = "key2" +is = "value2" + +[[entries]] + +name = "doctype2" +identifier = "local0002" + +[[entries.markers]] + +key = "key2" +is = "value2" diff --git a/src/jsonid/jsonid.py b/src/jsonid/jsonid.py index 9d3379e..a148643 100644 --- a/src/jsonid/jsonid.py +++ b/src/jsonid/jsonid.py @@ -16,11 +16,13 @@ import helpers import lookup import registry + + import local except ModuleNotFoundError: try: - from src.jsonid import export, file_processing, helpers, lookup, registry + from src.jsonid import export, file_processing, helpers, local, lookup, registry except ModuleNotFoundError: - from jsonid import export, file_processing, helpers, lookup, registry + from jsonid import export, file_processing, helpers, local, lookup, registry logger = None @@ -216,9 +218,18 @@ def main() -> None: ) parser.add_argument( "--registry", + "--local", help="path to a custom registry to lead into memory replacing the default", required=False, ) + parser.add_argument( + "--localonly", + "--lonly", + "--lonely", + help="if a local registry is specified, use this and this only", + required=False, + action="store_true", + ) # NB. consider output to stdout once the feature is more stable. parser.add_argument( "--pronom", @@ -284,7 +295,11 @@ def main() -> None: # Primary application functions. if args.registry: - raise NotImplementedError("custom registry is not yet available") + local.load_and_parse_local_registry(path=args.registry) + if args.localonly: + raise NotImplementedError("todo...") + + return if args.pronom: export.export_pronom() sys.exit() @@ -305,6 +320,8 @@ def main() -> None: logger.info("ok") sys.exit() if args.html: + if args.registry: + raise NotImplementedError("local registry output is not yet supported") helpers.html() sys.exit() if not strategy: diff --git a/src/jsonid/local.py b/src/jsonid/local.py new file mode 100644 index 0000000..585e25b --- /dev/null +++ b/src/jsonid/local.py @@ -0,0 +1,106 @@ +"""Functions supporting local registry use""" + +import logging +import pathlib +import tomllib as toml + +try: + import registry_class + import registry_data +except ModuleNotFoundError: + try: + from src.jsonid import registry_class, registry_data + except ModuleNotFoundError: + from jsonid import registry_class, registry_data + +logger = logging.getLogger(__name__) + + +class LocalRegistryException(Exception): + """Exception to raise if something goes wrong with the local + registry. + """ + + +def load_and_parse_local_registry(path: str): + """Read the data use the data.""" + + registry = pathlib.Path(path) + if not registry.exists(): + raise LocalRegistryException("registry path not found") + + load_local_registry(registry) + + +""" + registry_class.RegistryEntry( + identifier="jrid:0001", + name=[{"@en": "JavaScript Package Lock"}], + description=[{"@en": "describes an exact Node (NPM) module dependency tree"}], + markers=[ + {"KEY": "name", "EXISTS": None}, + {"KEY": "lockfileVersion", "EXISTS": None}, + {"KEY": "packages", "EXISTS": None}, + ], + ), +""" + + +def load_local_registry(registry: pathlib.Path): + """Load the local registry and return it as a data structure + to the caller. + """ + + with registry.open() as data: + local_registry_data = data.read() + + local_reg = toml.loads(local_registry_data) + + logger.debug("local registry length: %d", len(local_reg["entries"])) + + reg = registry_data.registry() + + for item in local_reg["entries"]: + + # TODO: cleanup, ensure keys are capitalized. + m = [] + for i in item["markers"]: + d = {} + for k, v in tuple(i.items()): + d.update({k.upper(): v}) + m.append(d) + + # TODO: variable naming. + a = registry_class.RegistryEntry( + identifier=item["identifier"], + name=[{"@en": "TODO"}], + description=[{"@en": "TODO"}], + markers=m, + ) + + print(a) + print(a.markers) + print("---") + # if local... + reg.append(a) + + # print(reg) + + """ + [[entries]] + + name = "doctype1" + identifier = "local0001" + localref = "http://example.com/repository/ID + + [[entries.markers]] + + key = "key1" + is = "value1" + + {'name': 'doctype1', 'identifier': 'local0001', 'markers': [{'key': 'key1', 'is': 'value1'}]} + + + """ + + assert False diff --git a/tests/test_local_registry.py b/tests/test_local_registry.py new file mode 100644 index 0000000..82559b2 --- /dev/null +++ b/tests/test_local_registry.py @@ -0,0 +1,44 @@ +"""Test functions associated with the local registry.""" + +from typing import Final + +from src.jsonid import local + +registry: Final[ + str +] = """ +[[entries]] + +name = "doctype1" +identifier = "local0001" + +[[entries.markers]] + +key = "key1" +is = "value1" + +[[entries.markers]] + +key = "key2" +is = "value2" + +[[entries]] + +name = "doctype2" +identifier = "local0002" + +[[entries.markers]] + +key = "key2" +is = "value2" + +""" + + +def test_load_local(tmp_path): + """Ensure loading the local registry works as anticipated.""" + + a = tmp_path / "registry_path" + a.write_text(registry) + + local.load_local_registry(a)