diff --git a/Makefile b/Makefile index 56b9351..af51371 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,14 @@ format: black --target-version py39 --line-length 132 --exclude tests/testdata/ *.py epidoc/ tests/ -check: format-check unittest +check: format-check type-check unittest format-check: black --check --target-version py39 --line-length 132 --exclude tests/testdata/ *.py epidoc/ tests/ +type-check: + mypy epidoc + unittest: python -m unittest discover diff --git a/epidoc/api.py b/epidoc/api.py index adbbb68..137c951 100644 --- a/epidoc/api.py +++ b/epidoc/api.py @@ -8,16 +8,16 @@ class EpiDoc: title = None - idno = {} + idno: dict[str, str] = {} material = None - origin_dates = [] - origin_place = {} - provenances = {} - terms = [] - languages = {} + origin_dates: list[str] = [] + origin_place: dict[str, str] = {} + provenances: dict[str, str] = {} + terms: list[str] = [] + languages: dict[str, str] = {} commentary = None edition_language = None - edition_foreign_languages = {} + edition_foreign_languages: dict[str, int] = {} @classmethod def create( diff --git a/epidoc/body.py b/epidoc/body.py index 04e76e1..24ce4ad 100644 --- a/epidoc/body.py +++ b/epidoc/body.py @@ -1,23 +1,25 @@ +from bs4 import Tag + from .normalize import _normalize class _Edition: @staticmethod - def _edition(body): + def _edition(body: Tag): return body.find("div", type="edition") # Note: limit to xml:space="preserve"? @staticmethod - def language(body): + def language(body: Tag): edition = _Edition._edition(body) if edition: return _normalize(edition.attrs.get("xml:lang")) @staticmethod - def foreign_languages(body): + def foreign_languages(body: Tag) -> dict[str, int]: edition = _Edition._edition(body) if not edition: return {} - result = {} + result: dict[str, int] = {} for elem in edition.find_all("foreign"): lang = _normalize(elem.attrs.get("xml:lang")) if not lang: diff --git a/epidoc/header.py b/epidoc/header.py index 7839701..a311cc0 100644 --- a/epidoc/header.py +++ b/epidoc/header.py @@ -1,19 +1,23 @@ +from typing import Any + +from bs4 import Tag + from .normalize import _normalize, _normalized_get_text, _normalized_attrs class _History: @staticmethod - def origin_dates(history): + def origin_dates(history: Tag): result = [] - for elem in history.origin.findAll("origdate"): + for elem in history.origin.findAll("origdate"): # type: ignore date = _normalized_attrs(elem) date["text"] = _normalized_get_text(elem) result.append(date) return result @staticmethod - def origin_place(history): - origin_place = history.origin.origplace + def origin_place(history: Tag): + origin_place = history.origin.origplace # type: ignore if not origin_place: return {} result = _normalized_attrs(origin_place) @@ -21,8 +25,8 @@ def origin_place(history): return result @staticmethod - def provenances(history): - result = {} + def provenances(history: Tag) -> dict[str, Any]: + result: dict[str, Any] = {} for elem in history.findAll("provenance"): typ = _normalize(elem.attrs.get("type")) if typ is None: @@ -31,7 +35,7 @@ def provenances(history): return result @staticmethod - def _provenance(provenance): + def _provenance(provenance: Tag): result = [] # Note: For some it's provenance.p.placename for elem in provenance.findAll("placename"): @@ -45,20 +49,20 @@ def _provenance(provenance): class _ProfileDesc: @staticmethod - def keyword_terms(profile_desc): - result = [] + def keyword_terms(profile_desc: Tag) -> list[dict[str, Any]]: + result: list[dict[str, Any]] = [] textclass = profile_desc.textclass if textclass is None: return result - for elem in textclass.keywords.findAll("term"): + for elem in textclass.keywords.findAll("term"): # type: ignore term = _normalized_attrs(elem) term["text"] = _normalized_get_text(elem) result.append(term) return result @staticmethod - def lang_usage(profile_desc): - result = {} + def lang_usage(profile_desc: Tag) -> dict[str, str]: + result: dict[str, str] = {} lang_usage = profile_desc.langusage if lang_usage is None: return result diff --git a/epidoc/normalize.py b/epidoc/normalize.py index 7399ca1..b322254 100644 --- a/epidoc/normalize.py +++ b/epidoc/normalize.py @@ -1,6 +1,13 @@ -def _normalize(v): +from typing import TypeVar, Any + +from bs4 import Tag + +T = TypeVar("T") + + +def _normalize(v: T) -> T: if isinstance(v, str): - return v.lower().strip() + return v.lower().strip() # type: ignore return v @@ -11,7 +18,7 @@ def _normalized_get_text(raw): return parsed if parsed else None -def _normalized_attrs(raw): +def _normalized_attrs(raw: Tag) -> dict[str, Any]: parsed = {} for name, value in raw.attrs.items(): parsed[_normalize(name)] = _normalize(value) diff --git a/requirements.txt b/requirements.txt index a219675..fce41d8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ -beautifulsoup4==4.10.0 +beautifulsoup4==4.12.3 black==24.3.0 # Code formatter lxml==5.2.1 +mypy==1.10.0 # Type checker setuptools==69.2.0 # Only required for publish it as a package +types-beautifulsoup4==4.12.0.20240229 # Stubs for beautifulsoup4 wheel==0.43.0 # Only required for publish it as a package