Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions GUARDRAILS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# GUARDRAILS.md — RyanData-Address-Utils
<!-- Version: 1.0.0 | Maintainer: John Eakin -->
Comment on lines +1 to +2
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title references adding AGENTS.md and companion templates, but the provided diff only adds TESTING.md/RUNBOOK.md/GUARDRAILS.md. Please align the PR title/description with the actual changes (or include the missing files) so reviewers know what to expect.

Copilot uses AI. Check for mistakes.

## Always

- Add type hints to all function signatures
- Format with `ruff format` before committing
- Write or update tests for every code change
- Use structured logging (`logging` module) — never `print()`
- Raise domain errors (`RyanDataAddressError`, `RyanDataValidationError`)

## Ask First

- Adding a new package dependency
- Changing a Pydantic model field (may break downstream consumers)
- Changing the public API in `__init__.py`
- Altering shapefile schema or PISD boundary logic

## Never

- Store secrets, tokens, or credentials in source code
- Use bare `except:` without specifying the exception type
- Commit `.env` files or production data files
- Use `print()` as a substitute for logging
- Access `src/pisd_shape/data/` files outside the `pisd_shape` module

## Data Sensitivity

- Voter file data and shapefiles are **not** committed to git
- Test fixtures use synthetic or publicly available data only
- Production data paths are configured via environment variables
58 changes: 58 additions & 0 deletions RUNBOOK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# RUNBOOK.md — RyanData-Address-Utils
<!-- Version: 1.0.0 | Maintainer: John Eakin -->

## Setup

```bash
git clone <repo>
cd RyanData-Address-Utils
uv sync
uv run pytest # verify install
```

## Common Operations

### Parse a batch of addresses

```python
from ryandata_address_utils import AddressService
service = AddressService()
result = service.parse("123 Main St, Plano TX 75023")
```

### Parse a DataFrame column

```python
df = service.parse_dataframe(df, address_col="RES_STREET", prefix="addr_")
```

### Run PISD shapefile extraction

```bash
cd src/pisd_shape
uv run python -m pisd_shape.main
```

## Linting & Formatting

```bash
uv run ruff check src tests # lint
uv run ruff format src tests # format
uv run mypy src # type check
```

## Dependency Updates

```bash
uv lock --upgrade # update lock file
uv sync # reinstall
uv run pytest # verify nothing broke
```

## Troubleshooting

| Symptom | Fix |
|---------|-----|
| `ModuleNotFoundError` | Run `uv sync` |
Comment on lines +54 to +56
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The troubleshooting table isn't valid Markdown because of the double leading pipes (|| ...). This won’t render as a table in most viewers; switch to standard table syntax (| header row + separator row) so it formats correctly on GitHub.

Copilot uses AI. Check for mistakes.
| Parser returns `None` | Check address format; try `usaddress` backend |
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The symptom/diagnostic here is misleading: AddressService.parse() returns a ParseResult, not None, and the default parser type is already "usaddress" (ParserFactory default). Consider updating this row to describe the actual failure mode (e.g., result.is_parsed false / result.is_valid false) and the recommended next step.

Suggested change
| Parser returns `None` | Check address format; try `usaddress` backend |
| `AddressService.parse()` returns a `ParseResult` with `result.is_parsed` or `result.is_valid` set to `False` | Check address format and clean up input; inspect parse errors and adjust or retry with a different parser backend if available |

Copilot uses AI. Check for mistakes.
| Shapefile import fails | Ensure `geopandas` extras installed: `uv sync --extra geo` |
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uv sync --extra geo won't work as written because pyproject.toml currently defines only the pandas optional dependency group (no geo extra). Either add a geo extra (e.g., geopandas-related deps) or update the runbook to use an existing option such as --extra pandas or --all-extras.

Suggested change
| Shapefile import fails | Ensure `geopandas` extras installed: `uv sync --extra geo` |
| Shapefile import fails | Ensure `geopandas` extras installed: `uv sync --extra pandas` |

Copilot uses AI. Check for mistakes.
42 changes: 42 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# TESTING.md — RyanData-Address-Utils
<!-- Version: 1.0.0 | Maintainer: John Eakin -->

## Framework

- **Runner:** pytest
- **Property-based:** Hypothesis
- **Coverage target:** 80%+ (src/)

## Commands

```bash
uv run pytest # all tests
uv run pytest --cov=src # with coverage
uv run pytest -x # stop on first failure
uv run pytest -k "test_parse" # filter by name
uv run pytest tests/unit/ # unit tests only
uv run pytest tests/property/ # Hypothesis tests only
Comment on lines +8 to +18
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coverage command here (--cov=src) doesn't match CI, which runs pytest with --cov=src/ryandata_address_utils (see .github/workflows/tests.yml). Using the package path keeps local docs consistent with what CI reports.

Suggested change
- **Coverage target:** 80%+ (src/)
## Commands
```bash
uv run pytest # all tests
uv run pytest --cov=src # with coverage
uv run pytest -x # stop on first failure
uv run pytest -k "test_parse" # filter by name
uv run pytest tests/unit/ # unit tests only
uv run pytest tests/property/ # Hypothesis tests only
- **Coverage target:** 80%+ (src/ryandata_address_utils)
## Commands
```bash
uv run pytest # all tests
uv run pytest --cov=src/ryandata_address_utils # with coverage
uv run pytest -x # stop on first failure
uv run pytest -k "test_parse" # filter by name
uv run pytest tests/unit/ # unit tests only
uv run pytest tests/property/ # Hypothesis tests only

Copilot uses AI. Check for mistakes.
```

## Test Layout

```
tests/
├── unit/ # Pure unit tests — no I/O, no network
├── integration/ # Tests that hit the filesystem or pandas
├── property/ # Hypothesis property-based tests
└── conftest.py # Shared fixtures
```
Comment on lines +17 to +29
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These commands and the test tree below assume tests/unit/, tests/integration/, and tests/property/, but the current repo uses a flat tests/ layout (e.g., tests/test_*.py plus tests/strategies.py). Please update the suggested commands/layout to match the actual structure so the instructions work as written.

Copilot uses AI. Check for mistakes.

## Test Standards

- Every public function has at least one unit test
- Parsers and validators get Hypothesis `@given` tests
- Fixtures live in `conftest.py`, not in test files
- No `print()` — use `caplog` or `capsys`
- Mock external I/O at the boundary (file reads, HTTP)

## CI

Tests run automatically on every PR via GitHub Actions.
All checks must pass before merge.
Loading