Skip to content

Commit e1567c8

Browse files
authored
Merge pull request #3 from tldrwtf/feature/tests
Feature/tests
2 parents 2861447 + 09a8f29 commit e1567c8

29 files changed

+1204
-607
lines changed

.github/workflows/ci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main, feature/** ]
6+
pull_request:
7+
branches: [ main, feature/** ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Set up Python
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: "3.11"
20+
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install -e ".[dev]"
25+
26+
- name: Lint
27+
run: |
28+
ruff check .
29+
black --check .
30+
isort --check-only .
31+
32+
- name: Run tests
33+
run: |
34+
pytest

docs/CONTRIBUTING.md

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,35 @@
2222
### Installation
2323

2424
1. Clone the repository:
25-
```bash
26-
git clone https://github.com/tldrwtf/pokedo.git
27-
cd pokedo
28-
```
2925

30-
2. Create a virtual environment:
31-
```bash
32-
python -m venv venv
26+
```bash
27+
git clone https://github.com/tldrwtf/pokedo.git
28+
cd pokedo
29+
```
3330

34-
# Windows
35-
venv\Scripts\activate
31+
1. Create a virtual environment:
3632

37-
# macOS/Linux
38-
source venv/bin/activate
39-
```
33+
```bash
34+
python -m venv venv
4035
41-
3. Install development dependencies:
42-
```bash
43-
pip install -e ".[dev]"
44-
```
36+
# Windows
37+
venv\Scripts\activate
4538
46-
4. Initialize the application (for testing):
47-
```bash
48-
pokedo init --name "Developer" --quick
49-
```
39+
# macOS/Linux
40+
source venv/bin/activate
41+
```
42+
43+
1. Install development dependencies (formatter, linter, tests):
44+
45+
```bash
46+
pip install -e ".[dev]"
47+
```
48+
49+
1. Initialize the application (for testing):
50+
51+
```bash
52+
pokedo init --name "Developer" --quick
53+
```
5054

5155
### Development Commands
5256

@@ -68,13 +72,22 @@ pytest tests/test_tasks.py
6872
6973
# Run with verbose output
7074
pytest -v
75+
76+
# Format code (Black)
77+
black .
78+
79+
# Sort imports (isort profile=black)
80+
isort .
81+
82+
# Lint (Ruff)
83+
ruff check .
7184
```
7285

7386
---
7487

7588
## Project Structure
7689

77-
```
90+
```text
7891
pokedo/
7992
├── cli/ # Command-line interface
8093
│ ├── app.py # Main Typer application
@@ -213,7 +226,7 @@ def safe_operation() -> None:
213226
214227
### Test Structure
215228
216-
```
229+
```text
217230
tests/
218231
├── __init__.py
219232
├── conftest.py # Shared fixtures
@@ -334,7 +347,7 @@ def new_command(
334347
console.print(f"Running with {arg}")
335348
```
336349
337-
2. Register in `cli/app.py`:
350+
1. Register in `cli/app.py`:
338351
339352
```python
340353
from pokedo.cli.commands import example
@@ -357,7 +370,7 @@ class NewModel(BaseModel):
357370
created_at: datetime = Field(default_factory=datetime.now)
358371
```
359372
360-
2. Add database operations in `data/database.py`:
373+
1. Add database operations in `data/database.py`:
361374
362375
```python
363376
def create_new_model_table(self) -> None:
@@ -390,9 +403,9 @@ class NewWellbeingEntry(BaseModel):
390403
note: str | None = None
391404
```
392405
393-
2. Add database table in `data/database.py`
406+
1. Add database table in `data/database.py`
394407
395-
3. Add CLI command in `cli/commands/wellbeing.py`:
408+
1. Add CLI command in `cli/commands/wellbeing.py`:
396409
397410
```python
398411
@app.command()
@@ -427,7 +440,7 @@ def new_tracker(
427440
428441
### Branch Naming
429442
430-
```
443+
```text
431444
feature/add-trading-system
432445
bugfix/fix-evolution-crash
433446
docs/update-readme
@@ -438,7 +451,7 @@ refactor/simplify-catch-rate
438451
439452
Follow conventional commit format:
440453
441-
```
454+
```text
442455
feat: add Pokemon trading system
443456
fix: resolve crash when evolving shiny Pokemon
444457
docs: update installation instructions

docs/TROUBLESHOOTING.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Troubleshooting Guide
2+
3+
Common issues and their fixes while working on PokeDo.
4+
5+
## Environment Setup
6+
7+
### Missing Dependencies
8+
9+
- **Symptom:** `ModuleNotFoundError` when running the CLI or tests.
10+
- **Fix:** Ensure the virtual environment is active and run `pip install -e ".[dev]"`.
11+
12+
### Database Permission Errors
13+
14+
- **Symptom:** `sqlite3.OperationalError: unable to open database file`.
15+
- **Fix:** Delete `~/.pokedo/pokedo.db` and rerun `pokedo init`. Confirm you have write access to the directory.
16+
17+
## CLI Issues
18+
19+
### Typer Option Errors
20+
21+
- **Symptom:** `No such option` or `OptionInfo` type errors when calling shortcuts.
22+
- **Fix:** Use the namespaced command (`pokedo pokemon pokedex`) when you need advanced options. Shortcuts are guarded wrappers and may have fewer flags.
23+
24+
### Pokedex Empty After Init
25+
26+
- **Symptom:** `pokedo pokedex` shows empty data even after initializing.
27+
- **Fix:** Run `pokedo init --quick` again; ensure the PokeAPI requests succeeded and check for networking issues.
28+
29+
## Testing Problems
30+
31+
### Pytest Missing
32+
33+
- **Symptom:** `No module named pytest`.
34+
- **Fix:** Install dev dependencies (`pip install -e ".[dev]"`) and rerun tests.
35+
36+
### Database Tests Interfering with Local Data
37+
38+
- **Symptom:** Tests modify your real `~/.pokedo` database.
39+
- **Fix:** Use the `isolated_db` fixture from `tests/conftest.py` and avoid importing the global `db` outside fixtures in tests.
40+
41+
## Pydantic Model Errors
42+
43+
### FieldInfo clashes
44+
45+
- **Symptom:** `PydanticUserError: Error when building FieldInfo from annotated attribute`.
46+
- **Fix:** Ensure datetime/date fields use module-qualified names (`import datetime as dt`) or callable factories (e.g., `Field(default_factory=dt.date.today)`). Clear `__pycache__` if errors persist.
47+
48+
## Logging and Debugging Tips
49+
50+
- Set `POKEDO_DEBUG=1` (if implemented) or instrument CLI commands with temporary prints to trace logic.
51+
- Clear caches in `~/.pokedo/cache` if sprite downloads or API responses look stale.
52+
53+
## Getting Support
54+
55+
- Re-read `docs/CONTRIBUTING.md` for setup steps.
56+
- Check open issues in the repository for similar problems.
57+
- When filing a new issue, include OS, Python version, and exact command output.

pokedo/cli/app.py

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
"""Main CLI application for PokeDo."""
22

33
import typer
4+
from rich import box
45
from rich.console import Console
56
from rich.panel import Panel
6-
from rich import box
77

88
from pokedo import __version__
9-
from pokedo.cli.commands import tasks, pokemon, wellbeing, stats
9+
from pokedo.cli.commands import pokemon, stats, tasks, wellbeing
1010
from pokedo.data.database import db
11-
from pokedo.cli.ui.displays import display_trainer_card
1211

1312
# Create main app
1413
app = typer.Typer(
1514
name="pokedo",
1615
help="PokeDo - A Pokemon-themed task manager and wellbeing tracker",
17-
no_args_is_help=False
16+
no_args_is_help=False,
1817
)
1918

2019
# Register sub-commands
@@ -29,8 +28,7 @@
2928
# Direct commands (shortcuts)
3029
@app.command("mood")
3130
def mood_shortcut(
32-
level: int = typer.Argument(..., min=1, max=5),
33-
note: str = typer.Option(None, "--note", "-n")
31+
level: int = typer.Argument(..., min=1, max=5), note: str = typer.Option(None, "--note", "-n")
3432
) -> None:
3533
"""Quick mood log (1-5)."""
3634
wellbeing.log_mood(level, note, None)
@@ -40,7 +38,7 @@ def mood_shortcut(
4038
def exercise_shortcut(
4139
exercise_type: wellbeing.ExerciseType = typer.Argument(...),
4240
duration: int = typer.Option(..., "--duration", "-d"),
43-
intensity: int = typer.Option(3, "--intensity", "-i", min=1, max=5)
41+
intensity: int = typer.Option(3, "--intensity", "-i", min=1, max=5),
4442
) -> None:
4543
"""Quick exercise log."""
4644
wellbeing.log_exercise(exercise_type, duration, intensity, None)
@@ -49,24 +47,20 @@ def exercise_shortcut(
4947
@app.command("sleep")
5048
def sleep_shortcut(
5149
hours: float = typer.Argument(...),
52-
quality: int = typer.Option(3, "--quality", "-q", min=1, max=5)
50+
quality: int = typer.Option(3, "--quality", "-q", min=1, max=5),
5351
) -> None:
5452
"""Quick sleep log."""
5553
wellbeing.log_sleep(hours, quality, None)
5654

5755

5856
@app.command("water")
59-
def water_shortcut(
60-
glasses: int = typer.Option(1, "--glasses", "-g")
61-
) -> None:
57+
def water_shortcut(glasses: int = typer.Option(1, "--glasses", "-g")) -> None:
6258
"""Quick water log."""
6359
wellbeing.log_hydration(glasses, None)
6460

6561

6662
@app.command("meditate")
67-
def meditate_shortcut(
68-
minutes: int = typer.Argument(...)
69-
) -> None:
63+
def meditate_shortcut(minutes: int = typer.Argument(...)) -> None:
7064
"""Quick meditation log."""
7165
wellbeing.log_meditation(minutes, None)
7266

@@ -117,12 +111,13 @@ def show_version() -> None:
117111
def initialize(
118112
name: str = typer.Option("Trainer", "--name", "-n", help="Your trainer name"),
119113
quick: bool = typer.Option(False, "--quick", "-q", help="Quick init (Gen 1 only)"),
120-
gen: int = typer.Option(0, "--gen", "-g", help="Initialize specific generation (1-9, 0=all)")
114+
gen: int = typer.Option(0, "--gen", "-g", help="Initialize specific generation (1-9, 0=all)"),
121115
) -> None:
122116
"""Initialize PokeDo and create trainer profile."""
123-
from pokedo.utils.config import config
124117
import asyncio
118+
125119
from pokedo.data.pokeapi import pokeapi
120+
from pokedo.utils.config import config
126121

127122
console.print("[bold]Welcome to PokeDo![/bold]")
128123
console.print("Initializing your Pokemon journey...\n")
@@ -132,7 +127,7 @@ def initialize(
132127
console.print("[green]+ Created data directories[/green]")
133128

134129
# Initialize database
135-
trainer = db.get_or_create_trainer(name)
130+
db.get_or_create_trainer(name)
136131
console.print(f"[green]+ Created trainer profile: {name}[/green]")
137132

138133
# Determine range to initialize
@@ -191,10 +186,7 @@ def show_dashboard() -> None:
191186

192187
# Header
193188
console.print()
194-
console.print(Panel(
195-
f"[bold]PokeDo[/bold] - {trainer.name}'s Journey",
196-
box=box.DOUBLE
197-
))
189+
console.print(Panel(f"[bold]PokeDo[/bold] - {trainer.name}'s Journey", box=box.DOUBLE))
198190

199191
# Quick stats
200192
today = date.today()
@@ -212,10 +204,9 @@ def show_dashboard() -> None:
212204

213205
# Team preview
214206
if team:
215-
team_str = " | ".join([
216-
f"{p.display_name} Lv.{p.level}" + (" *" if p.is_shiny else "")
217-
for p in team[:3]
218-
])
207+
team_str = " | ".join(
208+
[f"{p.display_name} Lv.{p.level}" + (" *" if p.is_shiny else "") for p in team[:3]]
209+
)
219210
console.print(f"\n[dim]Team:[/dim] {team_str}")
220211

221212
# Today's tasks
@@ -230,7 +221,9 @@ def show_dashboard() -> None:
230221
console.print("\n[green]All tasks completed![/green]")
231222

232223
# Commands hint
233-
console.print("\n[dim]Commands: task add/complete | pokemon team/pokedex | daily | --help[/dim]")
224+
console.print(
225+
"\n[dim]Commands: task add/complete | pokemon team/pokedex | daily | --help[/dim]"
226+
)
234227

235228

236229
if __name__ == "__main__":

0 commit comments

Comments
 (0)