build: Update pyproject.toml to follow standards

This now follows [PEP 517](https://peps.python.org/pep-0517/) and [PEP 621](https://peps.python.org/pep-0621/) to define the metadata of the project, as well as its dependencies.

As a result, the toolchain now uses [uv](https://github.com/astral-sh/uv) instead of [poetry](https://python-poetry.org/).

The build-backend has been switched to [Hatch](https://hatch.pypa.io/latest/).

Fixes #677
This commit is contained in:
Alexis Métaireau 2024-12-19 11:52:13 +01:00
parent d868699bab
commit 42a9b6f2f7
No known key found for this signature in database
GPG key ID: C65C7A89A8FFC56E
15 changed files with 1334 additions and 1647 deletions

View file

@ -46,11 +46,10 @@ methods](https://python-poetry.org/docs/#installation))_
```sh ```sh
pipx ensurepath pipx ensurepath
pipx install poetry pipx install uv
pipx inject poetry poetry-plugin-export
``` ```
After this, restart the terminal window, for the `poetry` command to be in your After this, restart the terminal window, for the `uv` command to be in your
`$PATH`. `$PATH`.
@ -60,44 +59,39 @@ Clone this repository:
git clone https://github.com/freedomofpress/dangerzone/ git clone https://github.com/freedomofpress/dangerzone/
``` ```
Change to the `dangerzone` folder, and install the poetry dependencies: Change to the `dangerzone` folder, and install the dependencies:
> **Note**: due to an issue with [poetry](https://github.com/python-poetry/poetry/issues/1917), if it prompts for your keyring, disable the keyring with `keyring --disable` and run the command again.
``` ```
cd dangerzone cd dangerzone
poetry install uv sync
``` ```
Build the latest container: Build the latest container:
```sh ```sh
python3 ./install/common/build-image.py uv run ./install/common/build-image.py
``` ```
Download the OCR language data: Download the OCR language data:
```sh ```sh
python3 ./install/common/download-tessdata.py uv run ./install/common/download-tessdata.py
``` ```
Run from source tree: Run from source tree:
```sh ```sh
# start a shell in the virtual environment
poetry shell
# run the CLI # run the CLI
./dev_scripts/dangerzone-cli --help uv run ./dev_scripts/dangerzone-cli --help
# run the GUI # run the GUI
./dev_scripts/dangerzone uv run ./dev_scripts/dangerzone
``` ```
Create a .deb: Create a .deb:
```sh ```sh
./install/linux/build-deb.py uv run ./install/linux/build-deb.py
``` ```
## Fedora ## Fedora
@ -105,7 +99,7 @@ Create a .deb:
Install dependencies: Install dependencies:
```sh ```sh
sudo dnf install -y rpm-build podman python3 python3-devel python3-poetry-core \ sudo dnf install -y rpm-build podman python3 python3-devel python3-uv \
pipx qt6-qtbase-gui pipx qt6-qtbase-gui
``` ```

14
QA.md
View file

@ -16,14 +16,14 @@ It can run the tasks for you, pausing when it needs manual intervention.
You can run it with a command like: You can run it with a command like:
```bash ```bash
poetry run ./dev_scripts/qa.py {distro}-{version} uv run ./dev_scripts/qa.py {distro}-{version}
``` ```
### The checklist ### The checklist
- [ ] Create a test build in Windows and make sure it works: - [ ] Create a test build in Windows and make sure it works:
- [ ] Check if the suggested Python version is still supported. - [ ] Check if the suggested Python version is still supported.
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with uv.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -32,7 +32,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in macOS (Intel CPU) and make sure it works: - [ ] Create a test build in macOS (Intel CPU) and make sure it works:
- [ ] Check if the suggested Python version is still supported. - [ ] Check if the suggested Python version is still supported.
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with uv.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -41,7 +41,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in macOS (M1/2 CPU) and make sure it works: - [ ] Create a test build in macOS (M1/2 CPU) and make sure it works:
- [ ] Check if the suggested Python version is still supported. - [ ] Check if the suggested Python version is still supported.
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with uv.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -50,7 +50,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in the most recent Ubuntu LTS platform (Ubuntu 24.04 - [ ] Create a test build in the most recent Ubuntu LTS platform (Ubuntu 24.04
as of writing this) and make sure it works: as of writing this) and make sure it works:
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with uv.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -59,7 +59,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in the most recent Fedora platform (Fedora 41 as of - [ ] Create a test build in the most recent Fedora platform (Fedora 41 as of
writing this) and make sure it works: writing this) and make sure it works:
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with uv.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -68,7 +68,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in the most recent Qubes Fedora template (Fedora 40 as - [ ] Create a test build in the most recent Qubes Fedora template (Fedora 40 as
of writing this) and make sure it works: of writing this) and make sure it works:
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with uv.
- [ ] Run the Dangerzone tests. - [ ] Run the Dangerzone tests.
- [ ] Create a Qubes .rpm package and install it system-wide. - [ ] Create a Qubes .rpm package and install it system-wide.
- [ ] Ensure that the Dangerzone application appears in the "Applications" - [ ] Ensure that the Dangerzone application appears in the "Applications"

View file

@ -7,9 +7,9 @@ This section documents how we currently release Dangerzone for the different dis
Here is a list of tasks that should be done before issuing the release: Here is a list of tasks that should be done before issuing the release:
- [ ] Create a new issue named **QA and Release for version \<VERSION\>**, to track the general progress. - [ ] Create a new issue named **QA and Release for version \<VERSION\>**, to track the general progress.
You can generate its content with the the `poetry run ./dev_scripts/generate-release-tasks.py` command. You can generate its content with the the `uv run ./dev_scripts/generate-release-tasks.py` command.
- [ ] [Add new Linux platforms and remove obsolete ones](https://github.com/freedomofpress/dangerzone/blob/main/RELEASE.md#add-new-linux-platforms-and-remove-obsolete-ones) - [ ] [Add new Linux platforms and remove obsolete ones](https://github.com/freedomofpress/dangerzone/blob/main/RELEASE.md#add-new-platforms-and-remove-obsolete-ones)
- [ ] Bump the Python dependencies using `poetry lock` - [ ] Bump the Python dependencies using `uv lock`
- [ ] Check for new [WiX releases](https://github.com/wixtoolset/wix/releases) and update it if needed - [ ] Check for new [WiX releases](https://github.com/wixtoolset/wix/releases) and update it if needed
- [ ] Update `version` in `pyproject.toml` - [ ] Update `version` in `pyproject.toml`
- [ ] Update `share/version.txt` - [ ] Update `share/version.txt`
@ -121,11 +121,11 @@ Here is what you need to do:
```bash ```bash
# In case of a new Python installation or minor version upgrade, e.g., from # In case of a new Python installation or minor version upgrade, e.g., from
# 3.11 to 3.12, reinstall Poetry # 3.11 to 3.12, reinstall uv
python3 -m pip install poetry poetry-plugin-export python3 -m pip install uv
# You can verify the correct Python version is used # You can verify the correct Python version is used
poetry debug info uv python find
# Replace with the actual version # Replace with the actual version
export DZ_VERSION=$(cat share/version.txt) export DZ_VERSION=$(cat share/version.txt)
@ -136,18 +136,15 @@ Here is what you need to do:
# Clean the git repository # Clean the git repository
git clean -df git clean -df
# Clean up the environment
poetry env remove --all
# Install the dependencies # Install the dependencies
poetry install --sync uv sync
``` ```
- [ ] Build the container image and the OCR language data - [ ] Build the container image and the OCR language data
```bash ```bash
poetry run ./install/common/build-image.py uv run ./install/common/build-image.py
poetry run ./install/common/download-tessdata.py uv run ./install/common/download-tessdata.py
# Copy the container image to the assets folder # Copy the container image to the assets folder
cp share/container.tar ~dz/release-assets/$VERSION/dangerzone-$VERSION-arm64.tar cp share/container.tar ~dz/release-assets/$VERSION/dangerzone-$VERSION-arm64.tar
@ -157,7 +154,7 @@ Here is what you need to do:
- [ ] Build the app bundle - [ ] Build the app bundle
```bash ```bash
poetry run ./install/macos/build-app.py uv run ./install/macos/build-app.py
``` ```
- [ ] Sign the application bundle, and notarize it - [ ] Sign the application bundle, and notarize it
@ -170,7 +167,7 @@ Here is what you need to do:
```bash ```bash
# Sign the .App and make it a .dmg # Sign the .App and make it a .dmg
poetry run ./install/macos/build-app.py --only-codesign uv run ./install/macos/build-app.py --only-codesign
# Notarize it. You must run this command from the MacOS UI # Notarize it. You must run this command from the MacOS UI
# from a terminal application. # from a terminal application.
@ -203,11 +200,11 @@ The Windows release is performed in a Windows 11 virtual machine (as opposed to
- [ ] Checkout the dependencies, and clean your local copy: - [ ] Checkout the dependencies, and clean your local copy:
```bash ```bash
# In case of a new Python installation or minor version upgrade, e.g., from # In case of a new Python installation or minor version upgrade, e.g., from
# 3.11 to 3.12, reinstall Poetry # 3.11 to 3.12, reinstall uv
python3 -m pip install poetry poetry-plugin-export python3 -m pip install uv
# You can verify the correct Python version is used # You can verify the correct Python version is used
poetry debug info uv python find
# Replace with the actual version # Replace with the actual version
export DZ_VERSION=$(cat share/version.txt) export DZ_VERSION=$(cat share/version.txt)
@ -219,16 +216,16 @@ The Windows release is performed in a Windows 11 virtual machine (as opposed to
git clean -df git clean -df
# Clean up the environment # Clean up the environment
poetry env remove --all uv env remove --all
# Install the dependencies # Install the dependencies
poetry install --sync uv install --sync
``` ```
- [ ] Copy the container image into the VM - [ ] Copy the container image into the VM
> [!IMPORTANT] > [!IMPORTANT]
> Instead of running `python .\install\windows\build-image.py` in the VM, run the build image script on the host (making sure to build for `linux/amd64`). Copy `share/container.tar` and `share/image-id.txt` from the host into the `share` folder in the VM. > Instead of running `python .\install\windows\build-image.py` in the VM, run the build image script on the host (making sure to build for `linux/amd64`). Copy `share/container.tar.gz` and `share/image-id.txt` from the host into the `share` folder in the VM.
- [ ] Run `poetry run .\install\windows\build-app.bat` - [ ] Run `uv run .\install\windows\build-app.bat`
- [ ] When you're done you will have `dist\Dangerzone.msi` - [ ] When you're done you will have `dist\Dangerzone.msi`
Rename `Dangerzone.msi` to `Dangerzone-$VERSION.msi`. Rename `Dangerzone.msi` to `Dangerzone-$VERSION.msi`.
@ -262,7 +259,7 @@ or create your own locally with:
./dev_scripts/env.py --distro debian --version bookworm run --dev bash ./dev_scripts/env.py --distro debian --version bookworm run --dev bash
# Build the latest container # Build the latest container
./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c "cd dangerzone && poetry run ./install/common/build-image.py" ./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c "cd dangerzone && uv run ./install/common/build-image.py"
# Create a .deb # Create a .deb
./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c "cd dangerzone && ./install/linux/build-deb.py" ./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c "cd dangerzone && ./install/linux/build-deb.py"
@ -286,7 +283,7 @@ or create your own locally with:
./dev_scripts/env.py --distro fedora --version 41 build-dev ./dev_scripts/env.py --distro fedora --version 41 build-dev
# Build the latest container (skip if already built): # Build the latest container (skip if already built):
./dev_scripts/env.py --distro fedora --version 41 run --dev bash -c "cd dangerzone && poetry run ./install/common/build-image.py" ./dev_scripts/env.py --distro fedora --version 41 run --dev bash -c "cd dangerzone && uv run ./install/common/build-image.py"
# Create a .rpm: # Create a .rpm:
./dev_scripts/env.py --distro fedora --version 41 run --dev bash -c "cd dangerzone && ./install/linux/build-rpm.py" ./dev_scripts/env.py --distro fedora --version 41 run --dev bash -c "cd dangerzone && ./install/linux/build-rpm.py"

View file

@ -1,2 +1,2 @@
set DANGERZONE_MODE=cli set DANGERZONE_MODE=cli
poetry run python .\dev_scripts\dangerzone %* uv run python .\dev_scripts\dangerzone %*

View file

@ -1,2 +1,2 @@
set DANGERZONE_MODE=gui set DANGERZONE_MODE=gui
poetry run python .\dev_scripts\dangerzone %* uv run python .\dev_scripts\dangerzone %*

View file

@ -52,7 +52,7 @@ Run Dangerzone in the development environment:
env.py --distro ubuntu --version 22.04 run --dev bash env.py --distro ubuntu --version 22.04 run --dev bash
user@dangerzone-dev:~$ cd dangerzone/ user@dangerzone-dev:~$ cd dangerzone/
user@dangerzone-dev:~$ poetry run ./dev_scripts/dangerzone user@dangerzone-dev:~$ uv run ./dev_scripts/dangerzone
Run Dangerzone in the end-user environment: Run Dangerzone in the end-user environment:
@ -106,8 +106,8 @@ RUN apt-get update \
# FIXME: Install Poetry on Fedora via package manager. # FIXME: Install Poetry on Fedora via package manager.
DOCKERFILE_BUILD_DEV_FEDORA_DEPS = r""" DOCKERFILE_BUILD_DEV_FEDORA_DEPS = r"""
RUN dnf install -y git rpm-build podman python3 python3-devel python3-poetry-core \ RUN dnf install -y git rpm-build podman python3 python3-devel uv \
pipx make qt6-qtbase-gui gcc gcc-c++\ make qt6-qtbase-gui python3-hatchling pipx gcc gcc-c++\
&& dnf clean all && dnf clean all
# FIXME: Drop this fix after it's resolved upstream. # FIXME: Drop this fix after it's resolved upstream.

View file

@ -35,14 +35,14 @@ It can run the tasks for you, pausing when it needs manual intervention.
You can run it with a command like: You can run it with a command like:
```bash ```bash
poetry run ./dev_scripts/qa.py {distro}-{version} uv run ./dev_scripts/qa.py {distro}-{version}
``` ```
### The checklist ### The checklist
- [ ] Create a test build in Windows and make sure it works: - [ ] Create a test build in Windows and make sure it works:
- [ ] Check if the suggested Python version is still supported. - [ ] Check if the suggested Python version is still supported.
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with uv.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -51,7 +51,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in macOS (Intel CPU) and make sure it works: - [ ] Create a test build in macOS (Intel CPU) and make sure it works:
- [ ] Check if the suggested Python version is still supported. - [ ] Check if the suggested Python version is still supported.
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with `uv`.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -60,7 +60,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in macOS (M1/2 CPU) and make sure it works: - [ ] Create a test build in macOS (M1/2 CPU) and make sure it works:
- [ ] Check if the suggested Python version is still supported. - [ ] Check if the suggested Python version is still supported.
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with `uv`.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -69,7 +69,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in the most recent Ubuntu LTS platform (Ubuntu 24.04 - [ ] Create a test build in the most recent Ubuntu LTS platform (Ubuntu 24.04
as of writing this) and make sure it works: as of writing this) and make sure it works:
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with `uv`.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -78,7 +78,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in the most recent Fedora platform (Fedora 41 as of - [ ] Create a test build in the most recent Fedora platform (Fedora 41 as of
writing this) and make sure it works: writing this) and make sure it works:
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with `uv`.
- [ ] Build the container image and ensure the development environment uses - [ ] Build the container image and ensure the development environment uses
the new image. the new image.
- [ ] Download the OCR language data using `./install/common/download-tessdata.py` - [ ] Download the OCR language data using `./install/common/download-tessdata.py`
@ -87,7 +87,7 @@ poetry run ./dev_scripts/qa.py {distro}-{version}
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below). - [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
- [ ] Create a test build in the most recent Qubes Fedora template (Fedora 40 as - [ ] Create a test build in the most recent Qubes Fedora template (Fedora 40 as
of writing this) and make sure it works: of writing this) and make sure it works:
- [ ] Create a new development environment with Poetry. - [ ] Create a new development environment with `uv`.
- [ ] Run the Dangerzone tests. - [ ] Run the Dangerzone tests.
- [ ] Create a Qubes .rpm package and install it system-wide. - [ ] Create a Qubes .rpm package and install it system-wide.
- [ ] Ensure that the Dangerzone application appears in the "Applications" - [ ] Ensure that the Dangerzone application appears in the "Applications"
@ -251,23 +251,47 @@ Install dependencies:
</table> </table>
<<<<<<< HEAD
=======
<table>
<tr>
<td>
<details>
<summary><i>:memo: Expand this section if you are on Ubuntu 20.04 (Focal).</i></summary>
</br>
The default Python version that ships with Ubuntu Focal (3.8) is not
compatible with PySide6, which requires Python 3.9 or greater.
You can install Python 3.9 using the `python3.9` package.
```bash
sudo apt install -y python3.9
```
`uv` will automatically pick up the correct version when running.
</details>
</td>
</tr>
</table>
```sh ```sh
sudo apt install -y podman dh-python build-essential make libqt6gui6 \ sudo apt install -y podman dh-python build-essential make libqt6gui6 \
pipx python3 python3-dev pipx python3 python3-dev
``` ```
Install Poetry using `pipx` (recommended) and add it to your `$PATH`: Install `uv` using `pipx` (recommended) and add it to your `$PATH`:
_(See also a list of [alternative installation _(See also a list of [alternative installation
methods](https://python-poetry.org/docs/#installation))_ methods](https://python-`uv`.org/docs/#installation))_
```sh ```sh
pipx ensurepath pipx ensurepath
pipx install poetry pipx install `uv`
pipx inject poetry poetry-plugin-export
``` ```
After this, restart the terminal window, for the `poetry` command to be in your After this, restart the terminal window, for the ``uv command to be in your
`$PATH`. `$PATH`.
@ -277,13 +301,13 @@ Clone this repository:
git clone https://github.com/freedomofpress/dangerzone/ git clone https://github.com/freedomofpress/dangerzone/
``` ```
Change to the `dangerzone` folder, and install the poetry dependencies: Change to the `dangerzone` folder, and install the `uv` dependencies:
> **Note**: due to an issue with [poetry](https://github.com/python-poetry/poetry/issues/1917), if it prompts for your keyring, disable the keyring with `keyring --disable` and run the command again. > **Note**: due to an issue with [`uv`](https://github.com/python-`uv`/`uv`/issues/1917), if it prompts for your keyring, disable the keyring with `keyring --disable` and run the command again.
``` ```
cd dangerzone cd dangerzone
poetry install `uv` install
``` ```
Build the latest container: Build the latest container:
@ -302,7 +326,7 @@ Run from source tree:
```sh ```sh
# start a shell in the virtual environment # start a shell in the virtual environment
poetry shell `uv` shell
# run the CLI # run the CLI
./dev_scripts/dangerzone-cli --help ./dev_scripts/dangerzone-cli --help
@ -323,15 +347,36 @@ CONTENT_BUILD_FEDORA = r"""## Fedora
Install dependencies: Install dependencies:
```sh ```sh
sudo dnf install -y rpm-build podman python3 python3-devel python3-poetry-core \ sudo dnf install -y rpm-build podman python3 python3-devel python3-`uv`-core \
pipx qt6-qtbase-gui pipx qt6-qtbase-gui
``` ```
Install Poetry using `pipx`: <table>
<tr>
<td>
<details>
<summary><i>:memo: Expand this section if you are on Fedora 41.</i></summary>
</br>
The default Python version that ships with Fedora 41 (3.13) is not
compatible with PySide6, which requires Python 3.12 or earlier.
You can install Python 3.12 using the `python3.12` package.
```bash
sudo dnf install -y python3.12
```
`uv` will automatically pick up the correct version when running.
</details>
</td>
</tr>
</table>
Install `uv` using `pipx`:
```sh ```sh
pipx install poetry pipx install `uv`
pipx inject poetry poetry-plugin-export
``` ```
Clone this repository: Clone this repository:
@ -340,13 +385,13 @@ Clone this repository:
git clone https://github.com/freedomofpress/dangerzone/ git clone https://github.com/freedomofpress/dangerzone/
``` ```
Change to the `dangerzone` folder, and install the poetry dependencies: Change to the `dangerzone` folder, and install the `uv` dependencies:
> **Note**: due to an issue with [poetry](https://github.com/python-poetry/poetry/issues/1917), if it prompts for your keyring, disable the keyring with `keyring --disable` and run the command again. > **Note**: due to an issue with [`uv`](https://github.com/python-`uv`/`uv`/issues/1917), if it prompts for your keyring, disable the keyring with `keyring --disable` and run the command again.
``` ```
cd dangerzone cd dangerzone
poetry install `uv` install
``` ```
Build the latest container: Build the latest container:
@ -365,7 +410,7 @@ Run from source tree:
```sh ```sh
# start a shell in the virtual environment # start a shell in the virtual environment
poetry shell `uv` shell
# run the CLI # run the CLI
./dev_scripts/dangerzone-cli --help ./dev_scripts/dangerzone-cli --help
@ -394,10 +439,10 @@ Install the latest version of Python 3.12 (64-bit) [from python.org](https://www
Install Microsoft Visual C++ 14.0 or greater. Get it with ["Microsoft C++ Build Tools"](https://visualstudio.microsoft.com/visual-cpp-build-tools/) and make sure to select "Desktop development with C++" when installing. Install Microsoft Visual C++ 14.0 or greater. Get it with ["Microsoft C++ Build Tools"](https://visualstudio.microsoft.com/visual-cpp-build-tools/) and make sure to select "Desktop development with C++" when installing.
Install [poetry](https://python-poetry.org/). Open PowerShell, and run: Install [`uv`](https://python-`uv`.org/). Open PowerShell, and run:
``` ```
python -m pip install poetry poetry-plugin-export python -m pip install `uv`
``` ```
Install git from [here](https://git-scm.com/download/win), open a Windows terminal (`cmd.exe`) and clone this repository: Install git from [here](https://git-scm.com/download/win), open a Windows terminal (`cmd.exe`) and clone this repository:
@ -406,11 +451,11 @@ Install git from [here](https://git-scm.com/download/win), open a Windows termin
git clone https://github.com/freedomofpress/dangerzone/ git clone https://github.com/freedomofpress/dangerzone/
``` ```
Change to the `dangerzone` folder, and install the poetry dependencies: Change to the `dangerzone` folder, and install the `uv` dependencies:
``` ```
cd dangerzone cd dangerzone
poetry install `uv` install
``` ```
Build the dangerzone container image: Build the dangerzone container image:
@ -429,7 +474,7 @@ After that you can launch dangerzone during development with:
``` ```
# start a shell in the virtual environment # start a shell in the virtual environment
poetry shell `uv` shell
# run the CLI # run the CLI
.\dev_scripts\dangerzone-cli.bat --help .\dev_scripts\dangerzone-cli.bat --help
@ -832,11 +877,11 @@ class QAWindows(QABase):
logger.info("Verified that Docker Desktop is installed and running") logger.info("Verified that Docker Desktop is installed and running")
@QABase.task( @QABase.task(
"Install Poetry and the project's dependencies", ref=REF_BUILD, auto=True "Install `uv` and the project's dependencies", ref=REF_BUILD, auto=True
) )
def install_poetry(self): def install_uv(self):
self.run("python", "-m", "pip", "install", "poetry", "poetry-plugin-export") self.run("python", "-m", "pip", "install", "`uv`")
self.run("poetry", "install", "--sync") self.run("`uv`", "install", "--sync")
@QABase.task("Build Dangerzone container image", ref=REF_BUILD, auto=True) @QABase.task("Build Dangerzone container image", ref=REF_BUILD, auto=True)
def build_image(self): def build_image(self):
@ -846,12 +891,12 @@ class QAWindows(QABase):
def run_tests(self): def run_tests(self):
# NOTE: Windows does not have Makefile by default. # NOTE: Windows does not have Makefile by default.
self.run( self.run(
"poetry", "run", "pytest", "-v", "--ignore", r"tests\test_large_set.py" "`uv`", "run", "pytest", "-v", "--ignore", r"tests\test_large_set.py"
) )
@QABase.task("Build Dangerzone .exe", ref="REF_BUILD", auto=True) @QABase.task("Build Dangerzone .exe", ref="REF_BUILD", auto=True)
def build_dangerzone_exe(self): def build_dangerzone_exe(self):
self.run("poetry", "run", "python", r".\setup-windows.py", "build") self.run("`uv`", "run", "python", r".\setup-windows.py", "build")
@classmethod @classmethod
def get_id(cls): def get_id(cls):
@ -860,7 +905,7 @@ class QAWindows(QABase):
def start(self): def start(self):
self.install_python() self.install_python()
self.install_docker() self.install_docker()
self.install_poetry() self.install_uv()
self.build_image() self.build_image()
self.download_tessdata() self.download_tessdata()
self.run_tests() self.run_tests()
@ -892,9 +937,8 @@ class QALinux(QABase):
args_str = " ".join(args) args_str = " ".join(args)
self.container_run("bash", "-c", f"cd dangerzone; {args_str}") self.container_run("bash", "-c", f"cd dangerzone; {args_str}")
def poetry_run(self, *args): def uv_run(self, *args):
"""Run a command via Poetry inside a Dangerzone environment.""" self.shell_run("uv", "run", *args)
self.shell_run("poetry", "run", *args)
@QABase.task( @QABase.task(
"Create Dangerzone build environment", "Create Dangerzone build environment",
@ -921,7 +965,7 @@ class QALinux(QABase):
@QABase.task("Run tests", ref="REF_BUILD", auto=True) @QABase.task("Run tests", ref="REF_BUILD", auto=True)
def run_tests(self): def run_tests(self):
self.poetry_run("make", "test") self.`uv`_run("make", "test")
def build_package(self): def build_package(self):
"""Build the Dangerzone .deb/.rpm package""" """Build the Dangerzone .deb/.rpm package"""

View file

@ -0,0 +1,19 @@
# First, login to the container registry.
# (We only need this because images are not publicly available yet)
# Enter "USERNAME" instead of your username
# and use your PAT as a password
# regctl registry login ghcr.io
# Get the manifest from the latest tag
regctl manifest get --format raw-body ghcr.io/freedomofpress/dangerzone/dangerzone:latest > manifest.json
# The attestation for this manifest hash is available
# at the tag named "sha256-sha256(manifest.json)"
DIGEST="sha256-$(sha256sum manifest.json | awk '{ print $1 }')"
regctl artifact get ghcr.io/freedomofpress/dangerzone/dangerzone:${DIGEST} > bundle.json
# Finally verify that the attestation is the right one
cosign verify-blob-attestation --bundle bundle.json --new-bundle-format\
--certificate-oidc-issuer="https://token.actions.githubusercontent.com"\
--certificate-identity-regexp="^https://github.com/freedomofpress/dangerzone/.github/workflows/release-container-image.yml@refs/heads/test/image-publication-cosign"\
manifest.json

13
dodo.py
View file

@ -53,6 +53,7 @@ TESSDATA_TARGETS = list_language_data()
IMAGE_DEPS = [ IMAGE_DEPS = [
"Dockerfile", "Dockerfile",
"uv.lock",
*list_files("dangerzone/conversion"), *list_files("dangerzone/conversion"),
*list_files("dangerzone/container_helpers"), *list_files("dangerzone/container_helpers"),
"install/common/build-image.py", "install/common/build-image.py",
@ -65,7 +66,7 @@ SOURCE_DEPS = [
*list_files("dangerzone", recursive=True), *list_files("dangerzone", recursive=True),
] ]
PYTHON_DEPS = ["poetry.lock", "pyproject.toml"] PYTHON_DEPS = ["uv.lock", "pyproject.toml"]
DMG_DEPS = [ DMG_DEPS = [
*list_files("install/macos"), *list_files("install/macos"),
@ -206,9 +207,9 @@ def task_build_image():
} }
def task_poetry_install(): def task_uv_install():
"""Setup the Poetry environment""" """Setup the uv environment"""
return {"actions": ["poetry install --sync"], "clean": ["poetry env remove --all"]} return {"actions": ["uv sync"], "clean": ["rm -rf .venv"]}
def task_macos_build_dmg(): def task_macos_build_dmg():
@ -220,7 +221,7 @@ def task_macos_build_dmg():
return { return {
"actions": [ "actions": [
(copy_dir, [".", dz_dir]), (copy_dir, [".", dz_dir]),
f"cd {dz_dir} && poetry run install/macos/build-app.py --with-codesign", f"cd {dz_dir} && uv run install/macos/build-app.py --with-codesign",
( (
"xcrun notarytool submit --wait --apple-id %(apple_id)s" "xcrun notarytool submit --wait --apple-id %(apple_id)s"
f" --keychain-profile dz-notarytool-release-key {dmg_src}" f" --keychain-profile dz-notarytool-release-key {dmg_src}"
@ -234,7 +235,7 @@ def task_macos_build_dmg():
"task_dep": [ "task_dep": [
"macos_check_system", "macos_check_system",
"init_release_dir", "init_release_dir",
"poetry_install", "uv_install",
"download_tessdata", "download_tessdata",
], ],
"targets": [dmg_src, dmg_dst], "targets": [dmg_src, dmg_dst],

View file

@ -27,13 +27,13 @@ def build(build_dir, qubes=False):
The build process is the following: The build process is the following:
1. Clean up any stale data from previous runs under ./dist. Note that this directory 1. Clean up any stale data from previous runs under ./dist. Note that this directory
is used by `poetry build` and `rpmbuild`. is used by `uv build` and `rpmbuild`.
2. Create the necessary RPM project structure under the specified build directory 2. Create the necessary RPM project structure under the specified build directory
(default: ~/rpmbuild), and use symlinks to point to ./dist, so that we don't need (default: ~/rpmbuild), and use symlinks to point to ./dist, so that we don't need
to move files explicitly. to move files explicitly.
3. Create a Python source distribution using `poetry build`. If we are building a 3. Create a Python source distribution using `uv build --sdist`.
Qubes package and there is a container image under `share/`, stash it temporarily If we are building a Qubes package and there is a container image under
under a different directory. `share/`, stash it temporarily under a different directory.
4. Build both binary and source RPMs using rpmbuild. Optionally, pass to the SPEC 4. Build both binary and source RPMs using rpmbuild. Optionally, pass to the SPEC
`_qubes` flag, that denotes we want to build a package for Qubes. `_qubes` flag, that denotes we want to build a package for Qubes.
""" """
@ -75,7 +75,7 @@ def build(build_dir, qubes=False):
if stash_container and container_tar.exists(): if stash_container and container_tar.exists():
container_tar.rename(container_tar_bak) container_tar.rename(container_tar_bak)
try: try:
subprocess.run(["poetry", "build", "-f", "sdist"], cwd=root, check=True) subprocess.run(["uv", "build", "--sdist"], cwd=root, check=True)
# Copy and unlink the Dangerzone sdist, instead of just renaming it. If the # Copy and unlink the Dangerzone sdist, instead of just renaming it. If the
# build directory is outside the filesystem boundary (e.g., due to a container # build directory is outside the filesystem boundary (e.g., due to a container
# mount), then a simple rename will not work. # mount), then a simple rename will not work.

View file

@ -11,7 +11,7 @@
# #
# 1. It expects a `dangerzone-<version>.tar.gz` package under SOURCES. It is # 1. It expects a `dangerzone-<version>.tar.gz` package under SOURCES. It is
# best not to invoke `tar` yourself, but create a Python source distribution # best not to invoke `tar` yourself, but create a Python source distribution
# instead, via `poetry build`. # instead, via `uv build --sdist`.
# 2. It detects the `_qubes` parameter. If 1, it will build a package # 2. It detects the `_qubes` parameter. If 1, it will build a package
# tailored for installation in Qubes environments. Else, it will build a # tailored for installation in Qubes environments. Else, it will build a
# regular RPM package. The key differences between these packages are that: # regular RPM package. The key differences between these packages are that:
@ -41,7 +41,7 @@ URL: https://dangerzone.rocks
# XXX: rpmbuild attempts to find a tarball in SOURCES using the basename in the # XXX: rpmbuild attempts to find a tarball in SOURCES using the basename in the
# Source0 url. In our case, GitHub uses `v<version>.tar.gz`. However, the name # Source0 url. In our case, GitHub uses `v<version>.tar.gz`. However, the name
# of the source distribution that `poetry build` creates is # of the source distribution that `uv build --sdist` creates is
# `dangerzone-<version>.tar.gz`, so rpmbuild cannot find it. # `dangerzone-<version>.tar.gz`, so rpmbuild cannot find it.
# #
# Taking a hint from SecureDrop Workstation, we can fix this by adding an # Taking a hint from SecureDrop Workstation, we can fix this by adding an

View file

@ -28,7 +28,7 @@ def main():
) )
logger.info("Getting PyMuPDF deps as requirements.txt") logger.info("Getting PyMuPDF deps as requirements.txt")
cmd = ["poetry", "export", "--only", "debian"] cmd = ["uv", "export", "--only-group", "debian"]
container_requirements_txt = subprocess.check_output(cmd) container_requirements_txt = subprocess.check_output(cmd)
logger.info(f"Vendoring PyMuPDF under '{args.dest}'") logger.info(f"Vendoring PyMuPDF under '{args.dest}'")

1486
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,69 +1,89 @@
[tool.poetry] [project]
requires-python = ">=3.9,<3.13"
name = "dangerzone" name = "dangerzone"
version = "0.8.1" version = "0.8.1"
description = "Take potentially dangerous PDFs, office documents, or images and convert them to safe PDFs" description = "Take potentially dangerous PDFs, office documents, or images and convert them to safe PDFs"
authors = ["Freedom of the Press Foundation <info@freedom.press>", "Micah Lee <micah.lee@theintercept.com>"] authors = [
license = "AGPL-3.0" { name = "Freedom of the Press Foundation", email = "info@freedom.press" },
# NOTE: See also https://github.com/freedomofpress/dangerzone/issues/677 { name = "Micah Lee", email = "micah.lee@theintercept.com" }, ]
include = [ license = { text = "AGPL-3.0"}
{ path = "share/*", format = "sdist" },
{ path = "qubes/*", format = "sdist" }, dependencies = [
{ path = "install/linux/press.freedom.dangerzone.*", format = "sdist" }, "appdirs",
{ path = "README.md", format = "sdist" }, "click",
"platformdirs",
"colorama",
"markdown",
"packaging",
"pymupdf (>=1.23.3, <1.24.0)", # The version in Fedora 39
"pyside6 (>=6.7.1, < 6.8)",
# "pyxdg; sys_platform == 'linux'",
"requests",]
dynamic = ["readme", "classifiers"]
classifiers = [
"Programming Language :: Python",
"Intended Audience :: End Users/Desktop",
"Operating System :: OS Independent",
"Topic :: Security",
] ]
[tool.poetry.dependencies] [dependency-groups]
python = ">=3.9,<3.14" # Dependencies installed inside the container
click = "*" container = [
platformdirs = "*" "pymupdf",
PySide6 = "^6.7.1" ]
PyMuPDF = "^1.23.3" # The version in Fedora 39
colorama = "*"
pyxdg = {version = "*", platform = "linux"}
requests = "*"
markdown = "*"
packaging = "*"
[tool.poetry.scripts] debian = [
dangerzone = 'dangerzone:main' "pymupdf (>=1.24.11, <1.25)",
dangerzone-cli = 'dangerzone:main' ]
# Dependencies required for packaging the code on various platforms. # Dependencies required only for development
[tool.poetry.group.package.dependencies] dev = [
setuptools = "*" "httpx",
cx_freeze = {version = "^7.2.5", platform = "win32"} ]
pywin32 = {version = "*", platform = "win32"}
pyinstaller = {version = "*", platform = "darwin"}
doit = "^0.36.0"
jinja2-cli = "^0.8.2"
# Dependencies required for linting the code. # Dependencies required for linting the code.
[tool.poetry.group.lint.dependencies] lint = [
click = "*" # Install click so mypy is able to reason about it. "click",
mypy = "*" "mypy",
ruff = "*" "ruff",
types-colorama = "*" "types-colorama",
types-PySide2 = "*" "types-pyside2",
types-Markdown = "*" "types-markdown",
types-pygments = "*" "types-pygments",
types-requests = "*" "types-requests",
]
# Dependencies required for packaging the code on various platforms.
package = [
"cx-freeze",
"doit",
"jinja2-cli",
"pywin32",
"pyinstaller",
"setuptools",
]
test = [
"pytest",
"pytest-cov",
"pytest-mock",
"pytest-qt",
"pytest-rerunfailures",
"pytest-subprocess",
"strip-ansi",
"numpy (>=2.0, <3.0)" # for python 3.9 compatibility
]
[project.optional-dependencies]
# Dependencies required for testing the code. # Dependencies required for testing the code.
[tool.poetry.group.test.dependencies] # XXX Shoul we keep ?
pytest = "^7.1.2"
pytest-mock = "^3.10.0"
pytest-qt = "^4.2.0"
pytest-cov = "^5.0.0"
strip-ansi = "*"
pytest-subprocess = "^1.5.2"
pytest-rerunfailures = "^14.0"
numpy = "2.0" # bump when we remove python 3.9 support
[tool.poetry.group.debian.dependencies] [project.scripts]
pymupdf = "^1.24.11" dangerzone = 'dangerzone:main'
dangerzone-cli = 'dangerzone:main'
[tool.poetry.group.dev.dependencies]
httpx = "^0.27.2"
[tool.doit] [tool.doit]
verbosity = 3 verbosity = 3
@ -74,6 +94,24 @@ select = [
"I", "I",
] ]
[tool.setuptools.dynamic]
readme = {file = "README.md"}
[tool.hatch.build.targets.wheel]
packages = [
"dangerzone",
]
[tool.hatch.build.targets.sdist]
include = [
"dangerzone/*",
"share/*",
"qubes/*",
"install/linux/press.freedom.dangerzone.*",
"README.md",
]
[build-system] [build-system]
requires = ["poetry-core>=1.2.0"] requires = ["hatchling"]
build-backend = "poetry.core.masonry.api" build-backend = "hatchling.build"

1080
uv.lock Normal file

File diff suppressed because it is too large Load diff