diff --git a/.github/scripts/parse_bump_rule.py b/.github/scripts/parse_bump_rule.py new file mode 100644 index 0000000..d7e35fe --- /dev/null +++ b/.github/scripts/parse_bump_rule.py @@ -0,0 +1,18 @@ +import sys +import os + + +def parse(message): + if "#prerelease" in message: + return 'prerelease' + + for pre in ['pre', '']: + for level in ['patch', 'minor', 'major']: + if f'#{pre}{level}' in message: + return f'{pre}{level}' + + return 'patch' + + +message = os.environ['github_event_head_commit_message'] +print(parse(message)) diff --git a/.github/scripts/parse_version.py b/.github/scripts/parse_version.py new file mode 100644 index 0000000..2f7387e --- /dev/null +++ b/.github/scripts/parse_version.py @@ -0,0 +1,11 @@ +import sys + + +def parse(f): + import tomli + with open(f, "rb") as fp: + pyproject = tomli.load(fp) + return pyproject["tool"]["poetry"]["version"] + + +print(parse(sys.argv[1])) diff --git a/.github/scripts/update_versions.py b/.github/scripts/update_versions.py new file mode 100644 index 0000000..abaeb6d --- /dev/null +++ b/.github/scripts/update_versions.py @@ -0,0 +1,17 @@ +import os +import re +import fileinput + + +def update(version): + files = ("pyproject.toml", "setup.py", "src/quaternion/__init__.py") + pattern = re.compile('^(__version__|version) *= *".*?"') + replacement = r'\1 = "' + version + '"' + with fileinput.input(files=files, inplace=True) as f: + for line in f: + print(pattern.sub(replacement, line), end="") + + +version = os.environ["new_version"] + +update(version) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c79d6f..3663458 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,12 +8,54 @@ name: tests on: [push] jobs: + + get_new_version: + name: Get new version number + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.version }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.10' + + - name: Install tomli + shell: bash + run: | + python -m pip install --upgrade pip tomli + + - name: Install poetry + shell: bash + run: | + curl -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py + python get-poetry.py -y + + - name: Bump version + id: get_version + shell: bash + env: + github_event_head_commit_message: ${{ github.event.head_commit.message }} + run: | + export version_bump_rule=$(python .github/scripts/parse_bump_rule.py) + echo "version_bump_rule: '${version_bump_rule}'" + $HOME/.poetry/bin/poetry version "${version_bump_rule}" + export new_version=$(python .github/scripts/parse_version.py pyproject.toml) + echo "new_version: '${new_version}'" + echo "::set-output name=version::${new_version}" + + build_wheels: + needs: get_new_version name: Build wheels on ${{ matrix.os }} for ${{matrix.archs}} runs-on: ${{ matrix.os }} - if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + if: >- + !contains(github.event.head_commit.message, '[skip ci]') + && !contains(github.event.head_commit.message, '[skip tests]') strategy: fail-fast: false @@ -49,6 +91,13 @@ jobs: with: python-version: '3.8' + - name: Update versions + shell: bash + run: | + export new_version=${{needs.get_new_version.outputs.version}} + echo "Updating version to '${new_version}'" + python .github/scripts/update_versions.py + - name: Install cibuildwheel run: | python -m pip install --upgrade pip @@ -64,6 +113,7 @@ jobs: build_sdist: + needs: get_new_version name: Build source distribution runs-on: ubuntu-latest outputs: @@ -76,19 +126,18 @@ jobs: with: python-version: '3.8' + - name: Update versions + shell: bash + run: | + export new_version=${{needs.get_new_version.outputs.version}} + echo "Updating version to '${new_version}'" + python .github/scripts/update_versions.py + - name: Build sdist run: | python -m pip install oldest-supported-numpy python setup.py sdist - - name: Get version - id: get_version - run: | - # Note: This requires numpy, so it must run after the build step - export new_version=$(python -c 'import setup; print(setup.version)') - echo "Found version ${new_version}" - echo "::set-output name=version::${new_version}" - - uses: actions/upload-artifact@v2 with: path: dist/*.tar.gz @@ -96,33 +145,41 @@ jobs: upload_pypi: needs: [build_wheels, build_sdist] + name: Tag and release runs-on: ubuntu-latest - if: "github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[no release]')" - # # upload to PyPI on every tag starting with 'v' - # if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') - # # publish when a GitHub Release is created - # if: github.event_name == 'release' && github.event.action == 'published' + if: >- + github.ref == 'refs/heads/main' + && !contains(github.event.head_commit.message, '[no release]') + && (success() || contains(github.event.head_commit.message, '[skip tests]')) steps: - - uses: actions/checkout@v2 - # Needed for the git actions + - name: Check out code + uses: actions/checkout@v2 - uses: actions/download-artifact@v2 with: name: artifact path: dist - - name: Get latest version + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.10' + + - name: Update versions + shell: bash run: | - export new_version=${{needs.build_sdist.outputs.version}} - echo "new_version: '${new_version}'" + export new_version=${{needs.get_new_version.outputs.version}} + echo "Updating version to '${new_version}'" echo "new_version=${new_version}" >> $GITHUB_ENV + python .github/scripts/update_versions.py - name: Tag and push new version shell: bash run: | git config user.name github-actions git config user.email github-actions@github.com + git commit -m "Update version for new release" pyproject.toml setup.py src/quaternion/__init__.py git tag -a "v${new_version}" -m "Version ${new_version}" git status git push --follow-tags # Will not trigger new workflow because it uses GITHUB_TOKEN diff --git a/pyproject.toml b/pyproject.toml index b4bd28c..cf8ea83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,12 @@ +[tool.poetry] +name = "quaternion" +version = "2022.3.0" +description = "Add a quaternion dtype to NumPy" +readme = "README.md" +license = "MIT" +authors = ["Michael Boyle "] +homepage = "https://github.com/moble/quaternion" + [tool.pytest.ini_options] minversion = "6.0" norecursedirs = ".* build dist *.egg-info install ENV" diff --git a/setup.py b/setup.py index 5171ef4..051271c 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ # Set this first for easier replacement -version = "2022.2.10.14.20.39" +version = "2022.3.0" if "win" in platform.lower() and not "darwin" in platform.lower(): extra_compile_args = ["/O2"] diff --git a/src/quaternion/__init__.py b/src/quaternion/__init__.py index 23012cb..d961a39 100644 --- a/src/quaternion/__init__.py +++ b/src/quaternion/__init__.py @@ -3,7 +3,7 @@ # Copyright (c) 2021, Michael Boyle # See LICENSE file for details: -__version__ = "2022.2.10.14.20.39" +__version__ = "2022.3.0" __doc_title__ = "Quaternion dtype for NumPy" __doc__ = "Adds a quaternion dtype to NumPy." __all__ = ['quaternion', @@ -204,7 +204,7 @@ def as_spinor_array(a): assert a.dtype == np.dtype(np.quaternion) # I'm not sure why it has to be so complicated, but all of these steps # appear to be necessary in this case. - return a.view(np.float64).reshape(a.shape + (4,))[..., [0, 3, 2, 1]].ravel().view(np.complex).reshape(a.shape + (2,)) + return a.view(np.float64).reshape(a.shape + (4,))[..., [0, 3, 2, 1]].ravel().view(np.complex128).reshape(a.shape + (2,)) def as_rotation_matrix(q): diff --git a/src/quaternion/calculus.py b/src/quaternion/calculus.py index 2870169..850bc70 100644 --- a/src/quaternion/calculus.py +++ b/src/quaternion/calculus.py @@ -466,15 +466,15 @@ def spline_definite_integral(f, t, t1=None, t2=None, axis=0): indefinite_integral = spline_indefinite_integral definite_integral = spline_definite_integral except ImportError: - import warnings - warning_text = ( - "\n\n" + "!" * 57 + "\n" + - "Could not import from scipy, which means that derivatives\n" + - "and integrals will use less accurate finite-differencing\n" + - "techniques. You may want to install scipy." + - "\n" + "!" * 57 + "\n" - ) - warnings.warn(warning_text) + # import warnings + # warning_text = ( + # "\n\n" + "!" * 57 + "\n" + + # "Could not import from scipy, which means that derivatives\n" + + # "and integrals will use less accurate finite-differencing\n" + + # "techniques. You may want to install scipy." + + # "\n" + "!" * 57 + "\n" + # ) + # warnings.warn(warning_text) derivative = fd_derivative antiderivative = fd_indefinite_integral indefinite_integral = fd_indefinite_integral diff --git a/src/quaternion/numba_wrapper.py b/src/quaternion/numba_wrapper.py index 931505d..805c652 100644 --- a/src/quaternion/numba_wrapper.py +++ b/src/quaternion/numba_wrapper.py @@ -13,14 +13,14 @@ from numba import njit, jit, vectorize, int64, float64, complex128 GOT_NUMBA = True except ImportError: - import warnings - warning_text = \ - "\n\n" + "!" * 53 + "\n" + \ - "Could not import from numba, which means that some\n" + \ - "parts of this code may run MUCH more slowly. You\n" + \ - "may wish to install numba." + \ - "\n" + "!" * 53 + "\n" - warnings.warn(warning_text) + # import warnings + # warning_text = \ + # "\n\n" + "!" * 53 + "\n" + \ + # "Could not import from numba, which means that some\n" + \ + # "parts of this code may run MUCH more slowly. You\n" + \ + # "may wish to install numba." + \ + # "\n" + "!" * 53 + "\n" + # warnings.warn(warning_text) def _identity_decorator_outer(*args, **kwargs): def _identity_decorator_inner(fn): return fn