diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83b63fb..f7d9634 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,4 +36,7 @@ jobs: run: | uv sync uv run pre-commit run --all - uv run pytest + uv run pytest ./tests + uv run mypy ./src + uv run ruff check + uv run ruff format --check diff --git a/pyproject.toml b/pyproject.toml index bd8ca4c..e825d7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -113,3 +113,16 @@ build-backend = "hatchling.build" [tool.hatch.version] path = "src/bibx/__init__.py" + +[tool.tox] +requires = ["tox>=4.24.2"] +env_list = ["3.9", "3.10", "3.11", "3.12", "3.13"] + +[tool.tox.env_run_base] +deps = [ + "pytest>=8.3.5", + "ruff>=0.9.10", + "mypy~=1.9.0", + "types-requests>=2.32.0.20241016", +] +commands = [["ruff", "check"], ["pytest", "tests/"], ["mypy", "src/"]] diff --git a/src/bibx/builders/openalex.py b/src/bibx/builders/openalex.py index 2f31583..63e608e 100644 --- a/src/bibx/builders/openalex.py +++ b/src/bibx/builders/openalex.py @@ -94,6 +94,12 @@ def _extract_doi(url: str) -> str: @classmethod def _work_to_article(cls, work: Work) -> Article: + journal = None + if work.primary_location and work.primary_location.source: + journal = work.primary_location.source.display_name + permalink = None + if work.primary_location and work.primary_location.landing_page_url: + permalink = work.primary_location.landing_page_url article = Article( label=work.id, ids={ @@ -105,16 +111,12 @@ def _work_to_article(cls, work: Work) -> Article: authors=[cls._invert_name(a.author.display_name) for a in work.authorships], year=work.publication_year, title=work.title, - journal=( - work.primary_location - and work.primary_location.source - and work.primary_location.source.display_name - ), + journal=journal, volume=work.biblio.volume, issue=work.biblio.issue, page=work.biblio.first_page, doi=cls._extract_doi(work.doi) if work.doi else None, - _permalink=work.primary_location and work.primary_location.landing_page_url, + _permalink=permalink, times_cited=work.cited_by_count, references=[cls._reference_to_article(r) for r in work.referenced_works], keywords=[k.display_name for k in work.keywords], diff --git a/src/bibx/builders/scopus_csv.py b/src/bibx/builders/scopus_csv.py index 509807b..5950bc0 100644 --- a/src/bibx/builders/scopus_csv.py +++ b/src/bibx/builders/scopus_csv.py @@ -91,11 +91,11 @@ def build(self) -> Collection: articles = self._articles_from_files() return Collection(articles=Collection.deduplicate_articles(list(articles))) - def _articles_from_files(self) -> Generator[Article]: + def _articles_from_files(self) -> Generator[Article, None, None]: for file in self._files: yield from self._parse_file(file) - def _parse_file(self, file: TextIO) -> Generator[Article]: + def _parse_file(self, file: TextIO) -> Generator[Article, None, None]: reader = csv.DictReader(file) for row in reader: datum = Row.model_validate(row) diff --git a/src/bibx/builders/wos.py b/src/bibx/builders/wos.py index 43273ac..afdce0c 100644 --- a/src/bibx/builders/wos.py +++ b/src/bibx/builders/wos.py @@ -369,7 +369,7 @@ def _parse(cls, key: str, value: list[str]) -> dict: if key in cls.FIELDS: field = cls.FIELDS[key] parsed_value = field.parse(value) - return {new_key: parsed_value for new_key in [field.key, *field.aliases]} + return dict.fromkeys([field.key, *field.aliases], parsed_value) logger.debug("Found an unknown field with key %s and value %s", key, value) return {key: _ident(value)} diff --git a/src/bibx/collection.py b/src/bibx/collection.py index fc33677..59803eb 100644 --- a/src/bibx/collection.py +++ b/src/bibx/collection.py @@ -74,7 +74,7 @@ def _uniqe_articles_by_id(cls, articles: list[Article]) -> dict[str, Article]: articles.append(article) visited.add(id(article)) merged = reduce(Article.merge, articles) - article_by_id.update({id_: merged for id_ in ids}) + article_by_id.update(dict.fromkeys(ids, merged)) return article_by_id diff --git a/stubs/bibtexparser/bparser.pyi b/stubs/bibtexparser/bparser.pyi new file mode 100644 index 0000000..41698b4 --- /dev/null +++ b/stubs/bibtexparser/bparser.pyi @@ -0,0 +1,2 @@ +class BibDatabase: + entries: list[dict] diff --git a/stubs/networkx/algorithms/__init__.pyi b/stubs/networkx/algorithms/__init__.pyi new file mode 100644 index 0000000..e69de29 diff --git a/stubs/networkx/algorithms/community/__init__.pyi b/stubs/networkx/algorithms/community/__init__.pyi new file mode 100644 index 0000000..e69de29 diff --git a/stubs/networkx/classes/__init__.pyi b/stubs/networkx/classes/__init__.pyi new file mode 100644 index 0000000..e69de29 diff --git a/stubs/networkx/classes/reportviews.pyi b/stubs/networkx/classes/reportviews.pyi new file mode 100644 index 0000000..e53edcc --- /dev/null +++ b/stubs/networkx/classes/reportviews.pyi @@ -0,0 +1,6 @@ +from collections.abc import Iterator, Mapping, Set + +class NodeView(Mapping, Set): + def __getitem__(self, key: str, /) -> dict: ... + def __iter__(self) -> Iterator[str]: ... + def __len__(self) -> int: ...