From faa2e9329873aa9cc0a2e3cc32692b0630d48af4 Mon Sep 17 00:00:00 2001 From: Diego Date: Sun, 18 Apr 2021 17:56:34 -0400 Subject: [PATCH 1/2] First iteration of model install mechanism. --- src/TRUNAJOD/__init__.py | 16 +++++++++++++++ src/TRUNAJOD/_util.py | 24 +++++++++++++++++++++++ src/TRUNAJOD/language.py | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/TRUNAJOD/__init__.py create mode 100644 src/TRUNAJOD/_util.py create mode 100644 src/TRUNAJOD/language.py diff --git a/src/TRUNAJOD/__init__.py b/src/TRUNAJOD/__init__.py new file mode 100644 index 0000000..9a91563 --- /dev/null +++ b/src/TRUNAJOD/__init__.py @@ -0,0 +1,16 @@ +"""TRUNAJOD init module.""" +from pathlib import Path +from typing import Union + +from .language import Language + + +def load(name: Union[str, Path]) -> Language: + """Load a TRUNAJOD model from a local path. + + :param name: Model name + :type name: Union[str, Path] + :return: A TRUNAJOD language model. + :rtype: Language + """ + return _util.load_model(name) diff --git a/src/TRUNAJOD/_util.py b/src/TRUNAJOD/_util.py new file mode 100644 index 0000000..0279385 --- /dev/null +++ b/src/TRUNAJOD/_util.py @@ -0,0 +1,24 @@ +"""Utilities used by model loader.""" +from pathlib import Path +from typing import Union + +from .language import Language + + +def load_model(name: Union[str, Path]) -> Language: + """Load a TRUNAJOD model. + + :param name: [description] + :type name: Union[str, Path] + :return: [description] + :rtype: Language + """ + if isinstance(name, str): + if Path(name).exists(): + return load_model_from_path(Path(name)) + + +def load_model_from_path(model_path: Path) -> Language: + """Load a model from path, provided it was installed.""" + if not model_path.exists(): + raise IOError("Model does not exist!") diff --git a/src/TRUNAJOD/language.py b/src/TRUNAJOD/language.py new file mode 100644 index 0000000..6a34b93 --- /dev/null +++ b/src/TRUNAJOD/language.py @@ -0,0 +1,42 @@ +"""Define model for languages.""" +from typing import Any +from typing import Dict + + +class Language: + """Class that hold data for a specific language. + + For example, given that Spanish model was installed, this + class holds infinitve map, frequency indices, and any + resource defined in the model. + """ + + def __init__(self, *, meta: Dict[str, Any] = {}): + """Initialize a Language object. + + :param meta: model's metadata, defaults to {} + :type meta: Dict[str, Any], optional + """ + self.lang = None + self._meta = dict(meta) + + @property + def meta(self) -> Dict[str, Any]: + """Metadata of the language class. + + If a model is loaded, this includes details from the + model's meta.json + """ + self._meta.setdefault("lang", self.lang) + self._meta.setdefault("version", "0.0.0") + self._meta.setdefault("description", "") + self._meta.setdefault("author", "") + self._meta.setdefault("email", "") + self._meta.setdefault("url", "") + self._meta.setdefault("license", "") + return self._meta + + @meta.setter + def meta(self, value: Dict[str, Any]) -> None: + """Metadata setter.""" + self._meta = value From 45514554ecaa94e5576c2e1494e9b37ac4c3169f Mon Sep 17 00:00:00 2001 From: Diego Date: Mon, 19 Apr 2021 16:07:39 -0400 Subject: [PATCH 2/2] Add load metadata utility (#16) --- src/TRUNAJOD/_util.py | 47 +++++++++++++++++++++++++++++++++++++++++-- tests/util_test.py | 27 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/util_test.py diff --git a/src/TRUNAJOD/_util.py b/src/TRUNAJOD/_util.py index 0279385..77eff27 100644 --- a/src/TRUNAJOD/_util.py +++ b/src/TRUNAJOD/_util.py @@ -1,11 +1,17 @@ """Utilities used by model loader.""" from pathlib import Path -from typing import Union +from typing import Any +from typing import Dict + +import srsly from .language import Language -def load_model(name: Union[str, Path]) -> Language: +METADATA_FILENAME = "meta.json" + + +def load_model(name: str) -> Language: """Load a TRUNAJOD model. :param name: [description] @@ -22,3 +28,40 @@ def load_model_from_path(model_path: Path) -> Language: """Load a model from path, provided it was installed.""" if not model_path.exists(): raise IOError("Model does not exist!") + + meta = get_model_meta(model_path) + + +def get_model_meta(path: Path) -> Dict[str, Any]: + """Get metadata from model. + + :param path: Path to load meta from + :type path: Path + :return: Metadata dict + :rtype: Dict[str, Any] + """ + return load_meta(path / METADATA_FILENAME) + + +def load_meta(path: Path) -> Dict[str, Any]: + """Load and validate metadata file. + + :param path: Path of the metadata file + :type path: Path + :raises IOError: If E03, E04 happens (placeholder) + :raises ValueError: If metadata is invalid + :return: Metadata dict + :rtype: Dict[str, Any] + """ + if not path.parent.exists(): + raise IOError("Not exists!") + + if not path.exists() or not path.is_file(): + raise IOError("Cannot load json!") + + meta = srsly.read_json(path) + for setting in ("lang", "name", "version"): + if setting not in meta or not meta[setting]: + raise ValueError("Required metadata not found!") + + return meta diff --git a/tests/util_test.py b/tests/util_test.py new file mode 100644 index 0000000..d4f1ccf --- /dev/null +++ b/tests/util_test.py @@ -0,0 +1,27 @@ +"""Unit tests for Language loading utilities.""" +import json +from pathlib import Path + +from TRUNAJOD import _util + + +def test_load_meta(tmpdir): + """Test load_meta.""" + fp = tmpdir.mkdir("test_data").join("meta.json") + fp.write( + json.dumps( + { + "lang": "es", + "name": "trunajod", + "version": "v0.0.0", + "env": "pytest", + } + ) + ) + path = Path(fp.strpath) + assert _util.load_meta(path) == { + "lang": "es", + "name": "trunajod", + "version": "v0.0.0", + "env": "pytest", + }