Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback for metadata of conda packages #601

Merged
merged 2 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions src/scippneutron/metadata/_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,9 @@ def from_package_metadata(cls, package_name: str) -> Software:
:
A Software instance.
"""
from importlib.metadata import version

return cls(
name=package_name,
version=version(package_name),
version=_deduce_package_version(package_name),
url=_deduce_package_source_url(package_name),
doi=None,
)
Expand All @@ -277,10 +275,39 @@ def compact_repr(self) -> str:
return self.name_version


def _deduce_package_version(package_name: str) -> str | None:
from importlib.metadata import PackageNotFoundError, version

try:
return version(package_name)
except PackageNotFoundError:
# Either the package is not installed or has no metadata.
from importlib import import_module

try:
package = import_module(package_name)
except ModuleNotFoundError as e:
raise e from None

try:
return package.__version__
except AttributeError:
raise RuntimeError(
f"Package '{package_name}' has no metadata and no "
f"__version__ attribute. Specify the version manually."
) from None


def _deduce_package_source_url(package_name: str) -> str | None:
from importlib.metadata import metadata
from importlib.metadata import PackageNotFoundError, metadata

try:
meta = metadata(package_name)
except PackageNotFoundError:
# Either the package is not installed or has no metadata.
return None

if not (urls := metadata(package_name).get_all("project-url")):
if not (urls := meta.get_all("project-url")):
return None

try:
Expand Down
18 changes: 12 additions & 6 deletions tests/metadata/metadata_model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright (c) 2025 Scipp contributors (https://github.com/scipp)


import pytest
import scipp as sc
import scippnexus as snx
from dateutil.parser import parse as parse_datetime
Expand Down Expand Up @@ -44,10 +45,15 @@ def test_software_from_from_package_metadata_first_party() -> None:

def test_software_from_from_package_metadata_third_party() -> None:
software = metadata.Software.from_package_metadata('scipp')
expected = metadata.Software(
name='scipp',
version=sc.__version__,
url='https://github.com/scipp/scipp',
doi=None, # Cannot be deduced
assert software.name == 'scipp'
assert software.version == sc.__version__
assert software.url in (
'https://github.com/scipp/scipp', # properly deduced
None, # fallback for our conda packages
)
assert software == expected
assert software.doi is None


def test_software_from_from_package_metadata_fails_when_package_not_installed() -> None:
with pytest.raises(ModuleNotFoundError):
metadata.Software.from_package_metadata('not-a-package')