Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-mmh3 for openSUSE:Factory checked in at 2026-03-12 22:21:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-mmh3 (Old) and /work/SRC/openSUSE:Factory/.python-mmh3.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-mmh3" Thu Mar 12 22:21:48 2026 rev:4 rq:1338414 version:5.2.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-mmh3/python-mmh3.changes 2025-09-22 16:40:35.979730462 +0200 +++ /work/SRC/openSUSE:Factory/.python-mmh3.new.8177/python-mmh3.changes 2026-03-12 22:26:30.836722954 +0100 @@ -1,0 +2,6 @@ +Thu Mar 12 07:51:07 UTC 2026 - Dirk Müller <[email protected]> + +- update to 5.2.1: + * Add support for the Android wheel for Python 3.14. + +------------------------------------------------------------------- Old: ---- mmh3-5.2.0.tar.gz New: ---- mmh3-5.2.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-mmh3.spec ++++++ --- /var/tmp/diff_new_pack.3s00M9/_old 2026-03-12 22:26:31.484750120 +0100 +++ /var/tmp/diff_new_pack.3s00M9/_new 2026-03-12 22:26:31.492750455 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-mmh3 # -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-mmh3 -Version: 5.2.0 +Version: 5.2.1 Release: 0 Summary: Python extension for MurmurHash (MurmurHash3) License: MIT ++++++ mmh3-5.2.0.tar.gz -> mmh3-5.2.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/actionlint.yml new/mmh3-5.2.1/.github/actionlint.yml --- old/mmh3-5.2.0/.github/actionlint.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/mmh3-5.2.1/.github/actionlint.yml 2026-03-05 16:11:36.000000000 +0100 @@ -0,0 +1,6 @@ +# As of March 5, 2026, actionlint via super-linter 8.5.0 does not support macOS 26, so we ignore the runner-label warning for now. +paths: + .github/workflows/**/*.{yml,yaml}: + ignore: + - 'label "macos-26" is unknown.+' + - 'label "macos-26-intel" is unknown.+' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/dependabot.yml new/mmh3-5.2.1/.github/dependabot.yml --- old/mmh3-5.2.0/.github/dependabot.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/dependabot.yml 2026-03-05 16:11:36.000000000 +0100 @@ -4,15 +4,23 @@ directory: "/" schedule: interval: "weekly" + day: "monday" + open-pull-requests-limit: 5 groups: dependencies: patterns: - "*" + cooldown: + default-days: 7 - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" + day: "monday" + open-pull-requests-limit: 5 groups: dependencies: patterns: - "*" + cooldown: + default-days: 7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/benchmark-base-hash.yml new/mmh3-5.2.1/.github/workflows/benchmark-base-hash.yml --- old/mmh3-5.2.0/.github/workflows/benchmark-base-hash.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/benchmark-base-hash.yml 2026-03-05 16:11:36.000000000 +0100 @@ -16,11 +16,13 @@ BENCHMARK_MAX_SIZE: 65536 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: "3.13" + python-version: "3.14" - name: Install dependencies run: | pip install --upgrade pip @@ -85,7 +87,7 @@ sudo systemctl restart irqbalance systemctl status irqbalance - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: benchmark-results path: var diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/benchmark.yml new/mmh3-5.2.1/.github/workflows/benchmark.yml --- old/mmh3-5.2.0/.github/workflows/benchmark.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/benchmark.yml 2026-03-05 16:11:36.000000000 +0100 @@ -16,11 +16,13 @@ BENCHMARK_MAX_SIZE: 262144 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: "3.13" + python-version: "3.14" - name: Install dependencies run: | pip install --upgrade pip @@ -80,7 +82,7 @@ sudo systemctl restart irqbalance systemctl status irqbalance - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: benchmark-results path: var diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/build.yml new/mmh3-5.2.1/.github/workflows/build.yml --- old/mmh3-5.2.0/.github/workflows/build.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/build.yml 2026-03-05 16:11:36.000000000 +0100 @@ -5,9 +5,7 @@ on: # yamllint disable-line rule:truthy push: - branches: - - master - - feature/** + branches: "**" pull_request: types: - opened @@ -24,15 +22,17 @@ strategy: matrix: - os: [macos-14, windows-2022, ubuntu-24.04] - python-version: - [3.9, "3.10", "3.11", "3.12", "3.13", "3.14-dev", "3.14t-dev"] + os: [macos-26, windows-2025, ubuntu-24.04] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/draft-pdf.yml new/mmh3-5.2.1/.github/workflows/draft-pdf.yml --- old/mmh3-5.2.0/.github/workflows/draft-pdf.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/draft-pdf.yml 2026-03-05 16:11:36.000000000 +0100 @@ -4,8 +4,8 @@ on: push: branches: - - master - paper + workflow_dispatch: permissions: {} @@ -18,17 +18,20 @@ runs-on: ubuntu-latest name: Paper Draft + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/master' steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Build draft PDF - uses: openjournals/openjournals-draft-action@master + uses: openjournals/openjournals-draft-action@85a18372e48f551d8af9ddb7a747de685fbbb01c # v1.0 with: journal: joss # This should be the path to the paper within your repo. paper-path: paper/paper.md - name: Upload - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: paper # This is the output path where Pandoc will write the compiled diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/superlinter.yml new/mmh3-5.2.1/.github/workflows/superlinter.yml --- old/mmh3-5.2.0/.github/workflows/superlinter.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/superlinter.yml 2026-03-05 16:11:36.000000000 +0100 @@ -30,24 +30,31 @@ steps: # Checks out a copy of your repository on the ubuntu-latest machine - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: + persist-credentials: false # super-linter needs the full git history to get the # list of files that changed across commits fetch-depth: 0 # Runs the Super-Linter action - name: Run Super-Linter - uses: super-linter/super-linter@v8 + uses: super-linter/super-linter@61abc07d755095a68f4987d1c2c3d1d64408f1f9 # v8.5.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} LINTER_RULES_PATH: / - PYTHON_ISORT_CONFIG_FILE: pyproject.toml + GITHUB_ACTIONS_CONFIG_FILE: .github/actionlint.yml PYTHON_PYLINT_CONFIG_FILE: pyproject.toml + PYTHON_RUFF_CONFIG_FILE: pyproject.toml + PYTHON_RUFF_FORMAT_CONFIG_FILE: pyproject.toml # Suppressed because it conflicts with clang-format in some cases VALIDATE_CPP: false # Suppressed because copy/paste is sometimes required at low level VALIDATE_JSCPD: false + # Suppressed in favor of Ruff + VALIDATE_PYTHON_BLACK: false + VALIDATE_PYTHON_FLAKE8: false + VALIDATE_PYTHON_ISORT: false # Suppressed because it even accuses book titles VALIDATE_NATURAL_LANGUAGE: false # Suppressed because it does not honor the ignore-paths option @@ -55,9 +62,9 @@ # super-linter 7 does not honor the ignore-paths option of pylint # so we run pylint separately - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: 3.12 + python-version: "3.14" - name: Run pylint run: | pip install pylint diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/test-wheels.yml new/mmh3-5.2.1/.github/workflows/test-wheels.yml --- old/mmh3-5.2.0/.github/workflows/test-wheels.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/test-wheels.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,14 +0,0 @@ ---- -name: Build and Test Wheels - -on: - workflow_dispatch: - -permissions: {} - -jobs: - publish: - permissions: - contents: read - packages: read - uses: ./.github/workflows/wheels.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/upload-pypi.yml new/mmh3-5.2.1/.github/workflows/upload-pypi.yml --- old/mmh3-5.2.0/.github/workflows/upload-pypi.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/upload-pypi.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,20 +0,0 @@ ---- -name: Build and Upload Wheels to PyPI - -on: - workflow_dispatch: - -permissions: {} - -jobs: - publish: - if: github.ref_type == 'tag' - permissions: - contents: read - packages: read - uses: ./.github/workflows/wheels.yml - with: - pypi-repository: "pypi" - secrets: - pypi-username: ${{ secrets.PYPI_USERNAME }} - pypi-password: ${{ secrets.PYPI_PASSWORD }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/upload-testpypi.yml new/mmh3-5.2.1/.github/workflows/upload-testpypi.yml --- old/mmh3-5.2.0/.github/workflows/upload-testpypi.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/upload-testpypi.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,19 +0,0 @@ ---- -name: Build and Upload Wheels to TestPyPI - -on: - workflow_dispatch: - -permissions: {} - -jobs: - publish: - permissions: - contents: read - packages: read - uses: ./.github/workflows/wheels.yml - with: - pypi-repository: "testpypi" - secrets: - pypi-username: ${{ secrets.TEST_PYPI_USERNAME }} - pypi-password: ${{ secrets.TEST_PYPI_PASSWORD }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/.github/workflows/wheels.yml new/mmh3-5.2.1/.github/workflows/wheels.yml --- old/mmh3-5.2.0/.github/workflows/wheels.yml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/.github/workflows/wheels.yml 2026-03-05 16:11:36.000000000 +0100 @@ -2,16 +2,10 @@ name: Wheel-Builder on: - workflow_call: - inputs: - pypi-repository: - required: false - type: string - secrets: - pypi-username: - required: false - pypi-password: - required: false + push: + tags: + - "v*.*.*" + workflow_dispatch: permissions: {} @@ -25,45 +19,66 @@ archs: [x86_64, i686, aarch64, ppc64le, s390x] build: [manylinux, musllinux] include: - - os: windows-2022 + - os: windows-2025 archs: AMD64 - - os: windows-2022 + - os: windows-2025 archs: x86 - - os: windows-2022 + - os: windows-2025 archs: ARM64 - - os: macos-13 + - os: macos-26-intel archs: x86_64 - - os: macos-14 + - os: macos-26 archs: arm64 - - os: macos-14 + - os: macos-26 archs: universal2 - os: ubuntu-24.04 platform: android archs: x86_64 build: android - - os: macos-14 + - os: macos-26 platform: android archs: arm64_v8a build: android - - os: macos-14 + - os: macos-26 platform: ios archs: arm64_iphoneos - - os: macos-14 + - os: macos-26 platform: ios archs: arm64_iphonesimulator - - os: macos-13 + - os: macos-26-intel platform: ios archs: x86_64_iphonesimulator steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: "3.13" + python-version: "3.14" + - name: Set dev version for TestPyPI + if: github.event_name == 'workflow_dispatch' + shell: python + run: | + import re, datetime + timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%d%H%M") + text = open("pyproject.toml", encoding="utf-8").read() + m = re.search(r'version\s*=\s*"(.+?)"', text) + if not m: + raise RuntimeError("version field not found in pyproject.toml") + version = m.group(1) + base_version = version.split("-")[0] + new_text = re.sub( + r'version\s*=\s*".*?"', + f'version = "{base_version}.dev{timestamp}"', + text, + count=1 + ) + open("pyproject.toml", "w", encoding="utf-8").write(new_text) - name: Set up QEMU if: runner.os == 'Linux' && matrix.platform != 'android' - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 # https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/ - name: Set up KVM for Android emulation if: runner.os == 'Linux' && matrix.platform == 'android' @@ -72,11 +87,11 @@ sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - name: Build wheels - uses: pypa/[email protected] + uses: pypa/cibuildwheel@ee02a1537ce3071a004a6b08c41e72f0fdc42d9a # v3.4.0 with: output-dir: wheelhouse env: - CIBW_BUILD: "{cp39,cp310,cp311,cp312,cp313,cp314,cp314t}-${{ matrix.build }}*" + CIBW_BUILD: "{cp310,cp311,cp312,cp313,cp314,cp314t}-${{ matrix.build }}*" CIBW_PLATFORM: ${{ matrix.platform || 'auto' }} CIBW_ARCHS: ${{ matrix.archs }} CIBW_BUILD_FRONTEND: "build" @@ -87,7 +102,7 @@ CIBW_TEST_COMMAND_ANDROID: "python -m pytest ./tests" CIBW_TEST_COMMAND_IOS: "python -m pytest ./tests" CIBW_TEST_SKIP: "*-win_arm64 *-android_arm64_v8a" - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: Wheel-${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.build }}${{ matrix.archs }} path: ./wheelhouse/*.whl @@ -96,11 +111,32 @@ runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: "3.13" + python-version: "3.14" + - name: Set dev version for TestPyPI + if: github.event_name == 'workflow_dispatch' + shell: python + run: | + import re, datetime + timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%d%H%M") + text = open("pyproject.toml", encoding="utf-8").read() + m = re.search(r'version\s*=\s*"(.+?)"', text) + if not m: + raise RuntimeError("version field not found in pyproject.toml") + version = m.group(1) + base_version = version.split("-")[0] + new_text = re.sub( + r'version\s*=\s*".*?"', + f'version = "{base_version}.dev{timestamp}"', + text, + count=1 + ) + open("pyproject.toml", "w", encoding="utf-8").write(new_text) - name: Build sdist run: | python -m pip install --upgrade pip @@ -114,31 +150,44 @@ python -m pip install dist/*.tar.gz python -m pytest mypy --strict tests - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: path: dist/*.tar.gz - publish: - if: ${{ inputs.pypi-repository == 'pypi' || inputs.pypi-repository == 'testpypi'}} - name: "Upload to PyPI/Test PyPI" - runs-on: ubuntu-24.04 + publish-to-pypi: + name: "Publish artifacts to PyPI" + if: startsWith(github.ref, 'refs/tags/') needs: [build_wheels, build_sdist] + runs-on: ubuntu-24.04 + environment: + name: pypi + url: https://pypi.org/p/mmh3 + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing steps: - - name: Set up Python - uses: actions/setup-python@v5 + - name: Set up built items + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: - python-version: "3.13" + path: dist + merge-multiple: true + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + publish-to-testpypi: + name: "Publish artifacts to TestPyPI" + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/master' + needs: [build_wheels, build_sdist] + runs-on: ubuntu-24.04 + environment: + name: testpypi + url: https://test.pypi.org/p/mmh3 + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + steps: - name: Set up built items - uses: actions/download-artifact@v4 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: path: dist merge-multiple: true - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel twine - - name: "Publish" - env: - TWINE_USERNAME: ${{ secrets.pypi-username }} - TWINE_PASSWORD: ${{ secrets.pypi-password }} - run: | - twine upload --repository ${{ inputs.pypi-repository }} dist/* + - name: Publish package distributions to TestPyPI + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + repository-url: https://test.pypi.org/legacy/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/CHANGELOG.md new/mmh3-5.2.1/CHANGELOG.md --- old/mmh3-5.2.0/CHANGELOG.md 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/CHANGELOG.md 2026-03-05 16:11:36.000000000 +0100 @@ -10,6 +10,16 @@ [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) since version 3.0.0. +## [5.2.1] - 2026-03-06 + +### Added + +- Add support for the Android wheel for Python 3.14. + +### Removed + +- Drop support for Python 3.9, as it has reached the end of life on 2025-10-31. + ## [5.2.0] - 2025-07-29 ### Added @@ -81,7 +91,7 @@ - **Backward-incompatible**: Change the constructors of hasher classes to accept a buffer as the first argument ([#83](https://github.com/hajimes/mmh3/pull/83)). -- The type of flag argumens has been changed from `bool` to `Any` +- The type of flag arguments has been changed from `bool` to `Any` ([#84](https://github.com/hajimes/mmh3/pull/84)). - Change the format of CHANGELOG.md to conform to the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) standard @@ -300,6 +310,7 @@ [Softpedia collected mmh3 1.0 on April 27, 2011](https://web.archive.org/web/20110430172027/https://linux.softpedia.com/get/Programming/Libraries/mmh3-68314.shtml), it must have been uploaded to PyPI on or slightly before this date. +[5.2.1]: https://github.com/hajimes/mmh3/compare/v5.2.0...v5.2.1 [5.2.0]: https://github.com/hajimes/mmh3/compare/v5.1.0...v5.2.0 [5.1.0]: https://github.com/hajimes/mmh3/compare/v5.0.1...v5.1.0 [5.0.1]: https://github.com/hajimes/mmh3/compare/v5.0.0...v5.0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/LICENSE new/mmh3-5.2.1/LICENSE --- old/mmh3-5.2.0/LICENSE 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/LICENSE 2026-03-05 16:11:36.000000000 +0100 @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2011-2025 Hajime Senuma +Copyright (c) 2011-2026 Hajime Senuma Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/README.md new/mmh3-5.2.1/README.md --- old/mmh3-5.2.0/README.md 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/README.md 2026-03-05 16:11:36.000000000 +0100 @@ -81,6 +81,16 @@ See [Changelog (latest version)](https://mmh3.readthedocs.io/en/latest/changelog.html) for the complete changelog. +### [5.2.1] - 2026-03-06 + +#### Added + +- Add support for the Android wheel for Python 3.14. + +#### Removed + +- Drop support for Python 3.9, as it has reached the end of life on 2025-10-31. + ### [5.2.0] - 2025-07-29 #### Added @@ -114,13 +124,6 @@ - Drop support for Python 3.8, as it has reached the end of life on 2024-10-07 ([#117](https://github.com/hajimes/mmh3/pull/117)). -### [5.0.1] - 2024-09-22 - -#### Fixed - -- Fix the issue that the package cannot be built from the source distribution - ([#90](https://github.com/hajimes/mmh3/issues/90)). - ## License [MIT](https://github.com/hajimes/mmh3/blob/master/LICENSE), unless otherwise @@ -193,8 +196,8 @@ - Chapter 11: _Using Less Ram_ in Micha Gorelick and Ian Ozsvald. 2014. _High Performance Python: Practical Performant Programming for Humans_. O'Reilly Media. [ISBN: 978-1-4493-6159-4](https://www.amazon.com/dp/1449361595). - - 2nd edition of the above (2020). - [ISBN: 978-1492055020](https://www.amazon.com/dp/1492055026). + - 3rd edition of the above (2025). + [ISBN: 978-1098165963](https://www.amazon.com/dp/1098165969/). - Max Burstein. February 2, 2013. _[Creating a Simple Bloom Filter](http://www.maxburstein.com/blog/creating-a-simple-bloom-filter/)_. - Duke University. April 14, 2016. @@ -267,6 +270,6 @@ - <https://github.com/ifduyue/python-xxhash>: Python bindings for xxHash (Yue Du) +[5.2.1]: https://github.com/hajimes/mmh3/compare/v5.2.0...v5.2.1 [5.2.0]: https://github.com/hajimes/mmh3/compare/v5.1.0...v5.2.0 [5.1.0]: https://github.com/hajimes/mmh3/compare/v5.0.1...v5.1.0 -[5.0.1]: https://github.com/hajimes/mmh3/compare/v5.0.0...v5.0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/benchmark/benchmark.py new/mmh3-5.2.1/benchmark/benchmark.py --- old/mmh3-5.2.0/benchmark/benchmark.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/benchmark/benchmark.py 2026-03-05 16:11:36.000000000 +0100 @@ -8,11 +8,12 @@ from collections.abc import Callable from typing import Final -import mmh3 import pymmh3 import pyperf import xxhash +import mmh3 + K1: Final[int] = 0b1001111000110111011110011011000110000101111010111100101010000111 K2: Final[int] = 0b1100001010110010101011100011110100100111110101001110101101001111 MASK: Final[int] = 0xFFFFFFFFFFFFFFFF diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/benchmark/generate_table.py new/mmh3-5.2.1/benchmark/generate_table.py --- old/mmh3-5.2.0/benchmark/generate_table.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/benchmark/generate_table.py 2026-03-05 16:11:36.000000000 +0100 @@ -9,11 +9,12 @@ import os from typing import TypeVar -import mmh3 import pandas as pd import pyperf import xxhash +import mmh3 + T = TypeVar("T") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/benchmark/plot_graph.py new/mmh3-5.2.1/benchmark/plot_graph.py --- old/mmh3-5.2.0/benchmark/plot_graph.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/benchmark/plot_graph.py 2026-03-05 16:11:36.000000000 +0100 @@ -6,11 +6,12 @@ from typing import TypeVar import matplotlib.pyplot as plt -import mmh3 import pandas as pd import pyperf import xxhash +import mmh3 + T = TypeVar("T") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/benchmark/plot_graph_base_hash.py new/mmh3-5.2.1/benchmark/plot_graph_base_hash.py --- old/mmh3-5.2.0/benchmark/plot_graph_base_hash.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/benchmark/plot_graph_base_hash.py 2026-03-05 16:11:36.000000000 +0100 @@ -9,10 +9,11 @@ from typing import TypeVar import matplotlib.pyplot as plt -import mmh3 import pandas as pd import pyperf +import mmh3 + T = TypeVar("T") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/docs/api.md new/mmh3-5.2.1/docs/api.md --- old/mmh3-5.2.0/docs/api.md 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/docs/api.md 2026-03-05 16:11:36.000000000 +0100 @@ -32,9 +32,25 @@ architectures is required, such as when calculating hash footprints for web services. +```{caution} +[Buffer-accepting hash functions](#buffer-accepting-hash-functions) (except the +deprecated `hash_from_buffer`) accept positional-arguments only. Using keyword +arguments will raise a `TypeError`. +``` + +```{note} Support for no-GIL mode (officially introduced in Python 3.14) was added in -version 5.2.0. However, thread safety under the no-GIL variant has not been -fully tested. Please report any issues you encounter. +version 5.2.0. +- Basic hash functions are inherently thread-safe by design. +- Buffer-accepting hash functions are thread-safe, + **provided the input buffer is thread-safe**. +- Hasher classes are thread-safe, + again **assuming the input buffer is thread-safe**. + +However, thread safety under the no-GIL variant has not yet been +fully tested as of 5.2.0. If you encounter any issues, please report them via +the [issue tracker](https://github.com/hajimes/mmh3/issues). +``` ## Basic Hash Functions diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/pyproject.toml new/mmh3-5.2.1/pyproject.toml --- old/mmh3-5.2.0/pyproject.toml 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/pyproject.toml 2026-03-05 16:11:36.000000000 +0100 @@ -5,12 +5,12 @@ [project] name = "mmh3" -version = "5.2.0" +version = "5.2.1" description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions." readme = "README.md" license = {file = "LICENSE"} keywords = ["utility", "hash", "MurmurHash"] -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [ {name = "Hajime Senuma", email="[email protected]"} ] @@ -19,7 +19,6 @@ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -32,43 +31,58 @@ [project.optional-dependencies] test = [ - "pytest == 8.4.1", - "pytest-sugar == 1.0.0" + "pytest == 9.0.2", + "pytest-sugar == 1.1.1" ] lint = [ - "black == 25.1.0", - "clang-format == 20.1.8", - "isort == 6.0.1", - "pylint == 3.3.7" + "actionlint-py == 1.7.11.24", + "clang-format == 22.1.0", + "codespell == 2.4.1", + "pylint == 4.0.5", + "ruff == 0.15.4" ] type = [ - "mypy == 1.17.0" + "mypy == 1.19.1" ] docs = [ - "myst-parser == 4.0.1", - "shibuya == 2025.7.24", + "myst-parser == 5.0.0", + "shibuya == 2026.1.9", "sphinx == 8.2.3", "sphinx-copybutton == 0.5.2" ] benchmark = [ "pymmh3 == 0.0.5", - "pyperf == 2.9.0", - "xxhash == 3.5.0" + "pyperf == 2.10.0", + "xxhash == 3.6.0" ] plot = [ - "matplotlib == 3.10.3", - "pandas == 2.3.1" + "matplotlib == 3.10.8", + "pandas == 3.0.1" ] [project.urls] Homepage = "https://pypi.org/project/mmh3/" +Documentation = "https://mmh3.readthedocs.io/" Repository = "https://github.com/hajimes/mmh3" Changelog = "https://github.com/hajimes/mmh3/blob/master/CHANGELOG.md" "Bug Tracker" = "https://github.com/hajimes/mmh3/issues" -[tool.isort] -profile = "black" -src_paths = ["src/mmh3/__init__.pyi", "util", "tests", "benchmark", "docs"] +[tool.codespell] +# As of 2026-03-02, skip has an issue on super-linter +# https://github.com/super-linter/super-linter/issues/7466 +skip = "*/paper.bib,./build" +# Collet is a surname, Commun is an abbr for a journal name, +# fo is used in several test strings, and Ines is also a surname. +ignore-words-list = "Collet,Commun,fo,Ines" + +[tool.ruff] +src = ["src/mmh3/__init__.pyi", "util", "tests", "benchmark", "docs"] + +[tool.ruff.lint] +select = ["E", "W", "F", "I", "UP", "B", "SIM", "C4", "ISC", "NPY"] + +[tool.ruff.lint.isort] +known-first-party = ["mmh3"] [tool.setuptools] include-package-data = true @@ -92,7 +106,7 @@ # This setting can be found in the template file of super-linter 7.0.0. jobs = 0 # import-error: An error tricky to resolve, especially on super-linter. -# wrong-import-order: Respect isort's import order. +# wrong-import-order: Respect Ruff's import order. disable = [ "import-error", "wrong-import-order" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/src/mmh3/__init__.pyi new/mmh3-5.2.1/src/mmh3/__init__.pyi --- old/mmh3-5.2.0/src/mmh3/__init__.pyi 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/src/mmh3/__init__.pyi 2026-03-05 16:11:36.000000000 +0100 @@ -1,46 +1,36 @@ import sys -from typing import Any, Union, final +from typing import Any, final if sys.version_info >= (3, 12): from collections.abc import Buffer else: from _typeshed import ReadableBuffer as Buffer -def hash(key: Union[bytes, str], seed: int = 0, signed: Any = True) -> int: ... -def hash_from_buffer( - key: Union[Buffer, str], seed: int = 0, signed: Any = True -) -> int: ... +def hash(key: bytes | str, seed: int = 0, signed: Any = True) -> int: ... +def hash_from_buffer(key: Buffer | str, seed: int = 0, signed: Any = True) -> int: ... def hash64( - key: Union[bytes, str], seed: int = 0, x64arch: Any = True, signed: Any = True + key: bytes | str, seed: int = 0, x64arch: Any = True, signed: Any = True ) -> tuple[int, int]: ... def hash128( - key: Union[bytes, str], seed: int = 0, x64arch: Any = True, signed: Any = False + key: bytes | str, seed: int = 0, x64arch: Any = True, signed: Any = False ) -> int: ... -def hash_bytes(key: Union[bytes, str], seed: int = 0, x64arch: Any = True) -> bytes: ... -def mmh3_32_digest(key: Union[Buffer, str], seed: int = 0) -> bytes: ... -def mmh3_32_sintdigest(key: Union[Buffer, str], seed: int = 0) -> int: ... -def mmh3_32_uintdigest(key: Union[Buffer, str], seed: int = 0) -> int: ... -def mmh3_x64_128_digest(key: Union[Buffer, str], seed: int = 0) -> bytes: ... -def mmh3_x64_128_sintdigest(key: Union[Buffer, str], seed: int = 0) -> int: ... -def mmh3_x64_128_uintdigest(key: Union[Buffer, str], seed: int = 0) -> int: ... -def mmh3_x64_128_stupledigest( - key: Union[Buffer, str], seed: int = 0 -) -> tuple[int, int]: ... -def mmh3_x64_128_utupledigest( - key: Union[Buffer, str], seed: int = 0 -) -> tuple[int, int]: ... -def mmh3_x86_128_digest(key: Union[Buffer, str], seed: int = 0) -> bytes: ... -def mmh3_x86_128_sintdigest(key: Union[Buffer, str], seed: int = 0) -> int: ... -def mmh3_x86_128_uintdigest(key: Union[Buffer, str], seed: int = 0) -> int: ... -def mmh3_x86_128_stupledigest( - key: Union[Buffer, str], seed: int = 0 -) -> tuple[int, int]: ... -def mmh3_x86_128_utupledigest( - key: Union[Buffer, str], seed: int = 0 -) -> tuple[int, int]: ... +def hash_bytes(key: bytes | str, seed: int = 0, x64arch: Any = True) -> bytes: ... +def mmh3_32_digest(key: Buffer | str, seed: int = 0) -> bytes: ... +def mmh3_32_sintdigest(key: Buffer | str, seed: int = 0) -> int: ... +def mmh3_32_uintdigest(key: Buffer | str, seed: int = 0) -> int: ... +def mmh3_x64_128_digest(key: Buffer | str, seed: int = 0) -> bytes: ... +def mmh3_x64_128_sintdigest(key: Buffer | str, seed: int = 0) -> int: ... +def mmh3_x64_128_uintdigest(key: Buffer | str, seed: int = 0) -> int: ... +def mmh3_x64_128_stupledigest(key: Buffer | str, seed: int = 0) -> tuple[int, int]: ... +def mmh3_x64_128_utupledigest(key: Buffer | str, seed: int = 0) -> tuple[int, int]: ... +def mmh3_x86_128_digest(key: Buffer | str, seed: int = 0) -> bytes: ... +def mmh3_x86_128_sintdigest(key: Buffer | str, seed: int = 0) -> int: ... +def mmh3_x86_128_uintdigest(key: Buffer | str, seed: int = 0) -> int: ... +def mmh3_x86_128_stupledigest(key: Buffer | str, seed: int = 0) -> tuple[int, int]: ... +def mmh3_x86_128_utupledigest(key: Buffer | str, seed: int = 0) -> tuple[int, int]: ... class Hasher: - def __init__(self, data: Union[Buffer, None] = None, seed: int = 0) -> None: ... + def __init__(self, data: Buffer | None = None, seed: int = 0) -> None: ... def update(self, data: Buffer) -> None: ... def digest(self) -> bytes: ... def sintdigest(self) -> int: ... diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/src/mmh3/mmh3module.c new/mmh3-5.2.1/src/mmh3/mmh3module.c --- old/mmh3-5.2.0/src/mmh3/mmh3module.c 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/src/mmh3/mmh3module.c 2026-03-05 16:11:36.000000000 +0100 @@ -2328,7 +2328,7 @@ {"block_size", (getter)MMH3Hasher128x86_get_block_size, NULL, "int: Number of bytes of the internal block of this algorithm", NULL}, {"name", (getter)MMH3Hasher128x86_get_name, NULL, - "str: Te hash algorithm being used by this object", NULL}, + "str: The hash algorithm being used by this object", NULL}, {NULL} /* Sentinel */ }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/tests/test_invalid_inputs.py new/mmh3-5.2.1/tests/test_invalid_inputs.py --- old/mmh3-5.2.0/tests/test_invalid_inputs.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/tests/test_invalid_inputs.py 2026-03-05 16:11:36.000000000 +0100 @@ -2,9 +2,10 @@ # pylint: disable=no-value-for-parameter, too-many-function-args from typing import no_type_check -import mmh3 import pytest +import mmh3 + @no_type_check def test_hash_raises_typeerror() -> None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/tests/test_mmh3.py new/mmh3-5.2.1/tests/test_mmh3.py --- old/mmh3-5.2.0/tests/test_mmh3.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/tests/test_mmh3.py 2026-03-05 16:11:36.000000000 +0100 @@ -2,7 +2,6 @@ import sys import mmh3 - from helper import u32_to_s32 @@ -37,7 +36,7 @@ assert mmh3.hash("Hello, world!", 0x9747B28C) == u32_to_s32(0x24884CBA) - assert mmh3.hash("ππππππππ".encode("utf-8"), 0x9747B28C) == u32_to_s32(0xD58063C1) + assert mmh3.hash("ππππππππ".encode(), 0x9747B28C) == u32_to_s32(0xD58063C1) assert mmh3.hash("a" * 256, 0x9747B28C) == u32_to_s32(0x37405BDC) @@ -82,7 +81,7 @@ assert mmh3.hash("Hello, world!", 0x9747B28C, signed=False) == 0x24884CBA - assert mmh3.hash("ππππππππ".encode("utf-8"), 0x9747B28C, signed=False) == 0xD58063C1 + assert mmh3.hash("ππππππππ".encode(), 0x9747B28C, signed=False) == 0xD58063C1 assert mmh3.hash("a" * 256, 0x9747B28C, signed=False) == 0x37405BDC @@ -140,7 +139,7 @@ assert mmh3.hash("Hello, world!", 0x9747B28C) == u32_to_s32(0x24884CBA) - assert mmh3.hash("ππππππππ".encode("utf-8"), 0x9747B28C) == u32_to_s32(0xD58063C1) + assert mmh3.hash("ππππππππ".encode(), 0x9747B28C) == u32_to_s32(0xD58063C1) assert mmh3.hash("a" * 256, 0x9747B28C) == u32_to_s32(0x37405BDC) @@ -155,7 +154,7 @@ def test_hash_from_buffer() -> None: - mview = memoryview("foo".encode("utf8")) + mview = memoryview(b"foo") assert mmh3.hash_from_buffer(mview) == -156908512 assert mmh3.hash_from_buffer(mview, signed=False) == 4138058784 @@ -267,7 +266,7 @@ 4, "little" ) - assert mmh3.mmh3_32_digest("ππππππππ".encode("utf-8"), 0x9747B28C) == ( + assert mmh3.mmh3_32_digest("ππππππππ".encode(), 0x9747B28C) == ( 0xD58063C1 ).to_bytes(4, "little") @@ -329,9 +328,9 @@ 0x24884CBA ) - assert mmh3.mmh3_32_sintdigest( - "ππππππππ".encode("utf-8"), 0x9747B28C - ) == u32_to_s32(0xD58063C1) + assert mmh3.mmh3_32_sintdigest("ππππππππ".encode(), 0x9747B28C) == u32_to_s32( + 0xD58063C1 + ) assert mmh3.mmh3_32_sintdigest(b"a" * 256, 0x9747B28C) == u32_to_s32(0x37405BDC) @@ -379,7 +378,7 @@ assert mmh3.mmh3_32_uintdigest(b"Hello, world!", 0x9747B28C) == 0x24884CBA - assert mmh3.mmh3_32_uintdigest("ππππππππ".encode("utf-8"), 0x9747B28C) == 0xD58063C1 + assert mmh3.mmh3_32_uintdigest("ππππππππ".encode(), 0x9747B28C) == 0xD58063C1 assert mmh3.mmh3_32_uintdigest(b"a" * 256, 0x9747B28C) == 0x37405BDC diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/tests/test_mmh3_hasher.py new/mmh3-5.2.1/tests/test_mmh3_hasher.py --- old/mmh3-5.2.0/tests/test_mmh3_hasher.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/tests/test_mmh3_hasher.py 2026-03-05 16:11:36.000000000 +0100 @@ -1,6 +1,5 @@ # pylint: disable=missing-module-docstring,missing-function-docstring import mmh3 - from helper import u32_to_s32 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/tox.ini new/mmh3-5.2.1/tox.ini --- old/mmh3-5.2.0/tox.ini 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/tox.ini 2026-03-05 16:11:36.000000000 +0100 @@ -1,7 +1,7 @@ [tox] requires = tox>=4 -envlist = lint, type, py{39,310,311,312,313,314,314t} +envlist = lint, type, py{310,311,312,313,314,314t} [testenv] description = run unit tests @@ -19,13 +19,15 @@ commands_pre = uv pip install ".[lint]" commands = - black . - isort . + ruff format . + ruff check --fix . find ./src/mmh3 -name '*.[ch]' -exec clang-format -i {} + npx prettier --write . pylint --recursive=y . npx markdownlint --config .markdown-lint.yml \ --ignore-path .gitignore **/*.md + codespell + actionlint [testenv:type] description = run type checks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mmh3-5.2.0/util/refresh.py new/mmh3-5.2.1/util/refresh.py --- old/mmh3-5.2.0/util/refresh.py 2025-07-29 08:53:09.000000000 +0200 +++ new/mmh3-5.2.1/util/refresh.py 2026-03-05 16:11:36.000000000 +0100 @@ -132,15 +132,13 @@ """ subcode += "\n\n" - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ // To handle 64-bit data; see https://docs.python.org/3/c-api/arg.html #ifndef PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN #endif #include <Python.h> - """ - ) + """) return subcode @@ -156,13 +154,11 @@ """ subcode += "\n" - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #include <byteswap.h> #endif - """ - ) + """) return subcode @@ -171,7 +167,7 @@ """Use Py_ssize_t instead of int as the index type. Py_ssize_t is the type used by Python to represent the size of objects. - It is required to handle 64-bit data in Python extentions. + It is required to handle 64-bit data in Python extensions. See https://docs.python.org/3/c-api/intro.html#c.Py_ssize_t and @@ -214,15 +210,13 @@ for tr in transformations: subcode = subcode.replace(tr[0], tr[1]) - BYTE_SWAP_IF_BIG_ENDIAN = textwrap.dedent( - """\ + BYTE_SWAP_IF_BIG_ENDIAN = textwrap.dedent("""\ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) return bswap_\\1(p[i]); #else return p[i]; #endif - """ - ) + """) subcode = re.sub( r"getblock(.*?)(\s\(.*?\{\n).*?\}", @@ -266,8 +260,7 @@ """ # pylint: disable=invalid-name - BYTE_SWAP_IF_BIG_ENDIAN = textwrap.dedent( - """\ + BYTE_SWAP_IF_BIG_ENDIAN = textwrap.dedent("""\ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) ((uint32_t *)out)[0] = h2; ((uint32_t *)out)[1] = h1; @@ -276,8 +269,7 @@ #else \\1 #endif - """ - ) + """) subcode = re.sub( r"(\(\(uint32_t\*\)out\)\[0\] = h1;[\s\S]*\(\(uint32_t\*\)out\)\[3\] = h4;)", @@ -290,7 +282,7 @@ def expand_win_stdint_typedefs(subcode: str) -> str: - """Delineate int type defitions for the older versions of the VS compiler. + """Delineate int type definitions for the older versions of the VS compiler. Args: subcode (str): The code to be transformed. @@ -300,16 +292,14 @@ """ # pylint: disable=invalid-name - MSC_STDINT_TYPEDEFS = textwrap.dedent( - """\ + MSC_STDINT_TYPEDEFS = textwrap.dedent("""\ typedef signed __int8 int8_t; typedef signed __int32 int32_t; typedef signed __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; - """ - ) + """) return re.sub( r"typedef unsigned char(.*)uint64_t;", @@ -335,18 +325,15 @@ """ subcode += "\n\n" - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ //----------------------------------------------------------------------------- // Building blocks for multiply and rotate (MUR) operations. // Names are taken from Google Guava's implementation - """ - ) + """) subcode += "\n" - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ static FORCE_INLINE uint32_t mixK1(uint32_t k1) { @@ -359,11 +346,9 @@ return k1; } - """ - ) + """) - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ static FORCE_INLINE uint32_t mixH1(uint32_t h1, const uint32_t h2, const uint8_t shift, const uint32_t c1) { @@ -373,11 +358,9 @@ return h1; } - """ - ) + """) - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ static FORCE_INLINE uint64_t mixK_x64_128(uint64_t k1, const uint8_t shift, const uint64_t c1, const uint64_t c2) @@ -388,11 +371,9 @@ return k1; } - """ - ) + """) - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ static FORCE_INLINE uint64_t mixK1_x64_128(uint64_t k1) { @@ -405,11 +386,9 @@ return k1; } - """ - ) + """) - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ static FORCE_INLINE uint64_t mixK2_x64_128(uint64_t k2) { @@ -422,11 +401,9 @@ return k2; } - """ - ) + """) - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ static FORCE_INLINE uint64_t mixH_x64_128(uint64_t h1, uint64_t h2, const uint8_t shift, const uint32_t c) { @@ -436,11 +413,9 @@ return h1; } - """ - ) + """) - subcode += textwrap.dedent( - """\ + subcode += textwrap.dedent("""\ static FORCE_INLINE uint64_t mixK_x86_128(uint32_t k, const uint8_t shift, const uint32_t c1, const uint32_t c2) @@ -451,8 +426,7 @@ return k; } - """ - ) + """) return subcode @@ -468,15 +442,13 @@ """ hasher_digests = "\n\n" - hasher_digests += textwrap.dedent( - """\ + hasher_digests += textwrap.dedent("""\ static FORCE_INLINE void digest_x86_128_impl(uint32_t h1, uint32_t h2, uint32_t h3, uint32_t h4, const uint32_t k1, const uint32_t k2, const uint32_t k3, const uint32_t k4, const Py_ssize_t len, const char *out) { - """ - ) + """) hasher_digests += subcode + "\n" @@ -494,18 +466,15 @@ """ hasher_digests = "" - hasher_digests += textwrap.dedent( - """\ + hasher_digests += textwrap.dedent("""\ h1 ^= mixK_x86_128(k1, 15, c1, c2); h2 ^= mixK_x86_128(k2, 16, c2, c3); h3 ^= mixK_x86_128(k3, 17, c3, c4); h4 ^= mixK_x86_128(k4, 18, c4, c1); - """ - ) + """) hasher_digests += subcode + "\n" - hasher_digests += textwrap.dedent( - """\ + hasher_digests += textwrap.dedent("""\ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) ((uint32_t *)out)[0] = bswap_32(h1); ((uint32_t *)out)[1] = bswap_32(h2); @@ -517,8 +486,7 @@ ((uint32_t *)out)[2] = h3; ((uint32_t *)out)[3] = h4; #endif - """ - ) + """) hasher_digests += "\n}" return hasher_digests @@ -535,32 +503,25 @@ """ hasher_digests = "\n\n" - hasher_digests += textwrap.dedent( - """\ + hasher_digests += textwrap.dedent("""\ //----------------------------------------------------------------------------- // Finalization function - """ - ) + """) hasher_digests += "\n" - hasher_digests += textwrap.dedent( - """\ + hasher_digests += textwrap.dedent("""\ static FORCE_INLINE void digest_x64_128_impl(uint64_t h1, uint64_t h2, const uint64_t k1, const uint64_t k2, const Py_ssize_t len, const char *out) { - """ - ) - hasher_digests += textwrap.dedent( - """\ + """) + hasher_digests += textwrap.dedent("""\ h1 ^= mixK1_x64_128(k1); h2 ^= mixK2_x64_128(k2); - """ - ) + """) hasher_digests += subcode + "\n" - hasher_digests += textwrap.dedent( - """\ + hasher_digests += textwrap.dedent("""\ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) ((uint64_t *)out)[0] = bswap_64(h1); ((uint64_t *)out)[1] = bswap_64(h2); @@ -568,8 +529,7 @@ ((uint64_t *)out)[0] = h1; ((uint64_t *)out)[1] = h2; #endif - """ - ) + """) hasher_digests += "\n}" return hasher_digests @@ -593,8 +553,7 @@ "#define FORCE_INLINE inline __attribute__((always_inline))" ) - NON_WIN_FORCE_INLINE_REVISED = textwrap.dedent( - """\ + NON_WIN_FORCE_INLINE_REVISED = textwrap.dedent("""\ #if ((__GNUC__ > 4) || (__GNUC__ == 4 && GNUC_MINOR >= 4)) /* gcc version >= 4.4 4.1 = RHEL 5, 4.4 = RHEL 6. Don't inline for RHEL 5 gcc * which is 4.1*/ @@ -602,8 +561,7 @@ #else #define FORCE_INLINE #endif - """ - ) + """) return subcode.replace(NON_WIN_FORCE_INLINE_ORIGINAL, NON_WIN_FORCE_INLINE_REVISED) @@ -658,9 +616,9 @@ file_header_path = os.path.join(dir_path, FILE_HEADER_NAME) with ( - open(original_source_path, "r", encoding="utf-8") as source_file, - open(original_header_path, "r", encoding="utf-8") as header_file, - open(file_header_path, "r", encoding="utf-8") as file_header_file, + open(original_source_path, encoding="utf-8") as source_file, + open(original_header_path, encoding="utf-8") as header_file, + open(file_header_path, encoding="utf-8") as file_header_file, ): source = MMH3Source(source_file.read()) header = MMH3Header(header_file.read())
