Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,6 @@ dmypy.json

# tempory generated files
pyproject-sha.toml

#version ignore
simpeg_drivers/_version.py
37 changes: 33 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
[build-system]
requires = ["poetry-core>=1.8.0"]
build-backend = "poetry.core.masonry.api"
requires = ["poetry-core>=1.8.0", "poetry-dynamic-versioning>=1.9.0,<2.0.0"]
build-backend = "poetry_dynamic_versioning.backend"

[project]
name = "simpeg-drivers"
version = "0.4.0a1"
requires-python = '>=3.10,<4.0'

description = "Application to run SimPEG inversions with geoh5 files from Geoscience Analyst."
Expand All @@ -24,7 +23,7 @@ keywords = [
"simpeg",
]
readme = "package.rst"
dynamic = ["dependencies", "classifiers"]
dynamic = ["version", "dependencies", "classifiers"]
authors = [{ name = "Mira Geoscience", email = "support@mirageoscience.com" }]
maintainers = [
{ name = "Benjamin Kary", email = "benjamink@mirageoscience.com" },
Expand Down Expand Up @@ -64,6 +63,8 @@ include = [
{ path = "docs/**/THIRD_PARTY_SOFTWARE.rst" },
]

version = "0.0.0.dev0"

[tool.poetry.dependencies]
# note: py-deps-clock defines custom mapping from dask to dask-core
dask = ">=2025.3, <2025.4.dev" # also in simpeg[dask]
Expand Down Expand Up @@ -143,6 +144,34 @@ pydantic = ">=2.5.2, <3.0.dev" # from geoh5py, geoapps-utils
pymatsolver = ">=0.3.0, <0.4.dev" # from simpeg
zarr = ">=2.14.2, <2.15.dev" # from simpeg[dask]

[tool.poetry.requires-plugins]
poetry-dynamic-versioning = { version = ">=1.0.0,<2.0.0", extras = ["plugin"] }

[tool.poetry-dynamic-versioning]
bump = true
enable = true
fix-shallow-repository = true
strict = true
style = "pep440"
vcs = "git"

[tool.poetry-dynamic-versioning.substitution]
files = ["simpeg_drivers/_version.py", "recipe.yaml"]
patterns = [
{ value = '''(^__version__\s*(?::.*?)?=\s*['"])[^'"]*(['"])''', mode = "str" },
{ value = '''(^\s*version\s*(?::.*?)?:\s*['"])[^'"]*(['"])''', mode = "str" },
]

[tool.poetry-dynamic-versioning.files."simpeg_drivers/_version.py"]
persistent-substitution = true
initial-content = """
# Version placeholder that will be replaced during substitution
__version__ = "0.0.0"
"""

[tool.poetry-dynamic-versioning.files."recipe.yaml"]
persistent-substitution = true

[tool.ruff]
target-version = "py310"

Expand Down
6 changes: 4 additions & 2 deletions recipe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ schema_version: 1

context:
name: "simpeg-drivers"
version: "0.4.0a1"
version: "0.0.0.dev0" # This will be replaced by the actual version in the build process
python_min: "3.10"

package:
Expand All @@ -20,7 +20,8 @@ build:
requirements:
host:
- python 3.10.*
- poetry-core >=1.0.0
- poetry-core >=1.8.0
- poetry-dynamic-versioning >=1.9, <2.0.dev
- setuptools
- pip
run:
Expand Down Expand Up @@ -61,6 +62,7 @@ tests:
- geoh5py
- dask
- distributed
- simpeg_drivers._version
pip_check: true

- script:
Expand Down
12 changes: 9 additions & 3 deletions simpeg_drivers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@

from __future__ import annotations

import logging
from importlib.metadata import PackageNotFoundError, version
from pathlib import Path

__version__ = "0.4.0a1"

try:
from ._version import __version__
except ModuleNotFoundError:
from datetime import datetime

import logging
from pathlib import Path
__date_str = datetime.today().strftime("%Y%m%d")
__version__ = "0.0.0.dev0+" + __date_str


logging.basicConfig(level=logging.INFO)
Expand Down
14 changes: 9 additions & 5 deletions simpeg_drivers/uijson.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,20 @@ class SimPEGDriversUIJson(BaseUIJson):
@field_validator("version", mode="before")
@classmethod
def verify_and_update_version(cls, value: str) -> str:
package_version = cls.comparable_version(simpeg_drivers.__version__)
input_version = cls.comparable_version(value)
if input_version != package_version:
if not value:
value = simpeg_drivers.__version__

input_public = Version(str(value)).public
package_public = Version(simpeg_drivers.__version__).public

if input_public != package_public:
logger.warning(
"Provided ui.json file version '%s' does not match the current "
"simpeg-drivers version '%s'. This may lead to unpredictable behavior.",
value,
simpeg_drivers.__version__,
)
return value
return input_public

@staticmethod
def comparable_version(value: str) -> str:
Expand Down Expand Up @@ -71,7 +75,7 @@ def write_default(cls):

with open(cls.default_ui_json, encoding="utf-8") as file:
data = json.load(file)
data["version"] = simpeg_drivers.__version__
data["version"] = Version(simpeg_drivers.__version__).public

uijson = cls.model_construct(**data)
data = uijson.model_dump_json(indent=4, exclude_unset=False)
Expand Down
54 changes: 40 additions & 14 deletions tests/version_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,17 @@

from __future__ import annotations

import importlib
from pathlib import Path

import tomli as toml
import pytest
import yaml
from jinja2 import Template
from packaging.version import InvalidVersion, Version

import simpeg_drivers


def get_pyproject_version():
path = Path(__file__).resolve().parents[1] / "pyproject.toml"

with open(str(path), encoding="utf-8") as file:
pyproject = toml.loads(file.read())

return pyproject["project"]["version"]


def get_conda_recipe_version():
path = Path(__file__).resolve().parents[1] / "recipe.yaml"

Expand All @@ -45,10 +37,44 @@ def get_conda_recipe_version():


def test_version_is_consistent():
assert simpeg_drivers.__version__ == get_pyproject_version()
normalized_conda_version = Version(get_conda_recipe_version())
normalized_version = Version(simpeg_drivers.__version__)
assert normalized_conda_version == normalized_version
project_version = Version(simpeg_drivers.__version__)
conda_version = Version(get_conda_recipe_version())
assert conda_version.base_version == project_version.base_version


def _version_module_exists():
try:
importlib.import_module("simpeg_drivers._version")
return True
except ModuleNotFoundError:
return False


@pytest.mark.skipif(
_version_module_exists(),
reason="simpeg_drivers._version can be found: package is built",
)
def test_fallback_version_is_zero():
project_version = Version(simpeg_drivers.__version__)
fallback_version = Version("0.0.0.dev0")
assert project_version.base_version == fallback_version.base_version
assert project_version.pre is None
assert project_version.post is None
assert project_version.dev == fallback_version.dev


@pytest.mark.skipif(
not _version_module_exists(),
reason="simpeg_drivers._version cannot be found: uses a fallback version",
)
def test_conda_version_is_consistent():
project_version = Version(simpeg_drivers.__version__)
conda_version = Version(get_conda_recipe_version())

assert conda_version.is_devrelease == project_version.is_devrelease
assert conda_version.is_prerelease == project_version.is_prerelease
assert conda_version.is_postrelease == project_version.is_postrelease
assert conda_version == project_version


def test_conda_version_is_pep440():
Expand Down
Loading