Contributing
Development Setup
Using Nix (Recommended)
git clone https://github.com/kartoza/geotui.git
cd geotui
nix develop
This provides all dependencies including Python 3.13, ruff, mypy, bandit, pre-commit, mkdocs, gettext, and Docker.
Using pip
git clone https://github.com/kartoza/geotui.git
cd geotui
python -m venv .venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e ".[dev,docs,i18n]"
pre-commit install
Running the Application
Development Workflow
- Create a feature branch from
main
- Write tests first (TDD approach)
- Implement the feature
- Run the test suite:
pytest
- Run linting:
ruff check src/ tests/
- Format code:
ruff format src/ tests/
- Commit with a descriptive message
- Create a pull request
Coding Standards
| Tool |
Purpose |
Configuration |
| ruff |
Linting + formatting (replaces flake8, black, isort) |
pyproject.toml [tool.ruff] |
| mypy |
Static type checking (strict mode) |
pyproject.toml [tool.mypy] |
| bandit |
Security vulnerability scanning |
pyproject.toml [tool.bandit] |
| codespell |
Spell checking in source and docs |
.pre-commit-config.yaml |
Code Conventions
- Docstrings: Google-style on all public classes and functions
- Type hints: Required on all public function signatures
- Imports: Sorted by ruff (isort-compatible)
- Line length: 88 characters (Black default)
- Coverage target: 80% minimum
- i18n: All user-facing strings wrapped in
_()
- Async: Use
async/await for I/O operations (httpx, file operations)
- DRY: Single form/UI for CRUD with mode switching (see
UnlockScreen for unlock vs setup)
Security Rules
- No
shell=True in subprocess calls
- No hardcoded credentials or secrets
- All HTTP calls use
verify=True (HTTPS enforced)
- GeoServer resource names validated against
[a-zA-Z0-9_.\-]+ regex
- Config files written with
0o600 permissions
- Pre-commit
detect-private-key hook prevents accidental key commits
Technology Stack
Runtime Libraries
| Library |
Version |
Why we use it |
| Textual |
>=1.0.0 |
TUI framework with CSS-like styling, reactive data binding, widget composition, and async event handling. Chosen for cross-platform terminal support and rich widget library. |
| Rich |
>=13.0.0 |
Terminal rendering engine used by Textual. Provides styled text, tables, progress bars, and syntax highlighting. |
| httpx |
>=0.27.0 |
Async HTTP client for GeoServer REST API calls. Chosen over requests for native async support, keeping the UI responsive during uploads. |
| Pydantic |
>=2.0.0 |
Data validation and serialisation for connection configuration. Provides type-safe models with JSON schema generation. |
| cryptography |
>=42.0.0 |
Fernet symmetric encryption (AES-128-CBC + HMAC-SHA256) with PBKDF2-HMAC-SHA256 key derivation (600k iterations) for the credential vault. |
| fpdf2 |
>=2.8.0 |
Lightweight PDF generation for publish reports. No external dependencies (pure Python). |
| Click |
>=8.0.0 |
CLI framework for headless subcommands (publish, export, import-config). |
| keyring |
>=25.0.0 |
System keyring integration (reserved for future OS-level credential storage). |
Development Libraries
| Library |
Version |
Why we use it |
| pytest |
>=8.0.0 |
Test framework with fixture injection, parametrisation, and plugin ecosystem. |
| pytest-asyncio |
>=0.24.0 |
Async test support for Textual AppTest widget testing. |
| pytest-bdd |
>=7.0.0 |
BDD testing with Gherkin feature files for user story validation. |
| pytest-cov |
>=5.0.0 |
Coverage measurement and enforcement (minimum 60%, target 80%). |
| ruff |
>=0.8.0 |
Unified Python linter and formatter. Replaces flake8+black+isort with a single Rust-based tool. |
| mypy |
>=1.0.0 |
Static type checker with strict mode enabled. |
| bandit |
>=1.7.0 |
Security-focused static analysis (OWASP patterns, injection risks). |
| Babel |
>=2.16.0 |
Translation extraction and .po/.mo file management. |
Documentation Libraries
| Library |
Version |
Why we use it |
| MkDocs |
>=1.6.0 |
Static site generator for project documentation. |
| mkdocs-material |
>=9.5.0 |
Material Design theme with Kartoza brand customisation. |
| mkdocstrings |
>=0.27.0 |
Auto-generates API reference pages from Google-style docstrings. |
Pre-commit Hooks
Pre-commit hooks run automatically on every commit:
| Hook |
Purpose |
| trailing-whitespace |
Remove trailing whitespace |
| end-of-file-fixer |
Ensure files end with newline |
| check-yaml |
Validate YAML syntax |
| check-toml |
Validate TOML syntax |
| check-json |
Validate JSON syntax |
| detect-private-key |
Prevent accidental key commits |
| check-added-large-files |
Block files > 500KB |
| ruff |
Lint Python code |
| ruff-format |
Format Python code |
| mypy |
Static type checking |
| bandit |
Security vulnerability scanning |
| codespell |
Spell checking |
| reuse |
REUSE/SPDX license compliance |
Pre-push hooks (slower checks):
| Hook |
Purpose |
| pytest |
Run full test suite |
| docs-build |
Validate mkdocs builds cleanly |
Project Structure
geotui/
├── src/geotui/ # Application source
│ ├── app.py # Main Textual App class
│ ├── cli.py # Click CLI subcommands
│ ├── client.py # GeoServer REST API client (async)
│ ├── config.py # Config, encryption, vault
│ ├── publisher.py # Bulk publish engine
│ ├── report.py # PDF/JSON report generator
│ ├── theme.py # Kartoza brand colour theme
│ ├── screens/ # Modal screen components
│ ├── widgets/ # TUI widget components
│ ├── styles/ # Textual CSS styles
│ └── i18n/ # Translations (.pot/.po/.mo)
├── tests/ # Test suite
│ ├── unit/ # Unit tests
│ └── bdd/ # BDD feature tests
├── docs/ # MkDocs documentation
├── resources/ # Test data and resources
├── scripts/ # Build and utility scripts
├── .github/workflows/ # CI/CD pipelines
├── flake.nix # Nix development environment
├── pyproject.toml # Python project configuration
└── docker-compose.yml # Local GeoServer for testing
Local GeoServer for Testing
A Docker Compose file is provided for running a local GeoServer:
This starts a GeoServer instance at http://localhost:8080/geoserver with default credentials (admin/geoserver).
Building Documentation
cd docs
mkdocs serve # Live preview at http://localhost:8000
mkdocs build # Build static site
Versioning
- Version is maintained in
pyproject.toml and src/geotui/__init__.py
- Bug fixes increment the patch version
- New features increment the minor version
- Breaking changes increment the major version
Made with
by Kartoza | Donate! | GitHub