Development Guide¶
Contributing, architecture, test commands, and the release process for
qrtransfer.
Table of Contents¶
- Layout
- Architecture notes
- Setting up a development environment
- Commands
- Test strategy
- Continuous integration
- Release process
- Manual acceptance checklist
Layout¶
qrtransfer/
├── pyproject.toml # package metadata, extras, ruff/pyright/pytest config
├── mkdocs.yml # docs site config (MkDocs + Material)
├── README.md # user-facing README (also the PyPI long description)
├── LICENSE
├── CHANGELOG.md
├── SECURITY.md / CONTRIBUTING.md / CODE_OF_CONDUCT.md / ACCESSIBILITY.md
├── CODEOWNERS / CONTRIBUTORS / Dockerfile / .version
├── logo/logo.svg # project logo
├── Screenshots/ # page screenshots (for docs/screenshots.md)
├── docs/ # MkDocs source (published to GitHub Pages)
│ ├── index.md # home page
│ ├── getting-started.md, installation.md, usage.md, cli.md, api.md
│ ├── configuration.md, architecture.md, deployment.md
│ ├── faq.md, troubleshooting.md, development.md, screenshots.md
├── .github/workflows/ # ci.yml (tests/lint/types), container.yml, docs.yml
├── src/qrtransfer/
│ ├── __init__.py # __version__ (single source of truth)
│ ├── __main__.py # python -m qrtransfer
│ ├── api.py # public library surface (start/stop + re-exports)
│ ├── cli.py # argparse, orchestration, session lifecycle
│ ├── session.py # Session dataclass (token, limits, expiry, ...)
│ ├── server.py # HTTP handler + threading server, auth flow
│ ├── network.py # interface listing, IP detection, free ports
│ ├── config.py # persistent interface/port settings
│ ├── history.py # past-transfers JSON store
│ ├── zipper.py # temporary zip creation
│ ├── upload.py # streaming multipart parser + sanitization
│ ├── web.py # dependency-free send/receive HTML pages
│ ├── qr.py # QR rendering (qrcode-terminal)
│ └── tls.py # self-signed cert generation + SSL context
└── tests/ # pytest suite
├── conftest.py # in-process HTTP server fixture
├── test_config.py
├── test_network.py
├── test_zipper.py
├── test_upload.py
├── test_server.py # localhost integration tests
├── test_cli.py # argparse + subprocess end-to-end tests
└── test_qr.py
Architecture notes¶
- No module globals. A single mutable
Sessionobject carries the token, password, expiry, download counter, and limits; the HTTP handler reads it from an instance attribute, not from global state. - Auth ordering matters.
TransferHandler._authorizechecks expiry → token → password → limit in that order. Checking the token before the password means a wrong token always returns404, never401, so an attacker can't probe for the existence of a password. - Receive uploads are streamed.
upload.MultipartStreamReaderparsesmultipart/form-dataincrementally from the socket, so a large upload never has to be buffered in memory. The stdlibcgimodule is deliberately avoided (deprecated in 3.13). - Cross-platform config.
platformdirsresolves config/data/cache locations; on Windows these honour%APPDATA%/%LOCALAPPDATA%. Config migration from the legacy~/.qr-filetransfer.jsonis handled inconfig.load_config.
Setting up a development environment¶
git clone https://github.com/rkriad585/qrtransfer.git
cd qrtransfer
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
.[dev] installs the package plus pytest, ruff, pyright, and build.
Commands¶
Run the test suite:
pytest -v
Lint and format:
ruff check .
ruff format --check . # check only
ruff format . # apply formatting
Type-check (uses the .venv configured in pyproject.toml):
pyright
Build distributions:
python -m build
Build and preview the documentation site (MkDocs):
pip install -e ".[docs]"
mkdocs serve # http://127.0.0.1:8000
mkdocs build # writes ./site (this is what the Docs CI workflow runs)
Smoke-test the console script:
qrtransfer --help
qrtransfer --version
qrtransfer myfile.jpg # then scan the QR code
qrtransfer receive # then upload from a phone
Test strategy¶
- Unit tests mock
psutilfor network code and the filesystem for config, zipper, and upload parsing — no real network access. - Integration tests start a real
TransferServeron an ephemeral port bound to127.0.0.1(seetests/conftest.py) and exercise the full auth flow overhttp.client, including multipart receive uploads. - CLI tests run
python -m qrtransferas a subprocess with a redirectedLOCALAPPDATA/XDG_*to keep tests hermetic, and verify the default exit-after-first-download behaviour end-to-end. - Test matrix in CI: Ubuntu / Windows / macOS × Python 3.9 / 3.11 / 3.13.
Continuous integration¶
.github/workflows/ci.yml runs on push to main and on pull requests:
test— the pytest matrix above.lint—ruff check .andruff format --check .(Ubuntu, Python 3.12).typecheck—pyrightinside the repo venv (Ubuntu, Python 3.12).
All three jobs must be green before merging.
.github/workflows/docs.yml builds the MkDocs site and deploys it to GitHub
Pages on pushes to main that touch the docs (and on workflow_dispatch). See
deployment.md.
Release process¶
- Bump
__version__insrc/qrtransfer/__init__.pyand add aCHANGELOG.mdentry. - Run
pytest,ruff, andpyrightlocally; make sure the wheel builds withpython -m build. - Tag the release:
git tag v0.1.0 && git push origin v0.1.0. The tag push also triggers.github/workflows/container.yml, which publishes the container image to GHCR. - Verify on a clean machine:
python -m venv /tmp/fresh && pip install git+https://github.com/rkriad585/qrtransfer.git@main && qrtransfer --version, or run the published container image (see deployment.md). The console script, import package, and repository name are allqrtransfer.
Manual acceptance checklist¶
Before each release, verify on the target platform:
- [ ]
qrtransfer myfile→ scan with a phone → file downloads, counter shows 1. - [ ] Directory +
--zip, password + expiry,--once, receive mode,--tls,--port 8080. - [ ] Windows console: unicode filenames,
Ctrl+Ccleanup, no leftover temp zips.
Related¶
- Documentation CI/deployment: deployment.md
- Repository overview for users: index.md