|
| 1 | +### Contributing to PythonNative |
| 2 | + |
| 3 | +Thanks for your interest in contributing. This repository contains the PythonNative library, CLI, templates, a demo app, and a Django site used for docs/demo hosting and E2E. Contributions should keep the code reliable, cross‑platform, and easy to use. |
| 4 | + |
| 5 | +## Quick start |
| 6 | + |
| 7 | +Development uses Python ≥ 3.9. |
| 8 | + |
| 9 | +```bash |
| 10 | +# create and activate a venv (recommended) |
| 11 | +python3 -m venv .venv && source .venv/bin/activate |
| 12 | + |
| 13 | +# install root tooling (lint/format/test) |
| 14 | +pip install -r requirements.txt |
| 15 | + |
| 16 | +# install library (editable) and CLI |
| 17 | +pip install -e libs/pythonnative |
| 18 | + |
| 19 | +# run tests |
| 20 | +pytest -q |
| 21 | + |
| 22 | +# format and lint |
| 23 | +black libs apps tests || true |
| 24 | +ruff check . |
| 25 | +``` |
| 26 | + |
| 27 | +Common library and CLI entry points: |
| 28 | + |
| 29 | +```bash |
| 30 | +# CLI help |
| 31 | +pn --help |
| 32 | + |
| 33 | +# create a new sample app (template fetch is remote) |
| 34 | +pn init my_app |
| 35 | + |
| 36 | +# run a local demo app skeleton |
| 37 | +cd apps/pythonnative_demo && pn run android |
| 38 | +``` |
| 39 | + |
| 40 | +## Project layout (high‑level) |
| 41 | + |
| 42 | +- `libs/pythonnative/` – installable library and CLI |
| 43 | + - `pythonnative/` – core cross‑platform UI components and utilities |
| 44 | + - `cli/` – `pn` command |
| 45 | + - `tests/` – unit tests for the library |
| 46 | +- `libs/templates/` – Android/iOS project templates and zips |
| 47 | +- `apps/` – application projects |
| 48 | + - `django_pythonnative/` – Django project for docs/demo hosting and E2E |
| 49 | + - `experiments/` – platform experiments (Android/iOS/Briefcase) |
| 50 | + - `pythonnative_demo/` – minimal demo app using the library |
| 51 | +- `README.md`, `requirements.txt` – repo docs and dev tooling |
| 52 | + |
| 53 | +## Coding guidelines |
| 54 | + |
| 55 | +- Style: Black; lint: Ruff; typing where useful. Keep APIs stable. |
| 56 | +- Prefer explicit, descriptive names; keep platform abstractions clean. |
| 57 | +- Add/extend tests under `libs/pythonnative/tests/` for new behavior. |
| 58 | +- Do not commit generated artifacts or large binaries; templates live under `libs/templates/`. |
| 59 | + |
| 60 | +Common commands: |
| 61 | + |
| 62 | +```bash |
| 63 | +pytest -q # run tests |
| 64 | +ruff check . # lint |
| 65 | +black libs apps # format |
| 66 | +``` |
| 67 | + |
| 68 | +## Conventional Commits |
| 69 | + |
| 70 | +This project uses Conventional Commits. Use the form: |
| 71 | + |
| 72 | +``` |
| 73 | +<type>(<scope>): <subject> |
| 74 | +
|
| 75 | +[optional body] |
| 76 | +
|
| 77 | +[optional footer(s)] |
| 78 | +``` |
| 79 | + |
| 80 | +### Commit message character set |
| 81 | + |
| 82 | +- Encoding: UTF‑8 is allowed and preferred across subjects and bodies. |
| 83 | +- Keep the subject ≤ 72 chars; avoid emoji. |
| 84 | + |
| 85 | +Accepted types (standard): |
| 86 | + |
| 87 | +- `build` – build system or external dependencies (e.g., requirements, packaging) |
| 88 | +- `chore` – maintenance (no library behavior change) |
| 89 | +- `ci` – continuous integration configuration (workflows, pipelines) |
| 90 | +- `docs` – documentation only |
| 91 | +- `feat` – user‑facing feature or capability |
| 92 | +- `fix` – bug fix |
| 93 | +- `perf` – performance improvements |
| 94 | +- `refactor` – code change that neither fixes a bug nor adds a feature |
| 95 | +- `revert` – revert of a previous commit |
| 96 | +- `style` – formatting/whitespace (no code behavior) |
| 97 | +- `test` – add/adjust tests only |
| 98 | + |
| 99 | +Recommended scopes (match the smallest accurate directory/module): |
| 100 | + |
| 101 | +- Library/CLI scopes: |
| 102 | + - `cli` – `libs/pythonnative/cli/` (the `pn` command) |
| 103 | + - `core` – `libs/pythonnative/pythonnative/` package internals |
| 104 | + - `components` – UI view modules under `libs/pythonnative/pythonnative/` (e.g., `button.py`, `label.py`) |
| 105 | + - `utils` – utilities like `utils.py` |
| 106 | + - `tests` – `libs/pythonnative/tests/` |
| 107 | + |
| 108 | +- Templates and examples: |
| 109 | + - `templates` – `libs/templates/` (Android/iOS templates, zips) |
| 110 | + - `demo` – `apps/pythonnative_demo/` |
| 111 | + - `experiments` – `apps/experiments/` |
| 112 | + |
| 113 | +- Django app and site: |
| 114 | + - `django` – `apps/django_pythonnative/` (site, docs pages, E2E harness) |
| 115 | + |
| 116 | +- Repo‑level and ops: |
| 117 | + - `deps` – dependency updates and version pins |
| 118 | + - `docker` – containerization files (e.g., `Dockerfile`) |
| 119 | + - `repo` – top‑level files (`README.md`, `CONTRIBUTING.md`, `.gitignore`, licenses) |
| 120 | + - `workflows` – CI pipelines (e.g., `.github/workflows/`) |
| 121 | + |
| 122 | +Note: Avoid redundant type==scope pairs (e.g., `docs(docs)`). Prefer a module scope (e.g., `docs(core)`) or `docs(repo)` for top‑level updates. |
| 123 | + |
| 124 | +Examples: |
| 125 | + |
| 126 | +```text |
| 127 | +build(deps): refresh pinned versions |
| 128 | +chore(repo): add contributing guidelines |
| 129 | +ci(workflows): add publish job |
| 130 | +docs(core): clarify ListView data contract |
| 131 | +feat(components): add MaterialSearchBar |
| 132 | +fix(cli): handle missing Android SDK gracefully |
| 133 | +perf(core): reduce allocations in list diffing |
| 134 | +refactor(utils): extract path helpers |
| 135 | +test(tests): cover ios template copy flow |
| 136 | +``` |
| 137 | + |
| 138 | +Examples (no scope): |
| 139 | + |
| 140 | +```text |
| 141 | +build: update packaging metadata |
| 142 | +chore: update .gitignore patterns |
| 143 | +docs: add project overview |
| 144 | +``` |
| 145 | + |
| 146 | +Breaking changes: |
| 147 | + |
| 148 | +- Use `!` after the type/scope or a `BREAKING CHANGE:` footer. |
| 149 | + |
| 150 | +```text |
| 151 | +feat(core)!: rename Page.set_root_view to set_root |
| 152 | +
|
| 153 | +BREAKING CHANGE: API renamed; update app code and templates. |
| 154 | +``` |
| 155 | + |
| 156 | +### Multiple scopes (optional) |
| 157 | + |
| 158 | +- Comma‑separate scopes without spaces: `type(scope1,scope2): ...` |
| 159 | +- Prefer a single scope when possible; use multiple only when the change genuinely spans tightly related areas. |
| 160 | + |
| 161 | +Example: |
| 162 | + |
| 163 | +```text |
| 164 | +feat(templates,cli): add ios template and wire pn init |
| 165 | +``` |
| 166 | + |
| 167 | +## Pull requests and squash merges |
| 168 | + |
| 169 | +- PR title: use Conventional Commit format. |
| 170 | + - Example: `feat(cli): add init subcommand` |
| 171 | + - Imperative mood; no trailing period; ≤ 72 chars; `!` for breaking changes. |
| 172 | +- PR description: include brief sections: What, Why, How (brief), Testing, Risks/Impact, Docs/Follow‑ups. |
| 173 | + - Link issues with keywords (e.g., `Closes #123`). |
| 174 | +- Merging: prefer “Squash and merge” with “Pull request title and description”. |
| 175 | +- Keep PRs focused; avoid unrelated changes in the same PR. |
| 176 | + |
| 177 | +Recommended PR template: |
| 178 | + |
| 179 | +```text |
| 180 | +What |
| 181 | +- Short summary of the change |
| 182 | +
|
| 183 | +Why |
| 184 | +- Motivation/user value |
| 185 | +
|
| 186 | +How (brief) |
| 187 | +- Key implementation notes or decisions |
| 188 | +
|
| 189 | +Testing |
| 190 | +- Local/CI coverage; links to tests if relevant |
| 191 | +
|
| 192 | +Risks/Impact |
| 193 | +- Compat, rollout, perf, security; mitigations |
| 194 | +
|
| 195 | +Docs/Follow-ups |
| 196 | +- Docs updated or TODO next steps |
| 197 | +
|
| 198 | +Closes #123 |
| 199 | +BREAKING CHANGE: <details if any> |
| 200 | +Co-authored-by: Name <email> |
| 201 | +``` |
| 202 | + |
| 203 | +## Pull request checklist |
| 204 | + |
| 205 | +- Tests: added/updated; `pytest` passes. |
| 206 | +- Lint/format: `ruff check .`, `black` pass. |
| 207 | +- Docs: update `README.md` and any Django docs pages if behavior changes. |
| 208 | +- Templates: update `libs/templates/` if generator output changes. |
| 209 | +- No generated artifacts committed. |
| 210 | + |
| 211 | +## Versioning and releases |
| 212 | + |
| 213 | +- The library version is tracked in `libs/pythonnative/setup.py`. Use SemVer. |
| 214 | +- Workflow: |
| 215 | + - Contributors: branch off `main` (or `dev` if used) and open PRs. |
| 216 | + - Maintainer (release): bump version, tag, and publish to PyPI. |
| 217 | + - Tag on `main`: `git tag -a vX.Y.Z -m "Release vX.Y.Z" && git push --tags`. |
| 218 | + |
| 219 | +### Branch naming (suggested) |
| 220 | + |
| 221 | +- Use lowercase kebab‑case; concise (≤ 40 chars). |
| 222 | +- Prefix conventions: |
| 223 | + - `feature/<scope>-<short-desc>` |
| 224 | + - `fix/<issue-or-bug>-<short-desc>` |
| 225 | + - `chore/<short-desc>` |
| 226 | + - `docs/<short-desc>` |
| 227 | + - `ci/<short-desc>` |
| 228 | + - `refactor/<scope>-<short-desc>` |
| 229 | + - `test/<short-desc>` |
| 230 | + - `perf/<short-desc>` |
| 231 | + - `build/<short-desc>` |
| 232 | + - `release/vX.Y.Z` |
| 233 | + - `hotfix/<short-desc>` |
| 234 | + |
| 235 | +Examples: |
| 236 | + |
| 237 | +```text |
| 238 | +feature/cli-init |
| 239 | +fix/core-threading-deadlock-123 |
| 240 | +docs/contributing |
| 241 | +ci/publish-pypi |
| 242 | +build/lock-versions |
| 243 | +refactor/utils-paths |
| 244 | +test/templates-android |
| 245 | +release/v0.2.0 |
| 246 | +hotfix/cli-regression |
| 247 | +``` |
| 248 | + |
| 249 | +## Security and provenance |
| 250 | + |
| 251 | +- Avoid bundling secrets or credentials in templates or code. |
| 252 | +- Prefer runtime configuration via environment variables for Django and CI. |
| 253 | + |
| 254 | +## License |
| 255 | + |
| 256 | +By contributing, you agree that your contributions are licensed under the repository’s MIT License. |
0 commit comments