Contributing¶
Development Setup¶
# Clone the repository
git clone https://github.com/shahadh7/adbflow.git
cd adbflow
# Create virtual environment
python -m venv .venv
source .venv/bin/activate
# Install with dev dependencies
pip install -e ".[all,dev]"
Running Tests¶
# All tests
pytest
# Unit tests only
pytest tests/unit/
# Single test
pytest tests/unit/test_foo.py::test_bar
# Stop on first failure
pytest -x
# Verbose output
pytest -v
Tests use pytest-asyncio with asyncio_mode = "auto", so async test functions are automatically detected.
Linting¶
Ruff is configured with target-version = "py310" and line-length = 100.
Type Checking¶
The project uses mypy --strict. All public APIs must have complete type annotations.
Code Style¶
- Async-first: all I/O methods are
asyncwith_asyncsuffix; sync wrappers useasyncio.run() - Type hints: required on all public APIs, using Python 3.10+ syntax (
X | Y,ParamSpec,TypeAlias) - Docstrings: Google-style on all public APIs
- Line length: 100 characters
- Imports: sorted by ruff
Project Structure¶
src/adbflow/
├── core/ # Transport, ADB binary, connection
├── device/ # Device info, properties, power, settings
├── ui/ # UI hierarchy, selectors, elements
├── gestures/ # Touch input
├── wait/ # Conditions, combinators, polling
├── vision/ # Template matching, color detection
├── ocr/ # Text recognition
├── files/ # File operations, sync, watcher
├── apps/ # App management, intents, permissions
├── media/ # Screenshots, recording, audio
├── logcat/ # Log streaming and capture
├── network/ # Network controls
├── notifications/ # Notification access
├── accessibility/ # Accessibility services
├── watchers/ # Background UI monitors
├── recorder/ # Action recording and playback
├── parallel/ # Multi-device pool
├── flow/ # Workflow engine
├── utils/ # Types, exceptions, geometry, retry
└── cli/ # Command-line interface
Key Design Rules¶
- All ADB I/O goes through
SubprocessTransport— never usesubprocessdirectly - Device is the central object — sub-modules attach as lazy
cached_property - UI selectors are lazy — no queries until interaction
- UI hierarchy is cached (2s TTL), invalidated after interactions
- Optional heavy deps behind extras:
[vision]for opencv,[ocr]for easyocr