Skip to content

For Developers

Hyacinthe-primus edited this page Nov 12, 2026 · 18 revisions

For Developers

For contributors, translators, and anyone who wants to run or build the project from source.


Prerequisites

Tool Version Purpose
Python 3.10 or 3.13 recommended Runtime
pip Latest Package manager
Git Any recent Cloning the repo
PyInstaller 6.x Building the .exe

Python 3.13 is what the project is currently compiled against. Avoid very recent versions, not all libraries may support them yet.

The current source version is 1.0.8 (src/app/__init__.py, pyproject.toml, and packaging/version_info.txt).


Clone & Install

git clone https://github.com/Hyacinthe-primus/File-Converter-Pro.git
cd File-Converter-Pro
pip install -r requirements.txt
pip install -r requirements-dev.txt             # Dev/Build dependencies
python src/main.py

Key Python Dependencies

Everything is installed by requirements.txt; see Credits for the full library list and what each package does. comtypes is Windows-only and no-ops on machines without Office.


External Binaries

FFmpeg is required for audio/video conversions; the other tools are optional. All are auto-detected at runtime; see Optional Tools for install links and what each tool unlocks. In a source run the directly resolvable executables are 7z/7zz, ffmpeg/ffprobe, gswin64c/gs, magick, soffice, wkhtmltopdf, pandoc, and tesseract. Pandoc may additionally use a LaTeX installation (pdflatex) when one is present.

Lookup order and config-file syntax are documented in External Tools (Advanced). In the source tree the override file is src/config/external_binaries.conf.


Running in Dev Mode

python src/main.py --help

This prints all available flags (language, theme, context menu, achievement commands, etc.).


CLI mode - achievement commands in terminal


CLI output is only visible when running from source. The compiled .exe does not expose a console window.


Tests

# Run all tests
python -m pytest tests/ -v

# Run a specific test file
python -m pytest tests/test_mixins.py -v

# External binaries resolver tests
python -m pytest tests/test_external_binaries.py -v

# Run a specific test
python -m pytest tests/test_mixins.py::test_format_size_kb -v

# Run tests in fast mode (no verbose)
python -m pytest tests/ -q

# Run tests with error display
python -m pytest tests/ --tb=short

Current suite: 1,067 passed, 8 skipped (79 test modules plus conftest.py). The skips require Word/LibreOffice integration tools that are unavailable in the current environment.

Conversion reliability regressions to run when touching shared helpers:

python -m pytest tests/test_conversion_pipeline.py tests/test_conversion_helpers_characterization.py -q
python -m pytest tests/test_docx_to_pdf_consolidation.py tests/test_pdf_to_word_text_only.py -q
python -m pytest tests/test_ocr_consolidation.py tests/test_ocr_merge_workers.py -q

Architecture / structural tests

tests/test_architecture.py guards cross-cutting invariants without launching the GUI:

  • Translation key consistency: every key in src/languages/fr.json must exist in every other language file, and any translate_text("...") literal that looks like a named key must exist in fr.json. New UI strings must be added to fr.json and all language files or these tests fail.
  • Mixin composition: every mixin in src/app/mixins/ (plus AppUIMixin / AppLogicMixin) must be in the FileConverterApp MRO, and key methods (e.g. project-tab handling) must resolve.
  • QSS object names: every setObjectName(...) must have a #selector somewhere (theme QSS, another .qss file, or an inline/f-string stylesheet in code).
python -m pytest tests/test_architecture.py -q

Ruff (Python Linter)

# Install ruff
pip install ruff

# Check all Python files
ruff check

# Check unused imports (F401)
ruff check --select F401

# Check unused variables (F841)
ruff check --select F841

# Check unused imports + variables
ruff check --select F401,F841

# Auto-fix unused imports
ruff check --select F401 --fix

# Auto-fix unused variables
ruff check --select F841 --fix --unsafe-fixes

# Auto-fix everything
ruff check --fix

# Code formatting (like black)
ruff format

