From f0c60932a869a6dccb148dd9a5b7c0c18c48e5f2 Mon Sep 17 00:00:00 2001 From: Adrian Date: Wed, 23 Oct 2024 15:13:28 +0200 Subject: [PATCH] Get rid of setuptools and use hatchling instead (#492) * Get rid of setuptools and use hatchling instead * Update minimum Python version check in Makefile * Update GitHub actions * Stop using deprecated set-output in GHA * Fix docker builds + use uv --- .github/workflows/migration-sql-comment.yml | 12 +++--- .github/workflows/migration-sql.yml | 15 ++++--- Dockerfile | 7 ++- MANIFEST.in | 6 --- Makefile | 9 ++-- package.json | 2 +- pyproject.toml | 47 +++++++++++++++++++++ requirements.dev.in | 1 + requirements.dev.txt | 5 +++ setup.cfg | 16 ------- setup.py | 26 ------------ 11 files changed, 78 insertions(+), 68 deletions(-) delete mode 100644 MANIFEST.in create mode 100644 pyproject.toml delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.github/workflows/migration-sql-comment.yml b/.github/workflows/migration-sql-comment.yml index ed65f72d0..d52ddc9b8 100644 --- a/.github/workflows/migration-sql-comment.yml +++ b/.github/workflows/migration-sql-comment.yml @@ -15,7 +15,7 @@ jobs: # hopefully this can be improved at some point; see this issue for details: # https://github.com/actions/download-artifact/issues/60 - name: Download artifact - uses: actions/github-script@v3.1.0 + uses: actions/github-script@v7 with: script: | const artifacts = await github.actions.listWorkflowRunArtifacts({ @@ -41,16 +41,16 @@ jobs: - name: Get data from artifact id: get-data run: | - echo ::set-output name=pull_id::$(> $GITHUB_OUTPUT if [ -f /tmp/migration-sql-data/upgrade.sql ]; then sql_command=$(> $GITHUB_OUTPUT fi fi - name: Find previous comment - uses: peter-evans/find-comment@v1 + uses: peter-evans/find-comment@v3 id: find-comment with: issue-number: ${{ steps.get-data.outputs.pull_id }} @@ -58,7 +58,7 @@ jobs: comment-author: github-actions[bot] - name: Create comment - uses: peter-evans/create-or-update-comment@v1 + uses: peter-evans/create-or-update-comment@v4 if: steps.get-data.outputs.sql with: issue-number: ${{ steps.get-data.outputs.pull_id }} @@ -75,7 +75,7 @@ jobs: version, i.e. any new column needs to have a `server_default` or be nullable. - name: Delete comment - uses: peter-evans/create-or-update-comment@v1 + uses: peter-evans/create-or-update-comment@v4 if: steps.find-comment.outputs.comment-id && !steps.get-data.outputs.sql with: issue-number: ${{ steps.get-data.outputs.pull_id }} diff --git a/.github/workflows/migration-sql.yml b/.github/workflows/migration-sql.yml index 66d01807e..630cffb13 100644 --- a/.github/workflows/migration-sql.yml +++ b/.github/workflows/migration-sql.yml @@ -9,24 +9,25 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: '3.12' - name: Get list of created migrations id: get-changed-files - uses: ThiefMaster/changed-files-action@json-output + uses: umani/changed-files@v4.2.0 with: repo-token: ${{ github.token }} + result-encoding: json pattern: '^newdle/migrations/versions/.+\.py$' - name: Check if any migrations changed id: migrations-changed run: | - echo ::set-output name=changed::${{ steps.get-changed-files.outputs.files_created != '[]' || steps.get-changed-files.outputs.files_updated != '[]' || steps.get-changed-files.outputs.files_deleted != '[]' }} + echo changed=${{ steps.get-changed-files.outputs.files_created != '[]' || steps.get-changed-files.outputs.files_updated != '[]' || steps.get-changed-files.outputs.files_deleted != '[]' }} >> $GITHUB_OUTPUT - name: Setup venv and config file if: steps.migrations-changed.outputs.changed == 'true' @@ -53,12 +54,12 @@ jobs: - name: Print changed migrations if: steps.migrations-changed.outputs.changed == 'true' run: | - first_migration=$(jq -r '.[0] // empty' ~/files_created.json) - latest_migration=$(jq -r '.[-1] // empty' ~/files_created.json) + first_migration=$(echo '${{ steps.get-changed-files.outputs.files_created }}' | jq -r '.[0] // empty') + latest_migration=$(echo '${{ steps.get-changed-files.outputs.files_created }}' | jq -r '.[-1] // empty') ./ci/print_revision_sql.sh $first_migration $latest_migration > /tmp/migration-sql-data/upgrade.sql - name: Create artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: migration-sql-data path: /tmp/migration-sql-data diff --git a/Dockerfile b/Dockerfile index d1c10cd93..972da2d47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,13 +22,16 @@ RUN set -ex && \ RUN apt-get update && apt-get install -y libpcre3 libpcre3-dev RUN pip install uwsgi +ENV UV_NO_CACHE=1 +ENV UV_SYSTEM_PYTHON=1 +COPY --from=ghcr.io/astral-sh/uv /uv /bin/uv COPY --from=builder /build/dist/newdle*.whl /tmp/ -RUN pip install $(echo /tmp/newdle*.whl)[exchange,cern] +RUN uv pip install $(echo /tmp/newdle*.whl)[exchange,cern] RUN find /usr/local/lib/python3.12/site-packages/newdle/client/build/ -type f -exec gzip -k {} + ADD docker/run.sh docker/uwsgi.ini / # install some useful tools for debugging etc. -RUN pip install ipython flask-shell-ipython httpie +RUN uv pip install ipython flask-shell-ipython httpie USER newdle diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index f722b5c05..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -graft newdle/client/build -graft newdle/migrations -graft newdle/templates -include newdle/newdle.cfg.example - -global-exclude *.py[co] __pycache__ .keep diff --git a/Makefile b/Makefile index 3f563b53c..0ac9928c3 100644 --- a/Makefile +++ b/Makefile @@ -25,12 +25,12 @@ ifeq (, $(shell which ${PYTHON} 2> /dev/null)) @printf "\033[38;5;220mFATAL\033[0m \033[38;5;196mPython not found (${PYTHON})\033[0m\n" @exit 1 endif -ifneq (True, $(shell ${PYTHON} -c 'import sys; print(sys.version_info[:2] >= (3, 7))')) - @printf "\033[38;5;220mFATAL\033[0m \033[38;5;196mYou need at least Python 3.7\033[0m\n" +ifneq (True, $(shell ${PYTHON} -c 'import sys; print(sys.version_info[:2] >= (3, 12))')) + @printf "\033[38;5;220mFATAL\033[0m \033[38;5;196mYou need at least Python 3.12\033[0m\n" @exit 1 endif @${PYTHON} -m venv --prompt newdle .venv - @${PIP} install -q -U pip setuptools + @${PIP} install -q -U pip ${CONFIG}: | ${CONFIG}.example @printf "\033[38;5;154mSETUP\033[0m \033[38;5;105mCreating config [\033[38;5;147m${CONFIG}\033[38;5;105m]\033[0m\n" @@ -141,7 +141,8 @@ build: i18n @printf " \033[38;5;154mBUILD\033[0m \033[38;5;176mBuilding production package\033[0m\n" @rm -rf newdle/client/build build @source ${VENV}/bin/activate && cd newdle/client && npm run build - @python setup.py bdist_wheel -q + @source ${VENV}/bin/activate && python -m pip install uv build + @source ${VENV}/bin/activate && python -m build --installer uv -o dist .PHONY: docker diff --git a/package.json b/package.json index 8fb005ea8..7f10169ec 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "scripts": { "prettier": "prettier --write 'newdle/client/src/**/*.{js,jsx,json,scss,css}'", "prettier:check": "prettier --check 'newdle/client/src/**/*.{js,jsx,json,scss,css}'", - "ruff-format": "ruff format setup.py conftest.py ci/ newdle/ tests/", + "ruff-format": "ruff format conftest.py ci/ newdle/ tests/", "ruff-format:check": "npm run ruff-format -- --diff --check", "eslint": "cd newdle/client && npx eslint --fix --max-warnings 0 src/", "eslint:specific": "cd newdle/client && npx eslint --fix --max-warnings 0", diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..b54b755eb --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,47 @@ +[project] +name = 'newdle' +version = '1.0-dev' +dynamic = ['dependencies', 'optional-dependencies'] +description = 'Open Source Collaborative enterprise meeting scheduling tool.' +readme = 'README.md' +license = 'MIT' +authors = [{ name = 'Indico Team', email = 'indico-team@cern.ch' }] +classifiers = [ + 'Environment :: Web Environment', + 'Framework :: Flask', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3.12', +] +requires-python = '~=3.12' + +[project.urls] +Releases = 'https://github.com/indico/newdle/releases' +Issues = 'https://github.com/indico/newdle/issues' +GitHub = 'https://github.com/indico/newdle' + +[build-system] +requires = ['hatchling==1.25.0', 'hatch-requirements-txt==0.4.1'] +build-backend = 'hatchling.build' + +[tool.hatch.metadata.hooks.requirements_txt] +files = ['requirements.txt'] + +[tool.hatch.metadata.hooks.requirements_txt.optional-dependencies] +dev = ['requirements.dev.txt'] +cern = ['requirements.cern.txt'] +exchange = ['requirements.exchange.txt'] + +[tool.hatch.build] +packages = ['newdle'] +exclude = [ + '.keep', + # exclude original client sources (they are all included in source maps anyway) + 'newdle/client/', + # no need for tests outside development + 'tests/', +] +artifacts = ['newdle/client/build/'] + +[tool.uv] +# uv does not know about dynamic metadata so `pip install -e .` should always reinstall +reinstall-package = ['newdle'] diff --git a/requirements.dev.in b/requirements.dev.in index 32ce1db71..346229187 100644 --- a/requirements.dev.in +++ b/requirements.dev.in @@ -1,4 +1,5 @@ -c requirements.txt +build flask-shell-ipython ipython pytest diff --git a/requirements.dev.txt b/requirements.dev.txt index 15970a71e..6d5c502cd 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -6,6 +6,8 @@ blinker==1.8.2 # via # -c requirements.txt # flask +build==1.2.2.post1 + # via -r requirements.dev.in click==8.1.7 # via # -c requirements.txt @@ -49,6 +51,7 @@ matplotlib-inline==0.1.7 packaging==24.0 # via # -c requirements.txt + # build # pytest parso==0.8.4 # via jedi @@ -64,6 +67,8 @@ pure-eval==0.2.2 # via stack-data pygments==2.18.0 # via ipython +pyproject-hooks==1.2.0 + # via build pytest==8.2.0 # via # -r requirements.dev.in diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 42d1d55ac..000000000 --- a/setup.cfg +++ /dev/null @@ -1,16 +0,0 @@ -[metadata] -name = newdle -version = 1.0-dev -license = MIT -description = Open Source Collaborative enterprise meeting scheduling tool. -long_description = file: README.md -long_description_content_type = text/markdown; charset=UTF-8; variant=CommonMark -author = Indico Team -author_email = indico-team@cern.ch -url = https://github.com/indico/newdle - -[options] -packages = find: -zip_safe = false -include_package_data = true -python_requires = ~=3.12 diff --git a/setup.py b/setup.py deleted file mode 100644 index 3db13c566..000000000 --- a/setup.py +++ /dev/null @@ -1,26 +0,0 @@ -from pathlib import Path - -from setuptools import setup - - -def read_requirements_file(path: Path): - with path.open() as f: - return [ - dep - for d in f.readlines() - if (dep := d.strip()) and not (dep.startswith(('-', '#')) or '://' in dep) - ] - - -def get_requirements(fname: str): - return read_requirements_file(Path(__file__).parent / fname) - - -setup( - install_requires=get_requirements('requirements.txt'), - extras_require={ - 'dev': get_requirements('requirements.dev.txt'), - 'exchange': get_requirements('requirements.exchange.txt'), - 'cern': get_requirements('requirements.cern.txt'), - }, -)