From 185b02d3abd77d6113cae15a692b95754c83a0fb Mon Sep 17 00:00:00 2001 From: Davide Marchegiani Date: Tue, 3 Dec 2024 18:30:28 +1100 Subject: [PATCH] First commit to setup the project skeleton --- .conda/env_build.yml | 10 ++++ .conda/env_dev.yml | 19 +++++++ .conda/meta.yaml | 42 +++++++++++++++ .gitattributes | 1 + .github/workflows/CD.yml | 71 ++++++++++++++++++++++++ .github/workflows/CI.yml | 111 ++++++++++++++++++++++++++++++++++++++ .gitignore | 5 ++ README.md | 58 +------------------- pyproject.toml | 57 ++++++++++++++++++++ setup.py | 7 +++ src/tests/__init__.py | 0 src/um_modify/__init__.py | 0 12 files changed, 325 insertions(+), 56 deletions(-) create mode 100644 .conda/env_build.yml create mode 100644 .conda/env_dev.yml create mode 100644 .conda/meta.yaml create mode 100644 .gitattributes create mode 100644 .github/workflows/CD.yml create mode 100644 .github/workflows/CI.yml create mode 100644 .gitignore create mode 100644 pyproject.toml create mode 100644 setup.py create mode 100644 src/tests/__init__.py create mode 100644 src/um_modify/__init__.py diff --git a/.conda/env_build.yml b/.conda/env_build.yml new file mode 100644 index 0000000..7af8f60 --- /dev/null +++ b/.conda/env_build.yml @@ -0,0 +1,10 @@ +channels: + - accessnri + - conda-forge + - nodefaults + +dependencies: + - anaconda-client + - conda-build + - conda-verify + - versioneer \ No newline at end of file diff --git a/.conda/env_dev.yml b/.conda/env_dev.yml new file mode 100644 index 0000000..f047d3b --- /dev/null +++ b/.conda/env_dev.yml @@ -0,0 +1,19 @@ +name: um-modify +channels: + - accessnri + - conda-forge + - coecms + - nodefaults + +dependencies: + - python >=3.10 + - mule + - numpy <2 + - versioneer + - xarray + - hypothesis + - ipykernel + - pip + - pytest + - pytest-cov + - ruff \ No newline at end of file diff --git a/.conda/meta.yaml b/.conda/meta.yaml new file mode 100644 index 0000000..4f766a6 --- /dev/null +++ b/.conda/meta.yaml @@ -0,0 +1,42 @@ +{% set version = load_setup_py_data(setup_file='../setup.py', from_recipe_dir=True).get('version') %} +{% set project = load_file_data('../pyproject.toml', from_recipe_dir=True).get('project') %} + +package: + name: {{ project.get('name') }} + version: "{{ version }}" + +build: + noarch: python + number: 0 + entry_points: + {% for name, script in project.get('scripts').items() %} + - {{ name }} = {{ script }} + {% endfor %} + +source: + path: ../src + +requirements: + host: + - python + - pip + - setuptools >=61.0.0 + - versioneer + run: + {% for dep in project.get('dependencies') %} + - {{ dep }} + {% endfor %} + +test: + commands: + {% for name, script in project.get('scripts').items() %} + - {{ name }} --help + {% endfor %} + +about: + home: {{ project.get('urls').get('Repository') }} + license: Apache Software + license_file: LICENSE + summary: {{ project.get('description') }} + license_family: Apache + diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b9016ab --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/um-modify/_version.py export-subst diff --git a/.github/workflows/CD.yml b/.github/workflows/CD.yml new file mode 100644 index 0000000..4d5cd5b --- /dev/null +++ b/.github/workflows/CD.yml @@ -0,0 +1,71 @@ +name: CD + +on: + push: + tags: + - '**' + +jobs: + get-package-name: + name: Get package name + runs-on: ubuntu-latest + outputs: + package-name: ${{ steps.get-package-name.outputs.package-name }} + steps: + - name: Checkout source + uses: actions/checkout@v4 + with: + fetch-tags: true + fetch-depth: 0 + + - name: Get name + id: get-package-name + run: | + echo "package-name=$(yq '.project.name' pyproject.toml)" >> $GITHUB_OUTPUT + + release-conda-package: + name: Build with conda and release + runs-on: ubuntu-latest + needs: get-package-name + env: + BUILD_FOLDER: ${{github.workspace}}/build + PACKAGE_PATH: ${{github.workspace}}/build/noarch/*.tar.bz2 + permissions: + contents: write + steps: + - name: Checkout source + uses: actions/checkout@v4 + with: + fetch-tags: true + fetch-depth: 0 + + - name: Setup conda build environment + uses: conda-incubator/setup-miniconda@a4260408e20b96e80095f42ff7f1a15b27dd94ca # v3.0.4 + with: + miniconda-version: "latest" + python-version: ${{ vars.PY_VERSION }} + environment-file: .conda/env_build.yml + auto-activate-base: false + auto-update-conda: false + show-channel-urls: true + + - name: Build conda package + shell: bash -el {0} + run: | + conda build . --no-anaconda-upload --output-folder=${{env.BUILD_FOLDER}} -c accessnri -c conda-forge + # Channels needed for the conda recipe tests + + - name: Upload conda package to Anaconda.org + shell: bash -el {0} + run: | + anaconda -t ${{ secrets.ANACONDA_TOKEN }} upload --user ${{ secrets.ANACONDA_USER_NAME }} ${{env.PACKAGE_PATH}} + + - name: Create Release + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 #v2.0.8 + with: + tag_name: ${{ github.ref_name }} + name: ${{needs.get-package-name.outputs.package-name}} ${{ github.ref_name }} + generate_release_notes: true + fail_on_unmatched_files: true + files: | + ${{env.PACKAGE_PATH}} \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..0fe3725 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,111 @@ +name: CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + workflow_dispatch: + +jobs: + changes: + runs-on: ubuntu-latest + permissions: + pull-requests: read + outputs: + tracked-files: ${{ steps.filter.outputs.tracked-files }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Filter files + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 #v3.0.2 + id: filter + with: + filters: | + tracked-files: + - 'setup.py' + - 'pyproject.toml' + - '.conda/**' + - 'src/**' + + verify-conda-build: + name: Verify Conda Build + runs-on: ubuntu-latest + needs: changes + # Only run if there are changes in the tracked files + if: ${{ needs.changes.outputs.tracked-files == 'true' }} + steps: + - uses: actions/checkout@v4 + + - name: Setup conda build environment + uses: conda-incubator/setup-miniconda@a4260408e20b96e80095f42ff7f1a15b27dd94ca # v3.0.4 + with: + miniconda-version: "latest" + python-version: ${{ vars.PY_VERSION }} + environment-file: .conda/env_build.yml + auto-activate-base: false + auto-update-conda: false + show-channel-urls: true + + - name: Verify conda recipe + shell: bash -el {0} + run: conda-verify .conda --ignore C2105,C2122 + # C2105: invalid package version for 'replace_landsurface' + # (there is no git tag in this test so versioneer outputs a + # version that conda-verify recognizes as 'invalid') + # C2122: invalid license family + # Reference --> https://github.com/conda/conda-verify?tab=readme-ov-file#checks + + - name: Build conda package + shell: bash -el {0} + run: conda build . --no-anaconda-upload --output-folder=./build -c accessnri -c conda-forge + # channels needed for the conda recipe tests + + - name: Verify conda package + shell: bash -el {0} + run: conda-verify ./build/noarch/*.tar.bz2 --ignore C1105,C1115,C1141 + # C1105: invalid version number for 'replace_landsurface' + # (there is no git tag in this test so versioneer outputs a + # version that conda-verify recognizes as 'invalid') + # C1115: Found invalid license + # C1141: Found python file without a corresponding pyc file + # Reference --> https://github.com/conda/conda-verify?tab=readme-ov-file#checks + + tests: + name: Tests + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + steps: + - name: Checkout code + uses: actions/checkout@v4.1.7 + + - name: Setup conda environment + uses: conda-incubator/setup-miniconda@a4260408e20b96e80095f42ff7f1a15b27dd94ca # v3.0.4 + with: + miniconda-version: "latest" + python-version: ${{ matrix.python-version }} + environment-file: .conda/env_dev.yml + activate-environment: um-modify + auto-update-conda: false + auto-activate-base: false + show-channel-urls: true + + - name: Install source + shell: bash -l {0} + run: python3 -m pip install --no-deps --no-build-isolation -e . + + - name: List installed packages + shell: bash -l {0} + run: conda list + + - name: Test of um-modify entry point + shell: bash -l {0} + run: um-modify --help + + - name: Run tests + shell: bash -l {0} + run: python3 -m pytest -s -v \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8398b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.coverage +__pycache__/ +*.py[cod] +.*_cache/ +.vscode/ \ No newline at end of file diff --git a/README.md b/README.md index bfc8e73..1816c6d 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,3 @@ -# General Repository Template +# um-modify -A general template repository for default settings when creating new repositories. - -This repository uses the Apache-2.0 license. `COPYRIGHT.txt` contains a current copyright statement which should be included at the top of all files. - -When creating a new repository you [can use this repository as a template](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template), to automate the creation of the correct license and COPYRIGHT statement. - -## COPYRIGHT Header - -Best practice suggests adding a copyright statement at the top of every source code file, or text file where it is possible to add a copyright statement without interfering with the purpose of the file. The reasoning is if a file is separated from the repository in which it resides then it may not be possible to ascertain it's licensing, which may hamper re-use. - -Making this as short and concise as possible reduces the overhead in including such a copyright statement. To that end using [SPDX identifiers](https://spdx.dev/ids/) is simple, efficient, portable and machine-readable. - -### Examples - -An example, short, copyright statement is reproduced below, as it might appear in different coding languages. Copy and add to files as appropriate: - -#### plaintext -It is common to include copyright statements at the bottom of a text document or website page -```text -© 2022 ACCESS-NRI and contributors. See the top-level COPYRIGHT file for details. -SPDX-License-Identifier: Apache-2.0 -``` - -#### python -For code it is more common to include the copyright in a comment at the top -```python -# Copyright 2022 ACCESS-NRI and contributors. See the top-level COPYRIGHT file for details. -# SPDX-License-Identifier: Apache-2.0 -``` - -#### shell -```bash -# Copyright 2022 ACCESS-NRI and contributors. See the top-level COPYRIGHT file for details. -# SPDX-License-Identifier: Apache-2.0 -``` - -##### FORTRAN -```fortran -! Copyright 2022 ACCESS-NRI and contributors. See the top-level COPYRIGHT file for details. -! SPDX-License-Identifier: Apache-2.0 -``` - -#### C/C++ -```c -// Copyright 2022 ACCESS-NRI and contributors. See the top-level COPYRIGHT file for details. -// SPDX-License-Identifier: Apache-2.0 -``` - -### Notes - -Note that the date is the first time the project is created. - -The date signifies the year from which the copyright notice applies. **NEVER** replace with a later year, only ever add later years or a year range. - -It is not necessary to include subsequent years in the copyright statement at all unless updates have been made at a later time, and even then it is largely discretionary: they are not necessary as copyright is contingent on the lifespan of copyright holder +50 years as per the [Berne Convention](https://en.wikipedia.org/wiki/Berne_Convention). +`um-modify` is a standalone Python module used to modify the data of a UM file. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..eb0cd86 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,57 @@ +[project] +name = "um-modify" +authors = [ + {name = "Davide Marchegiani", email="davide.marchegiani@anu.edu.au"}, +] +maintainers = [ + { name = "ACCESS-NRI", email = "access.nri@anu.edu.au" } +] +description = "Package to modify the data of a UM file." +license = { file = "LICENSE" } +readme = "README.md" +keywords = ["ACCESS-CM2", "ACCESS-ESM1.5", "ACCESS-ESM1.6", "Unified Model"] +dynamic = ["version"] +requires-python = ">=3.10" +dependencies = [ + "mule", + "numpy < 2", + "versioneer", +] + +[project.urls] +Repository = "https://github.com/ACCESS-NRI/um-modify" + +[project.scripts] +um-modify = "TODO" # TODO: Add the script + +[build-system] +build-backend = "setuptools.build_meta" +requires = [ + "setuptools>64", + "versioneer[toml]" +] + +[tool.setuptools.packages.find] +where = ["src"] +namespaces = false + +[tool.versioneer] +VCS = "git" +style = "pep440" +versionfile_source = "src/um_modify/_version.py" +versionfile_build = "um_modify/_version.py" +tag_prefix = "" +parentdir_prefix = "um-modify-" + +[tool.pytest.ini_options] +testpaths = ["src"] +addopts = ["--cov=src"] + +[tool.coverage.run] +branch = true +source = ["src/"] + +[tool.coverage.report] +omit = ["src/*/_version.py"] +skip_empty = true +show_missing = true \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..d14fa5b --- /dev/null +++ b/setup.py @@ -0,0 +1,7 @@ +import versioneer +from setuptools import setup + +setup( + version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), +) diff --git a/src/tests/__init__.py b/src/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/um_modify/__init__.py b/src/um_modify/__init__.py new file mode 100644 index 0000000..e69de29