-
-
Notifications
You must be signed in to change notification settings - Fork 78
Contributing
Pull requests are welcome! Please target the develop branch — PRs to master will not be accepted.
# Fork via GitHub, then:
git clone https://github.com/<your-username>/qbit_manage.git
cd qbit_manage
git checkout developBranch from develop. Use a descriptive name:
git checkout -b fix/share-limits-edge-case
git checkout -b feat/new-tagging-optionOption A — uv (recommended, faster):
# Install uv if not already present
curl -Lsf https://astral.sh/uv/install.sh | sh
make venv # creates .venv, installs project + dev deps
source .venv/bin/activate
make install-hooks # install pre-commit hooksOption B — pip + venv:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pre-commit installuv is also kept current via Renovate (the
pep621/uv manager), so lock-file updates happen automatically.
| Target | Description |
|---|---|
make venv |
Create virtual environment and install all dependencies |
make install-hooks |
Install pre-commit hooks into your local repo |
make test |
Run the full test suite |
make lint |
Run ruff linter with auto-fix |
make format |
Run ruff code formatter |
make pre-commit |
Run all pre-commit hooks on all files |
make clean |
Remove generated files (venv, dist, build, cache) |
make help |
List all available targets |
The project uses Ruff for linting and formatting:
-
Line length: 130 characters (see
ruff.toml) - Import style: Single-line imports (isort rules enforced)
Run before committing:
ruff check --fix .
ruff format .Hooks run automatically on git commit. They enforce:
| Hook | What it does |
|---|---|
trailing-whitespace |
Strips trailing spaces |
end-of-file-fixer |
Ensures files end with a newline |
check-json / check-yaml
|
Validates JSON and YAML syntax |
yamllint + yamlfix
|
Strict YAML style lint and auto-fix |
ruff-check |
Lints Python with auto-fix |
ruff-format |
Formats Python |
check_no_tracker_secrets |
Prevents accidental commit of tracker credentials from config files |
Run all hooks manually at any time:
make pre-commit
# or directly:
pre-commit run --all-filesRun the test suite with:
pytest tests/ # full suite (~168 tests)
pytest tests/ --no-cov # quick run, skip coverage reportTest scaffolding pattern (tests/factories.py):
The factories module provides bypass-constructors that create objects without needing a live qBittorrent connection. Key helpers:
-
make_share_limits()— returns a configuredShareLimitsinstance -
make_category()— returns aCategoryinstance -
make_tag_nohardlinks()— returns aTagNoHardLinksinstance
Use these in your own test fixtures rather than instantiating core classes directly. Each factory accepts keyword arguments to override defaults, keeping tests readable and isolated.
This project follows Conventional Commits:
<type>(<scope>): <short description>
Scopes are optional but encouraged (e.g., share_limits, tags, config).
Types used in this repo (verified against git history):
| Type | When to use |
|---|---|
feat |
New feature or behavior |
fix |
Bug fix |
refactor |
Code restructuring, no behavior change |
chore |
Dependency bumps, tooling, housekeeping |
docs |
Documentation only |
test |
Adding or updating tests |
ci |
CI/CD workflow changes |
perf |
Performance improvements |
Examples from the log:
feat(tags): add support for tagging private torrents
fix(share_limits): set limits when throttle skipped
refactor(share_limits): simplify logic and reduce code duplication
chore(deps): bump ruff from 0.14.5 to 0.14.6
- Ensure
make pre-commitpasses with no errors. - Run
pytest tests/and confirm no regressions. - Push your branch and open a PR against
develop— notmaster. - Describe what your PR does and link any related issues.
- A maintainer will review; CI must be green before merge.
For the release process (merging develop → master, tagging, PyPI publish),
see DEVELOPER.md.
qbit_manage/
├── qbit_manage.py # Main entry point and CLI argument parsing
├── modules/ # Core application logic
│ ├── config.py # Config loading; check_for_attribute() calls define all valid keys
│ ├── qbittorrent.py # qBittorrent API wrapper
│ ├── util.py # Shared helpers and utilities
│ ├── webhooks.py # Webhook notification support
│ ├── web_api.py # REST API server
│ ├── web_ui.py # Web UI server
│ └── core/ # Per-feature modules
│ ├── tags.py
│ ├── share_limits.py
│ ├── category.py
│ ├── tag_nohardlinks.py
│ ├── recheck.py
│ ├── remove_orphaned.py
│ └── remove_unregistered.py
├── tests/ # Test suite
│ └── factories.py # Bypass-constructors for unit testing
├── scripts/ # Standalone helper scripts
│ └── pre-commit/ # Pre-commit hook scripts
├── web-ui/ # Web UI frontend (HTML/CSS/JS)
├── desktop/tauri/ # Tauri desktop app shell
├── docs/ # Wiki documentation (synced to GitHub Wiki)
├── config/ # Sample configuration files
├── icons/ # Application icons
├── Makefile # Development automation
├── Dockerfile # Docker build
├── pyproject.toml # Python project configuration
├── ruff.toml # Ruff linter/formatter config
└── VERSION # Single source of truth for version
-
Questions: Join the Notifiarr Discord →
#qbit-managechannel - Bugs / Enhancements: Open an Issue
- Config Questions: Start a Discussion