# Check function complexity (C901)
ruff check --select C901

# Check duplicate imports (I001)
ruff check --select I001

Manual Checks

# Python syntax (check a file)
python -m py_compile file.py

# Run the application
python src/main.py

# Check file size
python -c "print(len(open('file.py').readlines()))"

Building the Exe

The project uses PyInstaller + UPX for compression. Build scripts are PowerShell-based.

1. Install build tools

pip install pyinstaller
winget install UPX.UPX

packaging/build.ps1 auto-detects upx.exe from PATH (then the optional $UPX_FALLBACK_PATH, including the standard WinGet install location). packaging/build_quick_check.ps1 still contains its own placeholder; set that to your local upx.exe path if you build Quick Check separately.

2. Build the main application

Run the build scripts from the packaging/ folder: build.ps1 looks for build.spec in the current directory.

Set-Location packaging
.\build.ps1

Runs PyInstaller with build.spec and produces packaging/dist/FCP/ (onedir output).

3. Build the Quick Check utility

.\build_quick_check.ps1

This requires an existing packaging/dist/FCP/ build and uses quick_check.spec. It is not run by build_all.ps1.

4. Package into an installer

.\build_installer.ps1

Calls Inno Setup with setup.iss and produces Output/FileConverterPro_Setup_<version>.exe. This script resolves the project root itself, but it expects the packaging/dist/FCP/ application build to exist.

Make sure Inno Setup is installed and on your PATH. Download: jrsoftware.org/isinfo.php

Full pipeline at once

Note: The Quick Check utility is not included in this pipeline and must be built separately using build_quick_check.ps1.

Set-Location packaging
.\build_all.ps1

build_all.ps1 runs the main application build, the installer build, and then creates Output/File_Converter_Pro_v<version>.zip from packaging/dist/FCP/ using 7-Zip. It also writes Output/checksums.txt with SHA-256 hashes for the installer and portable ZIP. Return to the repository root with Set-Location .. afterwards.


Project Structure

See the Directory Tree.

Main window inheritance chain:

Inheritance chain (MRO):
      AppLogicMixin(OptimizationMixin, ImageToPdfMixin, BatchMixin,
                    PdfOperationsMixin, PdfToWordMixin, WordToPdfMixin, CompressionMixin)
      └── AppUIMixin(FileManagementMixin, PanelsMixin, ProjectManagementMixin,
                     ThemeLanguageMixin, TranslationMixin, AppLogicMixin)
            └── FileConverterApp(AppUIMixin, QMainWindow)  ← QMainWindow mixed in here
                  └── FadingMainWindow

This chain is enforced by tests/test_architecture.py: every mixin class in app/mixins/ (plus AppUIMixin / AppLogicMixin) must be part of the FileConverterApp MRO, so a new mixin that is not composed into the app fails the test suite.


Batch Conversion Routing

Batch conversion lives in app/mixins/batch.py. Each file is dispatched through _convert_batch_file() → _batch_to_pdf / _batch_to_docx / _batch_to_png based on the target format code ("pdf", "docx", "png").

  • Stable format codes: the batch dialog stores a code as combo-item data (addItem(label, code)); the app reads it via selected_format() instead of matching translated labels so it works identically in every language.
  • Honest success reporting: a file only counts as converted when the output file actually exists (_convert_batch_file returns False otherwise). Unsupported combos are reported instead of silently "succeeding".
  • Engine reuse: document inputs reuse AdvancedConverterEngine (txt_to_pdf, rtf_to_pdf, xlsx_to_pdf, …); PDF → DOCX uses _batch_pdf_to_docx() which tries Word COM → LibreOffice (_convert_pdf_to_docx_libreoffice) → _solid_fitz_fallback; PDF → PNG renders one page per file via PyMuPDF.
  • Helpers (_batch_copy, _batch_temp_file, _pdf_to_png) keep routing side-effect-free and testable, see tests/test_batch.py.

Clone this wiki locally