diff --git a/BUILD.md b/BUILD.md index 3ef6b63..2580f52 100644 --- a/BUILD.md +++ b/BUILD.md @@ -113,7 +113,7 @@ Install Poetry using `pipx`: ```sh pipx install poetry -pipx inject poetry poetry-plugin-export +pipx inject poetry ``` Clone this repository: @@ -326,7 +326,7 @@ cd dangerzone Install Python dependencies: ```sh -python3 -m pip install poetry poetry-plugin-export +python3 -m pip install poetry poetry install ``` @@ -387,7 +387,7 @@ Install Microsoft Visual C++ 14.0 or greater. Get it with ["Microsoft C++ Build Install [poetry](https://python-poetry.org/). Open PowerShell, and run: ``` -python -m pip install poetry poetry-plugin-export +python -m pip install poetry ``` Install git from [here](https://git-scm.com/download/win), open a Windows terminal (`cmd.exe`) and clone this repository: diff --git a/Makefile b/Makefile index 217416d..e4ae230 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ fix: ## apply all the suggestions from ruff ruff format .PHONY: test -test: +test: ## Run the tests # Make each GUI test run as a separate process, to avoid segfaults due to # shared state. # See more in https://github.com/freedomofpress/dangerzone/issues/493 @@ -47,27 +47,31 @@ test-large: test-large-init ## Run large test set python -m pytest --tb=no tests/test_large_set.py::TestLargeSet -v $(JUNIT_FLAGS) --junitxml=$(TEST_LARGE_RESULTS) python $(TEST_LARGE_RESULTS)/report.py $(TEST_LARGE_RESULTS) -Dockerfile: Dockerfile.env Dockerfile.in +Dockerfile: Dockerfile.env Dockerfile.in ## Regenerate the Dockerfile from its template poetry run jinja2 Dockerfile.in Dockerfile.env > Dockerfile +.PHONY: poetry-install +poetry-install: ## Install project dependencies + poetry install + .PHONY: build-clean build-clean: - doit clean + poetry run doit clean .PHONY: build-macos-intel -build-macos-intel: build-clean - doit -n 8 +build-macos-intel: build-clean poetry-install ## Build macOS intel package (.dmg) + poetry run doit -n 8 .PHONY: build-macos-arm -build-macos-arm: build-clean - doit -n 8 macos_build_dmg +build-macos-arm: build-clean poetry-install ## Build macOS Apple Silicon package (.dmg) + poetry run doit -n 8 macos_build_dmg .PHONY: build-linux -build-linux: build-clean - doit -n 8 fedora_rpm debian_deb +build-linux: build-clean poetry-install ## Build linux packages (.rpm and .deb) + poetry run doit -n 8 fedora_rpm debian_deb .PHONY: regenerate-reference-pdfs -regenerate-reference-pdfs: +regenerate-reference-pdfs: ## Regenerate the reference PDFs pytest tests/test_cli.py -k regenerate --generate-reference-pdfs # Makefile self-help borrowed from the securedrop-client project # Explaination of the below shell command should it ever break. diff --git a/RELEASE.md b/RELEASE.md index 5df7288..17fbccb 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -123,7 +123,7 @@ Here is what you need to do: # In case of a new Python installation or minor version upgrade, e.g., from # 3.11 to 3.12, reinstall Poetry - python3 -m pip install poetry poetry-plugin-export + python3 -m pip install poetry # You can verify the correct Python version is used poetry debug info @@ -141,7 +141,7 @@ Here is what you need to do: poetry env remove --all # Install the dependencies - poetry install --sync + poetry sync ``` - [ ] Build the container image and the OCR language data @@ -205,7 +205,7 @@ The Windows release is performed in a Windows 11 virtual machine (as opposed to ```bash # In case of a new Python installation or minor version upgrade, e.g., from # 3.11 to 3.12, reinstall Poetry - python3 -m pip install poetry poetry-plugin-export + python3 -m pip install poetry # You can verify the correct Python version is used poetry debug info @@ -223,7 +223,7 @@ The Windows release is performed in a Windows 11 virtual machine (as opposed to poetry env remove --all # Install the dependencies - poetry install --sync + poetry sync ``` - [ ] Copy the container image into the VM diff --git a/dangerzone/__init__.py b/dangerzone/__init__.py index f029398..a67ebcf 100644 --- a/dangerzone/__init__.py +++ b/dangerzone/__init__.py @@ -4,6 +4,12 @@ import sys logger = logging.getLogger(__name__) +# Call freeze_support() to avoid passing unknown options to the subprocess. +# See https://github.com/freedomofpress/dangerzone/issues/873 +import multiprocessing + +multiprocessing.freeze_support() + try: from . import vendor # type: ignore [attr-defined] diff --git a/dangerzone/cli.py b/dangerzone/cli.py index ca5b644..1353995 100644 --- a/dangerzone/cli.py +++ b/dangerzone/cli.py @@ -52,7 +52,11 @@ def print_header(s: str) -> None: @click.option( "--set-container-runtime", required=False, - help="The path to the container runtime you want to set in the settings", + help=( + "The name or full path of the container runtime you want Dangerzone to use." + " You can specify the value 'default' if you want to take back your choice, and" + " let Dangerzone use the default runtime for this OS" + ), ) @click.version_option(version=get_version(), message="%(version)s") @errors.handle_document_errors @@ -69,10 +73,16 @@ def cli_main( display_banner() if set_container_runtime: settings = Settings() - container_runtime = settings.set_custom_runtime( - set_container_runtime, autosave=True - ) - click.echo(f"Set the settings container_runtime to {container_runtime}") + if set_container_runtime == "default": + settings.unset_custom_runtime() + click.echo( + "Instructed Dangerzone to use the default container runtime for this OS" + ) + else: + container_runtime = settings.set_custom_runtime( + set_container_runtime, autosave=True + ) + click.echo(f"Set the settings container_runtime to {container_runtime}") sys.exit(0) elif not filenames: raise click.UsageError("Missing argument 'FILENAMES...'") diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index 38b871f..fd86817 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -3,7 +3,6 @@ import os import platform import tempfile import typing -from multiprocessing import freeze_support from multiprocessing.pool import ThreadPool from pathlib import Path from typing import List, Optional @@ -228,7 +227,9 @@ class MainWindow(QtWidgets.QMainWindow): if not is_version_valid: self.handle_docker_desktop_version_check(is_version_valid, version) except errors.UnsupportedContainerRuntime as e: - pass # It's catched later in the flow. + pass # It's caught later in the flow. + except errors.NoContainerTechException as e: + pass # It's caught later in the flow. self.show() @@ -1236,9 +1237,6 @@ class DocumentsListWidget(QtWidgets.QListWidget): def start_conversion(self) -> None: if not self.thread_pool_initized: max_jobs = self.dangerzone.isolation_provider.get_max_parallel_conversions() - # Call freeze_support() to avoid passing unknown options to the subprocess. - # See https://github.com/freedomofpress/dangerzone/issues/873 - freeze_support() self.thread_pool = ThreadPool(max_jobs) for doc in self.docs_list: diff --git a/dangerzone/settings.py b/dangerzone/settings.py index a95917b..0e30896 100644 --- a/dangerzone/settings.py +++ b/dangerzone/settings.py @@ -52,6 +52,10 @@ class Settings: self.save() return container_runtime + def unset_custom_runtime(self) -> None: + self.settings.pop("container_runtime") + self.save() + def get(self, key: str) -> Any: return self.settings[key] diff --git a/debian/changelog b/debian/changelog index 269ced6..847cbda 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,13 +2,13 @@ dangerzone (0.9.0) unstable; urgency=low * Released Dangerzone 0.9.0 - -- Freedom of the Press Foundation Mon, 31 March 2025 15:57:18 +0300 + -- Freedom of the Press Foundation Mon, 31 Mar 2025 15:57:18 +0300 dangerzone (0.8.1) unstable; urgency=low * Released Dangerzone 0.8.1 - -- Freedom of the Press Foundation Tue, 22 December 2024 22:03:28 +0300 + -- Freedom of the Press Foundation Tue, 22 Dec 2024 22:03:28 +0300 dangerzone (0.8.0) unstable; urgency=low diff --git a/dev_scripts/qa.py b/dev_scripts/qa.py index b1ee7d9..86d33df 100755 --- a/dev_scripts/qa.py +++ b/dev_scripts/qa.py @@ -331,7 +331,7 @@ Install Poetry using `pipx`: ```sh pipx install poetry -pipx inject poetry poetry-plugin-export +pipx inject poetry ``` Clone this repository: @@ -397,7 +397,7 @@ Install Microsoft Visual C++ 14.0 or greater. Get it with ["Microsoft C++ Build Install [poetry](https://python-poetry.org/). Open PowerShell, and run: ``` -python -m pip install poetry poetry-plugin-export +python -m pip install poetry ``` Install git from [here](https://git-scm.com/download/win), open a Windows terminal (`cmd.exe`) and clone this repository: @@ -835,8 +835,8 @@ class QAWindows(QABase): "Install Poetry and the project's dependencies", ref=REF_BUILD, auto=True ) def install_poetry(self): - self.run("python", "-m", "pip", "install", "poetry", "poetry-plugin-export") - self.run("poetry", "install", "--sync") + self.run("python", "-m", "pip", "install", "poetry") + self.run("poetry", "sync") @QABase.task("Build Dangerzone container image", ref=REF_BUILD, auto=True) def build_image(self): diff --git a/docs/developer/doit.md b/docs/developer/doit.md index bf8fb16..dfbc0f5 100644 --- a/docs/developer/doit.md +++ b/docs/developer/doit.md @@ -42,7 +42,8 @@ doit ## Tips and tricks * You can run `doit list --all -s` to see the full list of tasks, their - dependencies, and whether they are up to date. + dependencies, and whether they are up to date (U) or will run (R). Note that + certain small tasks are always configured to run. * You can run `doit info ` to see which dependencies are missing. * You can pass the following environment variables to the script, in order to affect some global parameters: diff --git a/dodo.py b/dodo.py index ff8877d..1a7eda3 100644 --- a/dodo.py +++ b/dodo.py @@ -8,8 +8,7 @@ from doit.action import CmdAction ARCH = "arm64" if platform.machine() == "arm64" else "i686" VERSION = open("share/version.txt").read().strip() -FEDORA_VERSIONS = ["40", "41"] -DEBIAN_VERSIONS = ["bullseye", "jammy", "mantic", "noble", "trixie"] +FEDORA_VERSIONS = ["40", "41", "42"] ### Global parameters @@ -44,7 +43,6 @@ def list_language_data(): tessdata_dir = Path("share") / "tessdata" langs = json.loads(open(tessdata_dir.parent / "ocr-languages.json").read()).values() targets = [tessdata_dir / f"{lang}.traineddata" for lang in langs] - targets.append(tessdata_dir) return targets @@ -124,7 +122,7 @@ def build_deb(cwd): def build_rpm(version, cwd, qubes=False): """Build an .rpm package on the requested Fedora distro.""" - return build_linux_pkg(distro="Fedora", version=version, cwd=cwd, qubes=qubes) + return build_linux_pkg(distro="fedora", version=version, cwd=cwd, qubes=qubes) ### Tasks @@ -208,7 +206,7 @@ def task_build_image(): def task_poetry_install(): """Setup the Poetry environment""" - return {"actions": ["poetry install --sync"], "clean": ["poetry env remove --all"]} + return {"actions": ["poetry sync"], "clean": ["poetry env remove --all"]} def task_macos_build_dmg(): diff --git a/install/common/build-image.py b/install/common/build-image.py index 65a763d..868c5b1 100644 --- a/install/common/build-image.py +++ b/install/common/build-image.py @@ -5,7 +5,7 @@ import subprocess import sys from pathlib import Path -BUILD_CONTEXT = "dangerzone/" +BUILD_CONTEXT = "dangerzone" IMAGE_NAME = "dangerzone.rocks/dangerzone" if platform.system() in ["Darwin", "Windows"]: CONTAINER_RUNTIME = "docker" @@ -122,7 +122,8 @@ def main(): subprocess.run( [ - "./dev_scripts/repro-build.py", + sys.executable, + str(Path("dev_scripts") / "repro-build.py"), "build", "--runtime", args.runtime, diff --git a/install/common/download-tessdata.py b/install/common/download-tessdata.py index cf2b366..47c909e 100644 --- a/install/common/download-tessdata.py +++ b/install/common/download-tessdata.py @@ -51,6 +51,8 @@ def main(): if files == expected_files: logger.info("Skipping tessdata download, language data already exists") return + elif not files: + logger.info("Tesseract dir is empty, proceeding to download language data") else: logger.info(f"Found {tessdata_dir} but contents do not match") return 1 diff --git a/setup-windows.py b/setup-windows.py index ac5331a..7252b58 100644 --- a/setup-windows.py +++ b/setup-windows.py @@ -13,7 +13,7 @@ setup( description="Dangerzone", options={ "build_exe": { - "packages": ["dangerzone", "dangerzone.gui"], + "packages": ["dangerzone", "dangerzone.gui", "pymupdf._wxcolors"], "excludes": ["test", "tkinter"], "include_files": [("share", "share"), ("LICENSE", "LICENSE")], "include_msvcr": True,