diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5ace460 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b62a6f..0c90e01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,11 +7,16 @@ on: pull_request: branches: - "*" + release: + branch: main + types: [released] jobs: check: name: Check runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout the Repository uses: actions/checkout@v4 @@ -21,9 +26,23 @@ jobs: with: args: check + spelling: + name: Spellcheck + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout the Repository + uses: actions/checkout@v7 + + - name: Spellcheck repo + uses: crate-ci/typos@v1 + fmt: name: Formatting runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout the Repository uses: actions/checkout@v4 @@ -33,9 +52,37 @@ jobs: with: args: "format --diff --check" + build: + name: Build + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout the Repository + uses: actions/checkout@v7 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Build all packages + run: uv build --all-packages + + - name: List the built dist files + run: ls -lh dist/ + + - name: Upload the package sdist and wheels + uses: actions/upload-artifact@v7 + with: + name: dist + path: dist + retention-days: 1 + mypy: name: Typecheck runs-on: ubuntu-latest + permissions: + contents: read + needs: build steps: - name: Checkout the Repository uses: actions/checkout@v4 @@ -43,11 +90,50 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 - - name: Setup Python - run: uv python install + - name: Download the dist artifact + uses: actions/download-artifact@v8 + with: + name: dist + path: dist + + - name: Install the typing dependencies + run: | + uv sync --refresh --no-install-workspace \ + --all-groups - - name: Install the package - run: uv sync && uv pip install . + - name: Install the workspace packages + run: | + uv pip install dist/*.whl - name: Typecheck the package run: uv run mypy -p climatebenchpress.compressor + + publish: + name: Publish to PyPi + runs-on: ubuntu-latest + environment: pypi + permissions: + contents: read + id-token: write + if: ${{ github.event_name == 'release' }} + needs: + # require all jobs to succeed + - check + - spelling + - fmt + - build # includes the dist artifact + - mypy + steps: + - name: Download the dist artifact + uses: actions/download-artifact@v8 + with: + name: dist + path: dist + + - name: List the built dist files + run: ls -lh dist/ + + - name: Publish the packages + uses: pypa/gh-action-pypi-publish@release/v1 + with: + skip-existing: true diff --git a/.gitignore b/.gitignore index 9fa3ab6..5c8d13c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ **/__pycache__ **/*.egg-info +**/.DS_Store +**/.ipynb_checkpoints diff --git a/_typos.toml b/_typos.toml new file mode 100644 index 0000000..cf2872f --- /dev/null +++ b/_typos.toml @@ -0,0 +1,2 @@ +[default.extend-identifiers] +ower = "ower" diff --git a/pyproject.toml b/pyproject.toml index 5a6be5c..39919a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,36 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + [project] -name = "climatebenchpress.compressor" -version = "0.1.0" -description = "Add your description here" -readme = "README.md" +name = "climatebenchpress-compressor" +version = "1.0.0" requires-python = ">=3.12" +authors = [ + { name = "Tim Reichelt", email = "tim.reichelt@physics.ox.ac.uk" }, + { name = "Juniper Tyree", email = "juniper.tyree@helsinki.fi" }, +] +description = "ClimateBenchPress compression benchmark" +readme = "README.md" +license = "MPL-2.0" +keywords = ["climate", "compression", "benchmark", "compressors", "weather"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Atmospheric Science", + "Topic :: System :: Archiving :: Compression", + "Typing :: Typed", +] + dependencies = [ "astropy~=7.2.0", "cartopy~=0.24.1", @@ -52,8 +79,8 @@ dev = [ "types-seaborn~=0.13.2.20250111", ] -[tool.setuptools.packages.find] -where = ["src"] +[tool.hatch.build.targets.wheel] +packages = ["src/climatebenchpress"] [tool.setuptools.package-data] "climatebenchpress.compressor" = ["py.typed"] diff --git a/src/climatebenchpress/compressor/compressors/jpeg2000.py b/src/climatebenchpress/compressor/compressors/jpeg2000.py index afe23d9..70ece81 100644 --- a/src/climatebenchpress/compressor/compressors/jpeg2000.py +++ b/src/climatebenchpress/compressor/compressors/jpeg2000.py @@ -50,7 +50,7 @@ def abs_bound_codec( # Here we use the formula for the PSNR (https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio) # to convert between the absolute error and the PSNR value. # The original PSNR formula uses the root mean square error (RMSE), - # therefore JPEG does not guaruantee pointwise error bounds but only + # therefore JPEG does not guarantee pointwise error bounds but only # average error bounds. psnr = 20 * (math.log10(data_range) - math.log10(error_bound))