Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions .github/workflows/pypi-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
name: PyPI Release

on:
release:
types: [published]
workflow_dispatch: # Allow manual triggering

permissions:
contents: read
actions: read
id-token: write

jobs:
build-wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Set up Docker Buildx (Linux only)
if: runner.os == 'Linux'
uses: docker/setup-buildx-action@v3

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install cibuildwheel

- name: Sync Python version
run: python scripts/sync_python_version.py


- name: Verify Docker (Linux only)
if: runner.os == 'Linux'
run: |
docker --version
docker info
echo "Docker is ready for cibuildwheel"

- name: Build wheels
run: python -m cibuildwheel libCacheSim-python --output-dir wheelhouse

- name: Upload wheels as artifacts
uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.os }}
path: wheelhouse/*.whl

build-sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build

- name: Sync Python version
run: python scripts/sync_version.py

- name: Build source distribution
run: python -m build --sdist . --outdir dist/

- name: Upload sdist as artifact
uses: actions/upload-artifact@v4
with:
name: sdist
path: dist/*.tar.gz

publish-to-pypi:
name: Publish to PyPI
needs: [build-wheels, build-sdist]
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'
environment:
name: pypi
url: https://pypi.org/p/libcachesim
permissions:
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing

steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist/

- name: Flatten artifacts directory
run: |
mkdir -p final-dist
find dist/ -name "*.whl" -exec cp {} final-dist/ \;
find dist/ -name "*.tar.gz" -exec cp {} final-dist/ \;
ls -la final-dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: final-dist/
skip-existing: true

publish-to-test-pypi:
name: Publish to TestPyPI
needs: [build-wheels, build-sdist]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
environment:
name: testpypi
url: https://test.pypi.org/p/libcachesim
permissions:
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing

steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist/

- name: Flatten artifacts directory
run: |
mkdir -p final-dist
find dist/ -name "*.whl" -exec cp {} final-dist/ \;
find dist/ -name "*.tar.gz" -exec cp {} final-dist/ \;
ls -la final-dist/

- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
packages-dir: final-dist/
skip-existing: true
7 changes: 1 addition & 6 deletions examples/plugin_cache/s3fifo.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,7 @@ def cache_remove_hook(cache, obj_id):
cache.cache_remove(obj_id)

def cache_free_hook(cache):
cache.small_fifo.clear()
cache.small_freq.clear()
cache.ghost_fifo.clear()
cache.ghost_freq.clear()
cache.main_fifo.clear()
cache.main_freq.clear()
pass
Comment on lines 173 to +174
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The previous implementation of cache_free_hook was buggy as it tried to access non-existent attributes. However, replacing it with pass completely removes the resource cleanup logic. This could lead to a memory leak if PluginCache instances are created and destroyed repeatedly in a long-running process, as the StandaloneS3FIFO object and its contents might not be garbage collected properly.

It would be safer to provide a correct implementation that clears the data structures held by the StandaloneS3FIFO instance.

def cache_free_hook(cache):
    cache.small_set.clear()
    cache.main_set.clear()
    cache.ghost_set.clear()
    cache.freq.clear()


cache = PluginCache(
cache_size=1024,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ build-backend = "scikit_build_core.build"

[project]
name = "libcachesim"
version = "0.3.2"
version = "0.3.3"
description="Python bindings for libCacheSim"
readme = "README.md"
requires-python = ">=3.9"
Expand Down
4 changes: 4 additions & 0 deletions scripts/sync_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def update_pyproject_toml(version):
if current_version == version:
print(f"Python binding version already up to date: {version}")
return False
# If the pyproject version is newer than version.txt, it is allowed.
if current_version > version:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Direct string comparison of version numbers is unreliable. For example, '0.3.10' > '0.3.2' evaluates to False. This can lead to incorrect behavior where a newer version in version.txt is ignored.

You should use a proper version parsing library like packaging to ensure correct comparison. You will need to add from packaging.version import parse as parse_version to the imports at the top of the file.

Suggested change
if current_version > version:
if parse_version(current_version) > parse_version(version):

print(f"Warning: pyproject version {current_version} is newer than version.txt {version}, skipping update")
return False
# replace the version line with the new version
pyproject_data = re.sub(r"version = \"(dev|[0-9]+\.[0-9]+\.[0-9]+)\"", f'version = "{version}"', pyproject_data)

Expand Down