Skip to content

Commit

Permalink
Issue #50 include openeo-api and openeo-process versions in reports
Browse files Browse the repository at this point in the history
  • Loading branch information
soxofaan committed Mar 12, 2024
1 parent 2019ce4 commit 4d03e80
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/openeo_test_suite/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.0"
__version__ = "0.2.1"
15 changes: 10 additions & 5 deletions src/openeo_test_suite/lib/pytest_plugin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import argparse
import json
import shlex
import sys
from pathlib import Path

import openeo
import pytest
Expand All @@ -14,6 +16,7 @@
set_backend_under_test,
)
from openeo_test_suite.lib.process_selection import set_process_selection_from_config
from openeo_test_suite.lib.version import get_openeo_versions


def pytest_addoption(parser: pytest.Parser):
Expand Down Expand Up @@ -84,10 +87,12 @@ def pytest_configure(config: pytest.Config):

# Add some additional info to HTML report
# https://pytest-html.readthedocs.io/en/latest/user_guide.html#environment
config.stash[pytest_metadata.plugin.metadata_key]["Invocation"] = _invocation()
config.stash[pytest_metadata.plugin.metadata_key][
"openEO Test Suite version"
] = openeo_test_suite.__version__
config.stash[pytest_metadata.plugin.metadata_key].update(
{
"Invocation": _invocation(),
"openEO versions": get_openeo_versions(),
}
)


def _invocation() -> str:
Expand All @@ -99,7 +104,7 @@ def pytest_report_header(config: pytest.Config):
"""Implementation of `pytest_report_header` hook."""
# Add info to terminal report
return [
f"openEO Test Suite {openeo_test_suite.__version__}",
f"openEO versions: {get_openeo_versions()}",
f"Invoked with: {_invocation()}",
]

Expand Down
122 changes: 122 additions & 0 deletions src/openeo_test_suite/lib/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import json
import logging
import subprocess
from pathlib import Path
from typing import Dict, List, Optional, Union

import openeo_test_suite

_log = logging.getLogger(__name__)


_ON_ERROR_IGNORE = "ignore"
_ON_ERROR_WARN = "warn"
_ON_ERROR_FAIL = "fail"


# TODO: make this compatible with packaging?
PROJECT_ROOT = Path(openeo_test_suite.__file__).parents[2]


def get_openeo_versions() -> Dict[str, str]:
return {
"openeo-test-suite": get_openeo_test_suite_version(name_prefix=None),
"openeo-api": get_openeo_api_spec_version(name_prefix=None),
"openeo-processes": get_openeo_processes_spec_version(name_prefix=None),
}


def _join_non_empties(*parts: str, glue: str = " ") -> str:
"""Join non-empty parts"""
return glue.join(p for p in parts if p)


def get_openeo_test_suite_version(
*,
name_prefix: Optional[str] = "openeo-test-suite",
on_error: str = _ON_ERROR_WARN,
git_describe: bool = True,
) -> str:
"""Build openeo-test-suite version, optionally with name prefix and git rev suffix (if possible)"""
return _join_non_empties(
name_prefix,
openeo_test_suite.__version__,
_git_describe(PROJECT_ROOT, on_error=on_error) if git_describe else None,
)


def get_openeo_api_spec_version(
*,
name_prefix: Optional[str] = "openeo-api",
on_error: str = _ON_ERROR_WARN,
git_describe: bool = True,
) -> str:
"""Build version of current openeo-api submodule, optionally with name prefix and git rev suffix (if possible)"""
package_path = PROJECT_ROOT / "assets" / "openeo-api" / "package.json"
return _join_non_empties(
name_prefix,
_get_js_package_version(package_path, on_error=on_error),
_git_describe(package_path, on_error=on_error) if git_describe else None,
)


def get_openeo_processes_spec_version(
*,
name_prefix: Optional[str] = "openeo-processes",
on_error: str = _ON_ERROR_WARN,
git_describe: bool = True,
) -> str:
"""Build version of current openeo-processes submodule, optionally with name prefix and git rev suffix (if possible)"""
package_path = PROJECT_ROOT / "assets" / "processes" / "dev" / "package.json"
return _join_non_empties(
name_prefix,
_get_js_package_version(package_path, on_error=on_error),
_git_describe(package_path, on_error=on_error) if git_describe else None,
)


def _get_js_package_version(
package_path: Path, on_error: str = _ON_ERROR_WARN, default: str = "unknown"
) -> str:
"""
Get version of a "package.json" JS project
:param package_path: path to package.json file
"""
try:
package_metadata = json.loads(package_path.read_text())
version = package_metadata["version"]
except Exception as e:
if on_error == _ON_ERROR_WARN:
_log.warning(f"Failed to parse package version from {package_path}: {e}")
elif on_error == _ON_ERROR_IGNORE:
pass
else:
raise
version = default
return version


