diff --git a/.github/workflows/create_wheel.yml b/.github/workflows/create_wheel.yml new file mode 100644 index 0000000..89da9bc --- /dev/null +++ b/.github/workflows/create_wheel.yml @@ -0,0 +1,58 @@ + +name: Publish package + +on: + push: + branches: [ master, working_example ] + tags: + - '*' + pull_request: + branches: + - '*' + + +jobs: + build-wheel: + runs-on: ubuntu-latest + + steps: + - name: Clone github repository + uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - run: pip install build + - run: python -m build + + - name: Upload wheels to GH artifacts + uses: actions/upload-artifact@v7 + with: + name: wheel + path: dist/ + + upload-wheel: + runs-on: ubuntu-latest + needs: [build-wheel] + + steps: + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - uses: actions/download-artifact@v8 + with: + pattern: wheel* + path: dist/ + + - name: Publish to test PyPI + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/') + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.TEST_PYPI_API_TOKEN }} + packages-dir: dist/ + skip-existing: true + repository-url: https://test.pypi.org/legacy/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..dab9c04 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,59 @@ + +stages: + - build + - publish + +variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + +# ------------------------ +# BUILD WHEEL +# ------------------------ +build-wheel: + stage: build + image: python:3.14 + + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + - if: '$CI_COMMIT_BRANCH =~ /^(master|workshop_starting_point|working_example)$/' + - if: '$CI_COMMIT_TAG' + + before_script: + - python --version + - pip install --upgrade pip + - pip install build + + script: + - python -m build + + artifacts: + name: wheel + paths: + - dist/ + expire_in: 1 week + + cache: + paths: + - .cache/pip + + +# ------------------------ +# PUBLISH TO TEST PYPI +# ------------------------ +upload-wheel: + stage: publish + image: python:3.14 + needs: ["build-wheel"] + + rules: + # Only run on tag pushes + - if: '$CI_COMMIT_TAG' + + before_script: + - python --version + - pip install --upgrade pip + - pip install twine + + script: + - twine upload dist/* --repository-url https://test.pypi.org/legacy/ -u __token__ -p "$TEST_PYPI_API_TOKEN" --skip-existing + diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..0e4d1b1 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include LICENSE +include README.md +include jdev2026_python_wheel_thomas_baudier/data/*.npz diff --git a/README.md b/README.md index 31d330e..b553f2f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # JDEV 2026 Python Workshop -This project is a **Python workshop** designed to teach students how to create and publish a Python package on PyPI. The package is an educational demo of RSA encryption and breaking. +This project is a **Python workshop** designed to teach students how to create and publish a Python package on PyPI. The package is an educational demo of RSA encryption and breaking. + +We will use venv and setuptools, the standard and universal tools integrated in Python to learn the basics. Later you can use your favorite tools (poetry, uv, pixi, etc.) to create your own package. In the same way, you can use your favorite tools (Gitlab, Github, etc.) to automatize the build and publish process, and PyPI or your own repository to publish your package. The only need you have to know is a little bit of Python and Git and a working Github account. The rest will be explained in the workshop. # RSA Encryption & Breaking Demo (Educational) diff --git a/jdev2026_python_wheel_thomas_baudier/__init__.py b/jdev2026_python_wheel_thomas_baudier/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jdev2026_python_wheel_thomas_baudier/data/__init__.py b/jdev2026_python_wheel_thomas_baudier/data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/primes.npz b/jdev2026_python_wheel_thomas_baudier/data/primes.npz similarity index 100% rename from primes.npz rename to jdev2026_python_wheel_thomas_baudier/data/primes.npz diff --git a/decrypt_rsa.py b/jdev2026_python_wheel_thomas_baudier/decrypt_rsa.py similarity index 85% rename from decrypt_rsa.py rename to jdev2026_python_wheel_thomas_baudier/decrypt_rsa.py index 5fd1a52..76fc936 100644 --- a/decrypt_rsa.py +++ b/jdev2026_python_wheel_thomas_baudier/decrypt_rsa.py @@ -1,6 +1,8 @@ +from importlib.resources import files + import numpy as np -from helpers import ( +from .helpers import ( break_rsa_with_primes, display_gui, rsa_decrypt, @@ -31,7 +33,8 @@ def run_decrypt_rsa(): show_text_gui(str(c), title="Encrypted message", label="Encrypted message:") # Load the list of primes and break RSA to find d - primes = np.load("primes.npz").tolist() + data_path = files("jdev2026_python_wheel_thomas_baudier.data") / "primes.npz" + primes = np.load(data_path).tolist() d = break_rsa_with_primes(n, e, primes) # Decrypting the message diff --git a/helpers.py b/jdev2026_python_wheel_thomas_baudier/helpers.py similarity index 100% rename from helpers.py rename to jdev2026_python_wheel_thomas_baudier/helpers.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e65f66b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,22 @@ + +[project] +name = "jdev2026-python-wheel-thomas-baudier" +version = "0.1.1" +description = "Demo package" +authors = [{name="Thomas"}] +readme = "README.md" +requires-python = ">=3.10" + +dependencies = [ + "numpy", +] + +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.package-data] +"jdev2026_python_wheel_thomas_baudier" = ["data/*.npz"] + +[project.scripts] +decrypt-tool = "jdev2026_python_wheel_thomas_baudier.decrypt_rsa:run_decrypt_rsa"