diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 61fdb11..aa064ae 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -1,8 +1,6 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python - -name: Python package +name: Build, Test & Coverage +# Trigger the workflow on push or pull request events for the main branch on: push: branches: [ "main" ] @@ -10,32 +8,54 @@ on: branches: [ "main" ] jobs: - build: - + build-and-test: + name: Test (Python ${{ matrix.python-version }}) runs-on: ubuntu-latest + + # Test against multiple Python versions to ensure compatibility strategy: - fail-fast: false + fail-fast: false # If one version fails, let others finish (useful for debugging) matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: + # 1. Check out the repository code - uses: actions/checkout@v4 + + # 2. Set up the Python environment based on the matrix - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + cache: 'pip' # Cache pip to speed up subsequent runs + + # 3. Install the package and test dependencies - name: Install dependencies run: | python -m pip install --upgrade pip + # Install test dependencies (flake8, pytest, etc.) if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + # Install the package itself in editable mode + pip install -e . + # Or if you have optional deps: pip install -e ".[dataframes]" + + # 4. Linting: Check for syntax errors and coding style violations - name: Lint with flake8 run: | - # Ignore E501 (line too long), fail on all other errors - flake8 . --count --ignore=E501 --statistics - - name: Test with pytest and coverage + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings (except syntax errors) + # We ignore E501 (line length) as modern screens are wide + flake8 . --count --ignore=E501 --max-complexity=10 --statistics + + # 5. Testing: Run unit tests and generate coverage report + - name: Test with pytest run: | - pytest --cov=src/keyedstablehash --cov-report=term --cov-report=xml - - name: Upload coverage reports to Codecov + # Generates an XML report required by Codecov + pytest --cov=keyedstablehash --cov-report=xml --cov-report=term + + # 6. Upload Coverage: Send report to Codecov.io + - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.KEYEDSTABLEHASH_CODECOV_TOKEN }} diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..5c174d2 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Shlok T + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Readme.md b/Readme.md index 72d415c..1a4fe83 100644 --- a/Readme.md +++ b/Readme.md @@ -1,27 +1,23 @@
- Stable, secure, and reproducible hashing for Python objects and dataframes -
- ---- - # keyedstablehash **Deterministic, cryptographically secure hashing for complex Python objects and columnar data.** + +| | | +| --- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Testing | [](https://github.com/shloktech/keyedstablehash/actions/workflows/python-package.yml) [](https://codecov.io/github/shloktech/keyedstablehash) | +| Package | [](https://pypi.org/project/keyedstablehash/) [](https://pypi.org/project/keyedstablehash/) | +| Meta | [](https://github.com/shloktech/keyedstablehash/blob/main/LICENSE) | + | + +--- + + + `keyedstablehash` solves the problem of generating reproducible, secure hashes for arbitrary Python structures (dicts, lists, primitives) across different processes and machines. Think of it as `stablehash` meets `hashlib`, powered by the **SipHash-2-4** algorithm to prevent hash-flooding attacks. ## Why use `keyedstablehash`? diff --git a/docs/keyedstablehash_logo.png b/docs/keyedstablehash_logo.png new file mode 100644 index 0000000..65f6132 Binary files /dev/null and b/docs/keyedstablehash_logo.png differ