Python: Fluency + ship rxp
Fourth phase. Python at fluency — enough to ship a real CLI, write small services, do data work. Not “Python expert in 5 weeks.” Mastery comes when you operate something complex written in it. ~5 weeks, ~60 hrs.
The first three phases of Year 1 treated systems as something you observe — strace this, tcpdump that, EXPLAIN ANALYZE the other. Phase 4 is the first time you write something the platform will use. The bar isn’t “Python expert” — it’s “I can ship a small, tested, packaged CLI that someone could install today.” That’s enough to graduate from observer to author.
The Year 1 overview is explicit on this point: fluency, not mastery. The same principle applies to Phase 5 (Go). Mastery is what happens in Years 3-5 when you operate complex systems written in these languages — Spark, Kubeflow, platform-ctl, services/llm-gateway/. Year 1 is buying you the right to learn those without language friction.
Prerequisites
Why this phase exists
Years 3-5 lean on Python heavily — Spark/PySpark, Airflow DAGs, Ray, Kubeflow Pipelines, ML training scripts, FastAPI services, RAG glue code. You don’t need Python mastery to operate those — you need fluency + the operational patterns. The goal here is “I can read any Python codebase and ship a small CLI.”
rxp is the proof-of-fluency artifact. konfig is the stretch artifact for the same phase budget.
1. PROBLEM
You want to write small tools and small services that solve real problems in your platform. Python is the highest-leverage choice because it’s the lingua franca of ops/data/ML. The risk is over-investing in Python idioms that don’t compound.
This phase ships utility code that you’ll actually use — rxp for log-pattern extraction (gets called by Year 5 services/aiops/), konfig for validating your own basecamp YAML (Year 2+ uses it in CI).
Both projects have a real integration role — they’re not orphan demos. That’s the whole reason they exist as Year 1 artifacts: shipping habits + actual platform value.
2. PRINCIPLES (lean: fluency phase)
2.1 Text processing as a first-class primitive
Logs, configs, exceptions — most ops work is reading text. Regex + structured parsers are the tools.
Investigate:
- Build a regex that extracts
(timestamp, level, message)from a Linux journald line - When does regex fail? (Nested structure, escaping hell.) When do you reach for
lark/parsy/ a real parser?
2.2 Schema validation as a discipline
Configs lie. Validating at the boundary catches bugs early.
Investigate:
- Pydantic v2 validators on a small config object
- JSON Schema validation with
jsonschema; round-trip a YAML through it
This is the principle konfig embodies, and the reason it earns its place in basecamp CI in Year 2 — Helm values lie all the time (typos, missing keys, wrong types), and validating them at PR time is dramatically cheaper than discovering the lie at helm install time inside a cluster.
2.3 IO + concurrency basics
Python has multiple concurrency models — threads, asyncio, multiprocessing. Pick the right one per workload.
Investigate:
- When does
asynciowin? When doesmultiprocessingwin? When do threads suffice? - Build a small concurrent fetcher (5 URLs in parallel) three ways: threads, asyncio, sync
This investigation is deliberately a warm-up for Phase 5 — you’ll re-implement the same concurrent-fetcher problem in Go with goroutines and observe how much Go’s runtime takes off your shoulders. Comparing the three Python implementations now makes the contrast meaningful then.
2.4 CLI ergonomics
Good CLIs have: --help that’s actually helpful, predictable exit codes, --json for machine consumption, color when interactive, no color when piped.
Investigate:
typervsclick— pick onerichfor terminal rendering- Exit codes 0/1/2 conventions
Every CLI in the program — rxp, konfig, pulse, eventually platform-ctl and mlship — needs to behave well in pipes and well under --help. The habit you build here in Phase 4 is the same habit Year 5’s mlship is judged on.
2.5 Packaging + distribution (just enough)
Modern Python packaging is pyproject.toml + a build backend (hatch, pdm, poetry). PyPI vs TestPyPI for first ships.
Investigate:
pyproject.tomlminimum for a publishable package- Why TestPyPI before PyPI?
3. TRADE-OFFS (small)
| Decision | Option A | Option B | Cost |
|---|---|---|---|
| CLI framework | typer (modern, type-hinted) | click (mature, widely-used) | Either fine; typer is friendlier |
| Schema validation | pydantic v2 | jsonschema | both |
| Async style | asyncio | trio | structured concurrency (anyio) |
| Packaging | hatch | pdm | poetry |
4. TOOLS (as of 2025-10)
- Python 3.12+
uv— fast package manager (replaces pip + venv for most things)ruff— linter + formatter (replaces black + flake8 + isort)pytest— test runnerhypothesis— property-based testingtyper+rich— CLIpydantic v2— validationhttpx— HTTP client (sync + async)
5. MASTERY
5.1 Reading list
| Required | Why |
|---|---|
| ”Fluent Python” (Ramalho, 2nd ed.) Ch. 1-9 (data model, functions) | The book |
pydantic v2 docs (Models + Validators) | Validation depth |
| Recommended | Why |
|---|---|
| Real Python’s asyncio guide | When you reach the concurrency check |
5.2 Operational depth checklist
[ ] Set up uv + a fresh project (pyproject.toml + src layout)[ ] Write a tiny CLI with typer + rich; install in editable mode[ ] Add pytest; aim for 70%+ coverage on rxp[ ] Use ruff + format-check in CI[ ] Publish to TestPyPI; verify install on a clean machine[ ] Build a small async URL fetcher; benchmark vs sync[ ] Add hypothesis tests for one core function (property-based)[ ] Configure GitHub Actions: ruff + pytest on PR[ ] Tag a v0.1.0 release; verify changelog + installable[ ] Read one well-known small Python project (httpx, typer source) for 1 hour; note 3 patternsThe “read someone else’s source for 1 hour” item is the one that compounds across the rest of the program. Year 3 you’ll read PySpark’s executor code. Year 4 you’ll read Ray’s autoscaler. Year 5 you’ll read LangGraph’s state machine. The habit of reading production Python without flinching is the actual fluency outcome.
5.3 Project: rxp
A regex CLI: build, test, debug regular expressions. Doubles as a real log-parsing tool.
rxp test '\b[A-Z][a-z]+\b' "Hello World, Foo Bar"# → highlights matches, shows positions, capture groups
rxp explain '\b\d{3}-\d{4}\b'# → English description: "matches phone-number-like XXX-XXXX at word boundaries"
rxp stream # read stdin, highlight matches inlinerxp deliverables:
- typer CLI (test, explain, stream)
- 70%+ pytest coverage
- README + 10 examples
- TestPyPI publish
- GitHub Actions CI on PR
- Tagged release
- Quiet ship. Push to GitHub + TestPyPI. No blog post, no LinkedIn announcement. The discipline is shipping; launch energy is reserved for
mlshipin Year 5.
rxp reappears in Year 5 as a dependency of services/aiops/, where the agent uses it to extract structured data from log lines. That integration is the reason the explain command exists — humans use test, agents use explain to reason about a regex they didn’t write themselves.
See projects/rxp/plan for the full spec.
5.4 Stretch project: konfig
If you have time after rxp ships:
konfig validate config.yaml --schema schema.jsonkonfig generate-schema example.yaml > schema.jsonSame shape: typer + pydantic + jsonschema. Same quiet-ship discipline. Used in Year 2+ to validate basecamp Helm values in CI.
See projects/konfig/plan.
6. COMPARE: Python vs Bash for a small ops tool
You could write a regex-CLI as a bash one-liner with grep -P. When would Bash win? When does Python earn its weight?
300 words, in ops-handbook/.
The honest cutoff is roughly: if it’s one pipe and you’ll throw it away by tomorrow, Bash wins. If it has subcommands, types, tests, or will be installed elsewhere, Python earns its weight. Articulating the threshold in your own words is the actual exercise — knowing when not to reach for Python is as much fluency as knowing when to reach for it.
7. OPERATE
- 1-2 small runbooks (Python venv troubleshooting, “my package won’t install”)
- Weekly log
8. CONTRIBUTE
Approachable: typer docs, pydantic docs, ruff false-positive reports, any small Python tool you use.
Validation criteria
[ ] All 10 operational depth checks[ ] `rxp` shipped to TestPyPI + GitHub[ ] (Stretch) `konfig` shipped to TestPyPI + GitHub[ ] Python vs Bash comparison written up[ ] 1-2 runbooks; 5+ weekly log entries[ ] Patterns touched (not necessarily deepened): - text processing as a primitive (referenced by Year 5 aiops) - schema validation as discipline (referenced by Year 2 basecamp CI)[ ] Exit Test passedExit Test
Time: 2 hours.
- Build (60 min) — write a small Python CLI from scratch:
logragthat takes a log file + a regex, prints matches with line numbers, exits 0 if matches found, 1 if not. With tests + types + ruff clean. - Articulate (60 min) — 600 words: “When would I reach for
rxpvsgrep -Pvsawk? What’s the cost of each?”
Anti-patterns
| Anti-pattern | Why |
|---|---|
| Trying to learn every Python idiom in 5 weeks | Fluency, not mastery. You’ll deepen as you operate ML/data tools in Years 3-5 |
Using requirements.txt instead of pyproject.toml | Modern Python is pyproject.toml; old patterns are tech debt |
| Skipping types | Types catch bugs you’d otherwise pay for at 3am |
Loud-launching rxp (blog, LinkedIn) | Year 1 is quiet ship; loud launch is for mlship |
Patterns touched this phase
- Text processing — light touch (deepens via Year 5 aiops)
- Schema validation — light touch (used in Year 2 basecamp CI)
→ Next: Phase 5: Go + Concurrency