diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 1152ab5..21321b0 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -5,34 +5,47 @@ on: pull_request: release: types: - - published + - published jobs: - test: + lint: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install black isort flake8 bandit[toml] + - run: python -m black . --check + - run: python -m isort . --check-only + - run: python -m flake8 . + - run: python -m bandit . --recursive -c pyproject.toml + test: + needs: lint strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install setuptools wheel cython - - name: Build + - name: Install run: | - python setup.py build_ext --inplace + python -m pip install . - name: Run tests run: | - python test.py + cd tests + python -m unittest discover build-wheels: if: github.event_name == 'release' && github.event.action == 'published' @@ -44,11 +57,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/setup-python@v5 with: python-version: 3.8 - name: Install dependencies @@ -68,20 +80,19 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true - - name: Set up Python 3.8 - uses: actions/setup-python@v2 + - uses: actions/setup-python@v5 with: python-version: 3.8 - name: Install dependencies run: | - python -m pip install setuptools cython + python -m pip install build - name: Build dists run: | - python setup.py sdist - - uses: actions/upload-artifact@v2 + python -m build --sdist + - uses: actions/upload-artifact@v3 with: path: dist/*.tar.gz @@ -94,12 +105,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v2 - with: - name: artifact - path: dist + - uses: actions/download-artifact@v2 + with: + name: artifact + path: dist - - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.pypi_password }} + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.pypi_password }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 404e81e..61a144c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,35 +1,67 @@ repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 - hooks: - - id: check-json - - id: check-toml - - id: check-yaml - - id: check-case-conflict - - id: check-added-large-files - - id: debug-statements - - id: end-of-file-fixer - - id: mixed-line-ending - args: ["--fix=no"] - - id: requirements-txt-fixer - - id: trailing-whitespace - args: ["--markdown-linebreak-ext=md"] - - repo: https://github.com/asottile/pyupgrade - rev: 'v2.29.1' - hooks: - - id: pyupgrade - args: ["--py36-plus"] - - repo: https://github.com/psf/black - rev: '21.11b1' - hooks: - - id: black - language_version: python3 # Should be a command that runs python3.6+ - - repo: https://github.com/PyCQA/isort - rev: '5.10.1' - hooks: - - id: isort - language_version: python3 - - repo: https://gitlab.com/pycqa/flake8 - rev: 4.0.1 - hooks: - - id: flake8 +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-json + - id: check-toml + - id: check-yaml + - id: check-case-conflict + - id: check-added-large-files + - id: debug-statements + - id: end-of-file-fixer + - id: mixed-line-ending + args: [--fix=no] + - id: requirements-txt-fixer + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] +- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.13.0 + hooks: + - id: pretty-format-yaml + args: [--autofix] +- repo: https://github.com/tox-dev/pyproject-fmt + rev: 1.7.0 + hooks: + - id: pyproject-fmt +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v18.1.3 + hooks: + - id: clang-format +- repo: https://github.com/asottile/pyupgrade + rev: v3.15.2 + hooks: + - id: pyupgrade + args: [--py37-plus] +- repo: https://github.com/MarcoGorelli/cython-lint + rev: v0.16.2 + hooks: + - id: cython-lint + - id: double-quote-cython-strings +- repo: https://github.com/psf/black-pre-commit-mirror + rev: 24.4.0 + hooks: + - id: black +- repo: https://github.com/PyCQA/isort + rev: 5.13.2 + hooks: + - id: isort +- repo: https://github.com/PyCQA/bandit + rev: 1.7.8 + hooks: + - id: bandit + args: [-c, pyproject.toml] + additional_dependencies: ['.[toml]'] +- repo: https://github.com/pycqa/flake8 + rev: 7.0.0 + hooks: + - id: flake8 + additional_dependencies: + - flake8-annotations + - flake8-bugbear + - flake8-eradicate + - flake8-mutable + - flake8-simplify +- repo: https://github.com/Yelp/detect-secrets + rev: v1.4.0 + hooks: + - id: detect-secrets diff --git a/metrohash.pyx b/metrohash.pyx index 86cb336..aea0845 100644 --- a/metrohash.pyx +++ b/metrohash.pyx @@ -1,10 +1,7 @@ # distutils: language=c++ -import sys - from cython.operator cimport dereference as deref from libc.stdint cimport uint8_t, uint64_t -from libcpp cimport bool cdef extern from "metrohash.h" nogil: @@ -29,13 +26,6 @@ cdef extern from "metrohash.h" nogil: __all__ = ["MetroHash128", "MetroHash64", "metrohash128", "metrohash64"] -if sys.version_info < (3, ): - def bytes2hex(b): - return b.encode("hex") -else: - def bytes2hex(b): - return b.hex() - cpdef bytes metrohash64(bytes data, uint64_t seed=0ULL): cdef bytearray out = bytearray(8) @@ -91,7 +81,7 @@ cdef class MetroHash64(object): return bytes(_hash) def hexdigest(self): - return bytes2hex(self.digest()) + return self.digest().hex() def copy(self): return MetroHash64(self) @@ -139,7 +129,7 @@ cdef class MetroHash128(object): return bytes(_hash) def hexdigest(self): - return bytes2hex(self.digest()) + return self.digest().hex() def copy(self): return MetroHash128(self) diff --git a/pyproject.toml b/pyproject.toml index 010de90..7974011 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,28 @@ [build-system] -requires = ["setuptools", "wheel", "Cython"] +requires = [ + "Cython", + "setuptools", + "wheel", +] [tool.black] line-length = 120 +[tool.ruff] +line-length = 120 + [tool.isort] profile = "black" -src_paths = ["."] line_length = 120 + +[tool.mypy] +allow_redefinition = true +warn_unused_configs = true +warn_unused_ignores = true + +[tool.bandit] +skips = ["B101"] + +[tool.cython-lint] +max-line-length = 120 +ignore = ["W191"] diff --git a/setup.py b/setup.py index 10cc2fa..483dd16 100644 --- a/setup.py +++ b/setup.py @@ -11,13 +11,19 @@ INT_SOURCES = ["metrohash.pyx"] +machine = platform.machine().lower() +x86 = ("x86_64", "amd64", "i386", "x86", "i686") + if sys.platform == "win32": - cflags = ["/O2", "/arch:AVX2"] + if machine in x86: + cflags = ["/O2", "/arch:AVX"] + else: + cflags = ["/O2"] else: - if platform.machine().lower() in ("x86_64", "amd64"): - cflags = ["-O3", "-msse4.2"] + if machine in x86: + cflags = ["-O2", "-mavx"] else: - cflags = ["-O3", "-march=native"] + cflags = ["-O2"] extensions = [ Extension( @@ -54,7 +60,6 @@ "Topic :: Utilities", ], ext_modules=cythonize(extensions), - python_requires=">=3.6", - use_2to3=False, + python_requires=">=3.7", zip_safe=False, ) diff --git a/test.py b/tests/test_metrohash.py similarity index 85% rename from test.py rename to tests/test_metrohash.py index 5e5f3ce..90e161f 100644 --- a/test.py +++ b/tests/test_metrohash.py @@ -1,10 +1,9 @@ import unittest -from metrohash import MetroHash64, MetroHash128, bytes2hex, metrohash64, metrohash128 +from metrohash import MetroHash64, MetroHash128, metrohash64, metrohash128 class TestMetrohash(unittest.TestCase): - test_key_63 = b"012345678901234567890123456789012345678901234567890123456789012" def test_metrohash64(self): @@ -15,7 +14,7 @@ def test_metrohash64(self): h = cls(seed) h.update(input) - self.assertEqual(truth, bytes2hex(h.digest())) + self.assertEqual(truth, h.digest().hex()) self.assertEqual(truth, h.hexdigest()) def test_metrohash64_update(self): @@ -28,7 +27,7 @@ def test_metrohash64_update(self): h.digest() h.update(input[i : i + 4]) - self.assertEqual(truth, bytes2hex(h.digest())) + self.assertEqual(truth, h.digest().hex()) self.assertEqual(truth, h.hexdigest()) def test_metrohash64_copy(self): @@ -41,7 +40,7 @@ def test_metrohash64_copy(self): h.update(input[i : i + 4]) h = h.copy() - self.assertEqual(truth, bytes2hex(h.digest())) + self.assertEqual(truth, h.digest().hex()) self.assertEqual(truth, h.hexdigest()) def test_metrohash64_convenience(self): @@ -49,7 +48,7 @@ def test_metrohash64_convenience(self): (metrohash64, self.test_key_63, 0, "6b753dae06704bad"), (metrohash64, self.test_key_63, 1, "3b0d481cf4b9b8df"), ]: - result = bytes2hex(func(input, seed)) + result = func(input, seed).hex() self.assertEqual(truth, result) def test_metrohash128(self): @@ -60,7 +59,7 @@ def test_metrohash128(self): h = cls(seed) h.update(input) - self.assertEqual(truth, bytes2hex(h.digest())) + self.assertEqual(truth, h.digest().hex()) self.assertEqual(truth, h.hexdigest()) def test_metrohash128_update(self): @@ -73,7 +72,7 @@ def test_metrohash128_update(self): h.digest() h.update(input[i : i + 4]) - self.assertEqual(truth, bytes2hex(h.digest())) + self.assertEqual(truth, h.digest().hex()) self.assertEqual(truth, h.hexdigest()) def test_metrohash128_copy(self): @@ -86,7 +85,7 @@ def test_metrohash128_copy(self): h.update(input[i : i + 4]) h = h.copy() - self.assertEqual(truth, bytes2hex(h.digest())) + self.assertEqual(truth, h.digest().hex()) self.assertEqual(truth, h.hexdigest()) def test_metrohash128_convenience(self): @@ -94,7 +93,7 @@ def test_metrohash128_convenience(self): (metrohash128, self.test_key_63, 0, "c77ce2bfa4ed9f9b0548b2ac5074a297"), (metrohash128, self.test_key_63, 1, "45a3cdb838199d7fbdd68d867a14ecef"), ]: - result = bytes2hex(func(input, seed)) + result = func(input, seed).hex() self.assertEqual(truth, result) diff --git a/tox.ini b/tox.ini index 09ade95..0361504 100644 --- a/tox.ini +++ b/tox.ini @@ -1,3 +1,4 @@ [flake8] max-line-length = 120 -select = E7, E9, W2, W6, F +select = B, E7, E9, W2, W3, W6, F +ignore = E704