Locus Quarter automates property-feed analysis by combining:
- RSS listing intake.
- Nearby place discovery (Google Places).
- Commute-time scoring (Google Distance Matrix).
- Optional Gmail report delivery.
The project is now modernized for Python 3.11+, typed modular code, CI quality gates, and deterministic tests.
- Python 3.11 or newer.
- A Google Maps API key.
- Optional: Gmail API credentials for email delivery.
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e ".[dev]"export LQ_GOOGLE_MAPS_API_KEY="..."
export LQ_GMAIL_CLIENT_SECRET_FILE="/absolute/path/client_secret.json" # optional
export LQ_RECEIVER_MAIL_ADDRESS="to@example.com" # optional
export LQ_SENDER_MAIL_ADDRESS="from@example.com" # optionalpython locus_quarter.pySingle address mode:
python locus_quarter.py --address "Henriette Bosmanslaan 2, 1187 HH Amstelveen, Netherlands"JSON output:
python locus_quarter.py --format jsonNo artifact files:
python locus_quarter.py --no-save-artifactsEmail on:
python locus_quarter.py --email| Option | Description | Default |
|---|---|---|
--address |
Analyze one address instead of RSS feeds | None |
--config |
Config INI path | config-locus-quarter.ini |
--email/--no-email |
Send report via Gmail | --no-email |
--format text|json |
Console output format | text |
--output-dir |
Directory for run artifacts (.json + .txt) |
reports |
--save-artifacts/--no-save-artifacts |
Toggle artifact persistence | --save-artifacts |
--trigger |
Trigger label for run metadata (manual, cron, etc.) |
manual |
--print-metrics/--no-print-metrics |
Log run counters and duration | --print-metrics |
All list fields use Python list literal syntax in INI files.
| Key | Type | Required | Notes |
|---|---|---|---|
g_list_of_regions_urls |
list[str] |
yes | RSS feed URLs (HTTPS recommended) |
g_list_nearby_types_of_places |
list[str] |
yes | Google supported place types |
g_travel_mode |
list[str] |
yes | e.g. walking, bicycling, driving, transit |
g_limit_houses |
int |
yes | Max houses per feed |
g_limit_search_places_nearby |
int |
yes | Max places per type |
g_office_addresses |
list[str] |
no | Destination addresses for commute scoring |
g_office_travel_mode |
list[str] |
no | Travel modes for office commute |
| Key | Type | Required | Notes |
|---|---|---|---|
g_google_maps_client_api_key |
str |
yes | Use env:LQ_GOOGLE_MAPS_API_KEY |
| Key | Type | Required | Notes |
|---|---|---|---|
g_gmail_secrets_path |
str |
no | Token storage dir |
g_gmail_secret_json |
str |
no | Token filename |
g_gmail_action_scope |
str |
no | Comma-separated scopes |
g_gmail_client_secret_file |
str |
optional | Use env:LQ_GMAIL_CLIENT_SECRET_FILE |
g_gmail_google_developer_application_name |
str |
no | App display name |
g_receiver_mail_address |
str |
optional | Use env:LQ_RECEIVER_MAIL_ADDRESS |
g_sender_mail_address |
str |
optional | Use env:LQ_SENDER_MAIL_ADDRESS |
g_email_subject |
str |
no | Subject line |
Each run can emit:
reports/<run_id>.txttext report.reports/<run_id>.jsonstructured payload.
JSON includes:
mode(feedoraddress)trigger(manual,cron, etc.)records(per-house details)metrics(feed/geocode/places/distance calls, warnings/errors, duration)
Run all tests:
pytestRun lint/type checks:
ruff check .
ruff format --check .
mypy src locus_quarter.pySecurity and dependency checks:
detect-secrets scan --baseline .secrets.baseline
pip-auditMutation checks:
mutmut run | tee mutmut-run.log
python scripts/check_mutation_score.py --log-file mutmut-run.logCoverage gates:
pytest -q --cov=src/locus_quarter_app --cov-branch --cov-report=xml
python scripts/check_coverage_gates.py --min-statement 90 --min-branch 80Cron-friendly wrapper:
locus-quarter-scheduledEnvironment knobs:
LQ_CONFIG_PATH(defaultconfig-locus-quarter.ini)LQ_OUTPUT_DIR(defaultreports)
--email=trueis replaced by--email(and disable via--no-email).- Prefer
--format jsoninstead of parsing free-form text. - API keys/emails should come from env vars, not committed secrets.
- Legacy one-file implementation is replaced by
src/locus_quarter_app/*;locus_quarter.pyis now a compatibility wrapper.
-
Configuration error: Missing required configurationSetLQ_GOOGLE_MAPS_API_KEYor configureg_google_maps_client_api_key. -
Gmail auth prompt keeps appearing Confirm token file path (
g_gmail_secrets_path+g_gmail_secret_json) and client secret path. -
Empty or missing distance fields This can happen for unsupported route/mode combinations from Google API.
-
RSS yields no houses Verify feed URLs and configured locality/price filters.
MIT (see LICENSE).