Files
ai-workflow-course/modules/17-secrets-config-and-environments/lab/starter/sync.py
T
justin 3221f7abe8
CI / check (pull_request) Successful in 7s
Use python3 as the canonical command name course-wide (#104)
Most current systems (default Debian/Ubuntu, recent macOS) install Python
only as `python3`, with no bare `python` on PATH, so learners who copied
`python cli.py ...` into their host shell hit "command not found".

Convert host-shell `python <cmd>` -> `python3 <cmd>` across module/lab
READMEs, lab `.py` docstrings & usage strings, blog posts, lab prompt and
instruction files, the M04 verify.sh message, and the M10/M24 lab patches.
Module 01's convention note (and its blog/02 mirror) is rewritten so
`python3` is canonical and `python` is the documented fallback.

Stop-lines respected: Docker image tags (`python:3.12-slim`), `.venv/.../python`
and `...\.venv\Scripts\python.exe` paths, the M20 `"command": "python"`
teaching example and surrounding venv prose, container-internal invocations
(M16/M18 Dockerfiles, M16 README `docker run` examples), and CI-workflow
`run:` steps fed by `actions/setup-python` / `image: python:3.12` are left
as `python` on purpose.

pip was left out of scope: most occurrences are prose or CI/container-internal,
and `pip3` does not fix the PEP 668 externally-managed-environment refusal that
the course already addresses with venvs. The M01 note is worded to stay
consistent with bare `pip` (use whichever pip pairs with your Python).

Build (tools/build_wiki.py) and tools/check.sh both pass.

Closes #104

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GAEzanEoGJT5o1VizQar47
2026-06-23 20:18:04 -04:00

50 lines
1.8 KiB
Python

"""A 'sync' command for the tasks-app: the BEFORE picture for Module 17.
This is exactly the kind of file an AI hands you when you ask it to "add a command that syncs
tasks to our backend." It works. It also has two AI-classic mistakes baked in:
1. The API key is hardcoded right here in the source (see API_KEY below).
2. The backend URL is hardcoded too, so there is no way to point dev at a dev server and
prod at the prod one without editing code.
Your job in the lab is to refactor BOTH out of the source and into the environment. Don't read
ahead and fix it yet; first run it as-is so you can see the smell.
Run it:
python3 sync.py
It does not actually hit the network (so the lab works offline, on any OS); it simulates the
request and prints what it *would* send.
"""
import json
from pathlib import Path
# --- The anti-pattern. This is what we are here to remove. ---------------------------------
API_KEY = "sk-live-9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c" # <-- a real-looking secret, in source
BACKEND_URL = "https://api.example-tasks.com/v1" # <-- environment baked into code
# -------------------------------------------------------------------------------------------
STATE = Path(__file__).parent / "tasks.json"
def load_task_count() -> int:
"""Count tasks from the tasks-app state file, if it exists."""
if not STATE.exists():
return 0
return len(json.loads(STATE.read_text()))
def sync() -> int:
count = load_task_count()
# In a real client this would be an authenticated HTTP request. We just show what it'd send.
print(f"POST {BACKEND_URL}/tasks/sync")
print(f"Authorization: Bearer {API_KEY}")
print(f"Body: {{\"task_count\": {count}}}")
print("(simulated) sync OK")
return 0
if __name__ == "__main__":
raise SystemExit(sync())