def _git_describe(
path: Path, *, wrap: str = "()", on_error: str = _ON_ERROR_WARN
) -> Union[str, None]:
"""
Get short git rev description (possibly with "dirty" indicator), e.g. 'abc123' or 'abc123-dirty'
"""
try:
if not path.is_dir():
path = path.parent
assert path.is_dir()
command = ["git", "describe", "--always", "--dirty"]
description = subprocess.check_output(command, cwd=path).strip().decode("utf-8")
if wrap:
description = f"{wrap[0]}{description}{wrap[-1]}"
except Exception:
if on_error == _ON_ERROR_WARN:
_log.warning(f"Failed to git-describe {path}")
elif on_error == _ON_ERROR_IGNORE:
pass
else:
raise
description = None
return description
109 changes: 109 additions & 0 deletions src/openeo_test_suite/tests/test_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import re
import subprocess

import pytest

from openeo_test_suite.lib.version import (
_ON_ERROR_FAIL,
_ON_ERROR_IGNORE,
_ON_ERROR_WARN,
PROJECT_ROOT,
_get_js_package_version,
_git_describe,
get_openeo_api_spec_version,
get_openeo_processes_spec_version,
get_openeo_test_suite_version,
)


def test_get_openeo_test_suite_version():
assert re.fullmatch(
r"openeo-test-suite [0-9.]+ \([0-9a-f]+(-dirty)?\)",
get_openeo_test_suite_version(),
)
assert re.fullmatch(
r"[0-9.]+ \([0-9a-f]+(-dirty)?\)",
get_openeo_test_suite_version(name_prefix=None),
)
assert re.fullmatch(
r"[0-9.]+", get_openeo_test_suite_version(name_prefix=None, git_describe=False)
)


def test_get_openeo_api_spec_version():
assert re.fullmatch(
r"openeo-api [0-9.a-z-]+ \([0-9a-f]+\)", get_openeo_api_spec_version()
)
assert re.fullmatch(
r"[0-9.a-z-]+",
get_openeo_api_spec_version(name_prefix=None, git_describe=False),
)


def test_get_openeo_processes_spec_version():
assert re.fullmatch(
r"openeo-processes [0-9.a-z-]+ \([0-9a-f]+\)",
get_openeo_processes_spec_version(),
)
assert re.fullmatch(
r"[0-9.a-z-]+",
get_openeo_processes_spec_version(name_prefix=None, git_describe=False),
)


def test_get_js_package_version(tmp_path):
path = tmp_path / "package.json"
path.write_text('{"version":"1.2.3"}')
assert _get_js_package_version(path) == "1.2.3"


def test_get_js_package_version_on_error_default(tmp_path, caplog):
path = tmp_path / "package.json"
assert _get_js_package_version(path) == "unknown"
assert "Failed to parse package version from" in caplog.text


def test_get_js_package_version_on_error_ignore(tmp_path, caplog):
path = tmp_path / "package.json"
assert _get_js_package_version(path, on_error=_ON_ERROR_IGNORE) == "unknown"
assert caplog.text == ""


def test_get_js_package_version_on_error_warn(tmp_path, caplog):
path = tmp_path / "package.json"
assert _get_js_package_version(path, on_error=_ON_ERROR_WARN) == "unknown"
assert "Failed to parse package version from" in caplog.text


def test_get_js_package_version_on_error_fail(tmp_path, caplog):
path = tmp_path / "package.json"
with pytest.raises(FileNotFoundError):
_ = _get_js_package_version(path, on_error=_ON_ERROR_FAIL)


def test_git_describe():
assert re.fullmatch(r"\([0-9a-f]+(-dirty)?\)", _git_describe(PROJECT_ROOT))


def test_git_describe_wrap():
assert re.fullmatch(r"<[0-9a-f]+(-dirty)?>", _git_describe(PROJECT_ROOT, wrap="<>"))


def test_git_describe_on_error_default(tmp_path, caplog):
assert _git_describe(tmp_path) is None
assert "Failed to git-describe" in caplog.text


def test_git_describe_on_error_ignore(tmp_path, caplog):
assert _git_describe(tmp_path, on_error=_ON_ERROR_IGNORE) is None
assert caplog.text == ""


def test_git_describe_on_error_warn(tmp_path, caplog):
assert _git_describe(tmp_path, on_error=_ON_ERROR_WARN) is None
assert "Failed to git-describe" in caplog.text


def test_git_describe_on_error_fail(tmp_path, caplog):
with pytest.raises(subprocess.CalledProcessError):
_ = _git_describe(tmp_path, on_error=_ON_ERROR_FAIL)

0 comments on commit 4d03e80

Please sign in to comment.