ledger: JSONPlaceholder /users extraction (10 records) -> csv/md/json
This commit is contained in:
1 parent
2d0dda600f
commit
cc3b45975f
7 files changed
+544
No files matched your search
@@ -0,0 +1,11 @@
|
||||
id,name,username,email,city,phone,website,company
|
||||
1,Leanne Graham,Bret,Sincere@april.biz,Gwenborough,1-770-736-8031 x56442,hildegard.org,Romaguera-Crona
|
||||
2,Ervin Howell,Antonette,Shanna@melissa.tv,Wisokyburgh,010-692-6593 x09125,anastasia.net,Deckow-Crist
|
||||
3,Clementine Bauch,Samantha,Nathan@yesenia.net,McKenziehaven,1-463-123-4447,ramiro.info,Romaguera-Jacobson
|
||||
4,Patricia Lebsack,Karianne,Julianne.OConner@kory.org,South Elvis,493-170-9623 x156,kale.biz,Robel-Corkery
|
||||
5,Chelsey Dietrich,Kamren,Lucio_Hettinger@annie.ca,Roscoeview,(254)954-1289,demarco.info,Keebler LLC
|
||||
6,Mrs. Dennis Schulist,Leopoldo_Corkery,Karley_Dach@jasper.info,South Christy,1-477-935-8478 x6430,ola.org,Considine-Lockman
|
||||
7,Kurtis Weissnat,Elwyn.Skiles,Telly.Hoeger@billy.biz,Howemouth,210.067.6132,elvis.io,Johns Group
|
||||
8,Nicholas Runolfsdottir V,Maxime_Nienow,Sherwood@rosamond.me,Aliyaview,586.493.6943 x140,jacynthe.com,Abernathy Group
|
||||
9,Glenna Reichert,Delphine,Chaim_McDermott@dana.io,Bartholomebury,(775)976-6794 x41206,conrad.com,Yost and Sons
|
||||
10,Clementina DuBuque,Moriah.Stanton,Rey.Padberg@karina.biz,Lebsackbury,024-648-3804,ambrose.net,Hoeger LLC
|
||||
|
@@ -0,0 +1,102 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Leanne Graham",
|
||||
"username": "Bret",
|
||||
"email": "Sincere@april.biz",
|
||||
"city": "Gwenborough",
|
||||
"phone": "1-770-736-8031 x56442",
|
||||
"website": "hildegard.org",
|
||||
"company": "Romaguera-Crona"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Ervin Howell",
|
||||
"username": "Antonette",
|
||||
"email": "Shanna@melissa.tv",
|
||||
"city": "Wisokyburgh",
|
||||
"phone": "010-692-6593 x09125",
|
||||
"website": "anastasia.net",
|
||||
"company": "Deckow-Crist"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Clementine Bauch",
|
||||
"username": "Samantha",
|
||||
"email": "Nathan@yesenia.net",
|
||||
"city": "McKenziehaven",
|
||||
"phone": "1-463-123-4447",
|
||||
"website": "ramiro.info",
|
||||
"company": "Romaguera-Jacobson"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Patricia Lebsack",
|
||||
"username": "Karianne",
|
||||
"email": "Julianne.OConner@kory.org",
|
||||
"city": "South Elvis",
|
||||
"phone": "493-170-9623 x156",
|
||||
"website": "kale.biz",
|
||||
"company": "Robel-Corkery"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Chelsey Dietrich",
|
||||
"username": "Kamren",
|
||||
"email": "Lucio_Hettinger@annie.ca",
|
||||
"city": "Roscoeview",
|
||||
"phone": "(254)954-1289",
|
||||
"website": "demarco.info",
|
||||
"company": "Keebler LLC"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Mrs. Dennis Schulist",
|
||||
"username": "Leopoldo_Corkery",
|
||||
"email": "Karley_Dach@jasper.info",
|
||||
"city": "South Christy",
|
||||
"phone": "1-477-935-8478 x6430",
|
||||
"website": "ola.org",
|
||||
"company": "Considine-Lockman"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Kurtis Weissnat",
|
||||
"username": "Elwyn.Skiles",
|
||||
"email": "Telly.Hoeger@billy.biz",
|
||||
"city": "Howemouth",
|
||||
"phone": "210.067.6132",
|
||||
"website": "elvis.io",
|
||||
"company": "Johns Group"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Nicholas Runolfsdottir V",
|
||||
"username": "Maxime_Nienow",
|
||||
"email": "Sherwood@rosamond.me",
|
||||
"city": "Aliyaview",
|
||||
"phone": "586.493.6943 x140",
|
||||
"website": "jacynthe.com",
|
||||
"company": "Abernathy Group"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Glenna Reichert",
|
||||
"username": "Delphine",
|
||||
"email": "Chaim_McDermott@dana.io",
|
||||
"city": "Bartholomebury",
|
||||
"phone": "(775)976-6794 x41206",
|
||||
"website": "conrad.com",
|
||||
"company": "Yost and Sons"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Clementina DuBuque",
|
||||
"username": "Moriah.Stanton",
|
||||
"email": "Rey.Padberg@karina.biz",
|
||||
"city": "Lebsackbury",
|
||||
"phone": "024-648-3804",
|
||||
"website": "ambrose.net",
|
||||
"company": "Hoeger LLC"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
| id | name | username | email | city | phone | website | company |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 1 | Leanne Graham | Bret | Sincere@april.biz | Gwenborough | 1-770-736-8031 x56442 | hildegard.org | Romaguera-Crona |
|
||||
| 2 | Ervin Howell | Antonette | Shanna@melissa.tv | Wisokyburgh | 010-692-6593 x09125 | anastasia.net | Deckow-Crist |
|
||||
| 3 | Clementine Bauch | Samantha | Nathan@yesenia.net | McKenziehaven | 1-463-123-4447 | ramiro.info | Romaguera-Jacobson |
|
||||
| 4 | Patricia Lebsack | Karianne | Julianne.OConner@kory.org | South Elvis | 493-170-9623 x156 | kale.biz | Robel-Corkery |
|
||||
| 5 | Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca | Roscoeview | (254)954-1289 | demarco.info | Keebler LLC |
|
||||
| 6 | Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info | South Christy | 1-477-935-8478 x6430 | ola.org | Considine-Lockman |
|
||||
| 7 | Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz | Howemouth | 210.067.6132 | elvis.io | Johns Group |
|
||||
| 8 | Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me | Aliyaview | 586.493.6943 x140 | jacynthe.com | Abernathy Group |
|
||||
| 9 | Glenna Reichert | Delphine | Chaim_McDermott@dana.io | Bartholomebury | (775)976-6794 x41206 | conrad.com | Yost and Sons |
|
||||
| 10 | Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz | Lebsackbury | 024-648-3804 | ambrose.net | Hoeger LLC |
|
||||
@@ -0,0 +1,232 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Leanne Graham",
|
||||
"username": "Bret",
|
||||
"email": "Sincere@april.biz",
|
||||
"address": {
|
||||
"street": "Kulas Light",
|
||||
"suite": "Apt. 556",
|
||||
"city": "Gwenborough",
|
||||
"zipcode": "92998-3874",
|
||||
"geo": {
|
||||
"lat": "-37.3159",
|
||||
"lng": "81.1496"
|
||||
}
|
||||
},
|
||||
"phone": "1-770-736-8031 x56442",
|
||||
"website": "hildegard.org",
|
||||
"company": {
|
||||
"name": "Romaguera-Crona",
|
||||
"catchPhrase": "Multi-layered client-server neural-net",
|
||||
"bs": "harness real-time e-markets"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Ervin Howell",
|
||||
"username": "Antonette",
|
||||
"email": "Shanna@melissa.tv",
|
||||
"address": {
|
||||
"street": "Victor Plains",
|
||||
"suite": "Suite 879",
|
||||
"city": "Wisokyburgh",
|
||||
"zipcode": "90566-7771",
|
||||
"geo": {
|
||||
"lat": "-43.9509",
|
||||
"lng": "-34.4618"
|
||||
}
|
||||
},
|
||||
"phone": "010-692-6593 x09125",
|
||||
"website": "anastasia.net",
|
||||
"company": {
|
||||
"name": "Deckow-Crist",
|
||||
"catchPhrase": "Proactive didactic contingency",
|
||||
"bs": "synergize scalable supply-chains"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Clementine Bauch",
|
||||
"username": "Samantha",
|
||||
"email": "Nathan@yesenia.net",
|
||||
"address": {
|
||||
"street": "Douglas Extension",
|
||||
"suite": "Suite 847",
|
||||
"city": "McKenziehaven",
|
||||
"zipcode": "59590-4157",
|
||||
"geo": {
|
||||
"lat": "-68.6102",
|
||||
"lng": "-47.0653"
|
||||
}
|
||||
},
|
||||
"phone": "1-463-123-4447",
|
||||
"website": "ramiro.info",
|
||||
"company": {
|
||||
"name": "Romaguera-Jacobson",
|
||||
"catchPhrase": "Face to face bifurcated interface",
|
||||
"bs": "e-enable strategic applications"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Patricia Lebsack",
|
||||
"username": "Karianne",
|
||||
"email": "Julianne.OConner@kory.org",
|
||||
"address": {
|
||||
"street": "Hoeger Mall",
|
||||
"suite": "Apt. 692",
|
||||
"city": "South Elvis",
|
||||
"zipcode": "53919-4257",
|
||||
"geo": {
|
||||
"lat": "29.4572",
|
||||
"lng": "-164.2990"
|
||||
}
|
||||
},
|
||||
"phone": "493-170-9623 x156",
|
||||
"website": "kale.biz",
|
||||
"company": {
|
||||
"name": "Robel-Corkery",
|
||||
"catchPhrase": "Multi-tiered zero tolerance productivity",
|
||||
"bs": "transition cutting-edge web services"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Chelsey Dietrich",
|
||||
"username": "Kamren",
|
||||
"email": "Lucio_Hettinger@annie.ca",
|
||||
"address": {
|
||||
"street": "Skiles Walks",
|
||||
"suite": "Suite 351",
|
||||
"city": "Roscoeview",
|
||||
"zipcode": "33263",
|
||||
"geo": {
|
||||
"lat": "-31.8129",
|
||||
"lng": "62.5342"
|
||||
}
|
||||
},
|
||||
"phone": "(254)954-1289",
|
||||
"website": "demarco.info",
|
||||
"company": {
|
||||
"name": "Keebler LLC",
|
||||
"catchPhrase": "User-centric fault-tolerant solution",
|
||||
"bs": "revolutionize end-to-end systems"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Mrs. Dennis Schulist",
|
||||
"username": "Leopoldo_Corkery",
|
||||
"email": "Karley_Dach@jasper.info",
|
||||
"address": {
|
||||
"street": "Norberto Crossing",
|
||||
"suite": "Apt. 950",
|
||||
"city": "South Christy",
|
||||
"zipcode": "23505-1337",
|
||||
"geo": {
|
||||
"lat": "-71.4197",
|
||||
"lng": "71.7478"
|
||||
}
|
||||
},
|
||||
"phone": "1-477-935-8478 x6430",
|
||||
"website": "ola.org",
|
||||
"company": {
|
||||
"name": "Considine-Lockman",
|
||||
"catchPhrase": "Synchronised bottom-line interface",
|
||||
"bs": "e-enable innovative applications"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Kurtis Weissnat",
|
||||
"username": "Elwyn.Skiles",
|
||||
"email": "Telly.Hoeger@billy.biz",
|
||||
"address": {
|
||||
"street": "Rex Trail",
|
||||
"suite": "Suite 280",
|
||||
"city": "Howemouth",
|
||||
"zipcode": "58804-1099",
|
||||
"geo": {
|
||||
"lat": "24.8918",
|
||||
"lng": "21.8984"
|
||||
}
|
||||
},
|
||||
"phone": "210.067.6132",
|
||||
"website": "elvis.io",
|
||||
"company": {
|
||||
"name": "Johns Group",
|
||||
"catchPhrase": "Configurable multimedia task-force",
|
||||
"bs": "generate enterprise e-tailers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Nicholas Runolfsdottir V",
|
||||
"username": "Maxime_Nienow",
|
||||
"email": "Sherwood@rosamond.me",
|
||||
"address": {
|
||||
"street": "Ellsworth Summit",
|
||||
"suite": "Suite 729",
|
||||
"city": "Aliyaview",
|
||||
"zipcode": "45169",
|
||||
"geo": {
|
||||
"lat": "-14.3990",
|
||||
"lng": "-120.7677"
|
||||
}
|
||||
},
|
||||
"phone": "586.493.6943 x140",
|
||||
"website": "jacynthe.com",
|
||||
"company": {
|
||||
"name": "Abernathy Group",
|
||||
"catchPhrase": "Implemented secondary concept",
|
||||
"bs": "e-enable extensible e-tailers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Glenna Reichert",
|
||||
"username": "Delphine",
|
||||
"email": "Chaim_McDermott@dana.io",
|
||||
"address": {
|
||||
"street": "Dayna Park",
|
||||
"suite": "Suite 449",
|
||||
"city": "Bartholomebury",
|
||||
"zipcode": "76495-3109",
|
||||
"geo": {
|
||||
"lat": "24.6463",
|
||||
"lng": "-168.8889"
|
||||
}
|
||||
},
|
||||
"phone": "(775)976-6794 x41206",
|
||||
"website": "conrad.com",
|
||||
"company": {
|
||||
"name": "Yost and Sons",
|
||||
"catchPhrase": "Switchable contextually-based project",
|
||||
"bs": "aggregate real-time technologies"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Clementina DuBuque",
|
||||
"username": "Moriah.Stanton",
|
||||
"email": "Rey.Padberg@karina.biz",
|
||||
"address": {
|
||||
"street": "Kattie Turnpike",
|
||||
"suite": "Suite 198",
|
||||
"city": "Lebsackbury",
|
||||
"zipcode": "31428-2261",
|
||||
"geo": {
|
||||
"lat": "-38.2386",
|
||||
"lng": "57.2232"
|
||||
}
|
||||
},
|
||||
"phone": "024-648-3804",
|
||||
"website": "ambrose.net",
|
||||
"company": {
|
||||
"name": "Hoeger LLC",
|
||||
"catchPhrase": "Centralized empowering task-force",
|
||||
"bs": "target end-to-end models"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,45 @@
|
||||
# Ledger — JSONPlaceholder /users extraction (2026-10-23)
|
||||
|
||||
## What landed
|
||||
A finished data-extraction artifact: the public `https://jsonplaceholder.typicode.com/users`
|
||||
table (10 records) pulled into a normalized CSV table, a Markdown table, a JSON blob,
|
||||
and the raw HTTP response used as ground truth.
|
||||
|
||||
## Real tool call
|
||||
- `fetch` via `urllib.request` (Python stdlib, no third-party deps) against the live
|
||||
endpoint. HTTP 200, 5645 bytes received (verified in `2026-10-23-jpv-users.raw.json`).
|
||||
- No auth, no paywall, no paid credits (free-tier only).
|
||||
|
||||
## Artifact files (primary location)
|
||||
- `/root/.hermes/wizard-outputs/ledger/2026-10-23-jpv-users.raw.json` — untouched response body (ground truth)
|
||||
- `/root/.hermes/wizard-outputs/ledger/2026-10-23-jpv-users.csv` — normalized table (8 columns)
|
||||
- `/root/.hermes/wizard-outputs/ledger/2026-10-23-jpv-users.md` — Markdown table
|
||||
- `/root/.hermes/wizard-outputs/ledger/2026-10-23-jpv-users.json` — normalized records
|
||||
- `/root/.hermes/wizard-outputs/ledger/extract_jpv_users.py` — extraction script (provenance of the transform)
|
||||
|
||||
Committed next to this file in the troupe repo at
|
||||
`/root/troupe-standup/wizard-work/ledger/`.
|
||||
|
||||
## Method
|
||||
For each of the 10 records, the script flattens the nested `address` and `company`
|
||||
objects into flat columns and writes CSV + Markdown table + JSON.
|
||||
|
||||
## Verification (the CHECK)
|
||||
Run:
|
||||
```
|
||||
python3 /root/troupe-standup/wizard-work/ledger/verify_users.py
|
||||
```
|
||||
It asserts: header row is exactly the 8 expected columns; exactly 10 data rows; and three
|
||||
spot rows (ids 1, 3, 10) match values re-derivable from the fetched response.
|
||||
|
||||
Result (exit code): **0** —
|
||||
`OK: header exact, 10 rows, 3 spot rows verified`
|
||||
|
||||
## Spot-checked rows (from the fetched data)
|
||||
- id 1: Leanne Graham / Bret / Sincere@april.biz / Gwenborough / hildegard.org / Romaguera-Crona
|
||||
- id 3: Clementine Bauch / Samantha / Nathan@yesenia.net / McKenziehaven / ramiro.info / Romaguera-Jacobson
|
||||
- id 10: Clementina DuBuque / Moriah.Stanton / Rey.Padberg@karina.biz / Lebsackbury / ambrose.net / Hoeger LLC
|
||||
|
||||
## Notes
|
||||
- The `CHECK:` line above is the machine-enforced completion condition (Ralph loop); it
|
||||
exits 0 on the committed artifact and non-zero on any mismatch.
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Extract the JSONPlaceholder /users table (10 records) into structured files.
|
||||
|
||||
Real tool call: urllib.request against a live public endpoint (no auth, no
|
||||
paywall, no paid credits). Produces raw JSON, a CSV table, a Markdown table,
|
||||
and a normalised JSON blob.
|
||||
|
||||
Output (in /root/.hermes/wizard-outputs/ledger/):
|
||||
2026-10-23-jpv-users.raw.json - untouched HTTP response body
|
||||
2026-10-23-jpv-users.csv - normalised table (8 columns)
|
||||
2026-10-23-jpv-users.md - Markdown table
|
||||
2026-10-23-jpv-users.json - normalised records (JSON)
|
||||
"""
|
||||
import csv
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
|
||||
SRC = "https://jsonplaceholder.typicode.com/users"
|
||||
OUTDIR = "/root/.hermes/wizard-outputs/ledger"
|
||||
RAW = os.path.join(OUTDIR, "2026-10-23-jpv-users.raw.json")
|
||||
CSV = os.path.join(OUTDIR, "2026-10-23-jpv-users.csv")
|
||||
MD = os.path.join(OUTDIR, "2026-10-23-jpv-users.md")
|
||||
JSOUT = os.path.join(OUTDIR, "2026-10-23-jpv-users.json")
|
||||
|
||||
FIELDS = ["id", "name", "username", "email", "city", "phone", "website", "company"]
|
||||
|
||||
|
||||
def fetch():
|
||||
req = urllib.request.Request(
|
||||
SRC, headers={"User-Agent": "ledger-extract/1.0"}
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=30) as r:
|
||||
return r.read().decode("utf-8")
|
||||
|
||||
|
||||
def main():
|
||||
os.makedirs(OUTDIR, exist_ok=True)
|
||||
raw = fetch()
|
||||
with open(RAW, "w") as f:
|
||||
f.write(raw)
|
||||
|
||||
recs = json.loads(raw)
|
||||
rows = []
|
||||
for rec in recs:
|
||||
addr = rec.get("address") or {}
|
||||
comp = rec.get("company") or {}
|
||||
rows.append({
|
||||
"id": rec["id"],
|
||||
"name": rec["name"],
|
||||
"username": rec["username"],
|
||||
"email": rec["email"],
|
||||
"city": addr.get("city"),
|
||||
"phone": rec["phone"],
|
||||
"website": rec["website"],
|
||||
"company": comp.get("name"),
|
||||
})
|
||||
|
||||
with open(CSV, "w", newline="") as f:
|
||||
w = csv.DictWriter(f, fieldnames=FIELDS)
|
||||
w.writeheader()
|
||||
w.writerows(rows)
|
||||
|
||||
lines = [
|
||||
"| id | name | username | email | city | phone | website | company |",
|
||||
"|---|---|---|---|---|---|---|---|",
|
||||
]
|
||||
for r in rows:
|
||||
lines.append("| " + " | ".join(str(r[c]) for c in FIELDS) + " |")
|
||||
with open(MD, "w") as f:
|
||||
f.write("\n".join(lines) + "\n")
|
||||
|
||||
with open(JSOUT, "w") as f:
|
||||
json.dump(rows, f, indent=2)
|
||||
|
||||
print("fetched", len(rows), "users from", SRC)
|
||||
print("raw:", RAW)
|
||||
print("csv:", CSV)
|
||||
print("md:", MD)
|
||||
print("json:", JSOUT)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""CHECK — verify the JSONPlaceholder /users extraction artifact.
|
||||
|
||||
Reads users.csv (defaults to the committed copy in the troupe repo) and
|
||||
asserts:
|
||||
* header row is exactly the 8 expected columns
|
||||
* there are exactly 10 data rows
|
||||
* three spot rows match values re-derivable from the HTTP response
|
||||
|
||||
Exit 0 only if every assertion holds; non-zero otherwise.
|
||||
"""
|
||||
import csv
|
||||
import sys
|
||||
|
||||
# Committed artifact path (what ships to the repo).
|
||||
DEFAULT_CSV = "/root/troupe-standup/wizard-work/ledger/2026-10-23-jpv-users.csv"
|
||||
|
||||
HEADER = ["id", "name", "username", "email", "city", "phone", "website", "company"]
|
||||
|
||||
# (name, username, email, city, website, company)
|
||||
EXPECTED = {
|
||||
"1": ("Leanne Graham", "Bret", "Sincere@april.biz", "Gwenborough",
|
||||
"hildegard.org", "Romaguera-Crona"),
|
||||
"3": ("Clementine Bauch", "Samantha", "Nathan@yesenia.net",
|
||||
"McKenziehaven", "ramiro.info", "Romaguera-Jacobson"),
|
||||
"10": ("Clementina DuBuque", "Moriah.Stanton", "Rey.Padberg@karina.biz",
|
||||
"Lebsackbury", "ambrose.net", "Hoeger LLC"),
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
csv_path = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_CSV
|
||||
with open(csv_path, newline="") as f:
|
||||
reader = csv.DictReader(f)
|
||||
if reader.fieldnames != HEADER:
|
||||
print("HEADER MISMATCH: got %r" % (reader.fieldnames,))
|
||||
return 1
|
||||
rows = list(reader)
|
||||
|
||||
if len(rows) != 10:
|
||||
print("ROW COUNT MISMATCH: %d" % len(rows))
|
||||
return 1
|
||||
|
||||
for r in rows:
|
||||
key = r["id"]
|
||||
if key in EXPECTED:
|
||||
want = EXPECTED[key]
|
||||
got = (r["name"], r["username"], r["email"], r["city"],
|
||||
r["website"], r["company"])
|
||||
if got != want:
|
||||
print("ROW %s MISMATCH: got %r want %r" % (key, got, want))
|
||||
return 1
|
||||
print("OK: header exact, 10 rows, 3 spot rows verified")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user