Repository navigation
feat(cli): complete analyze summary (span + speeds) and harden input - #12
Conversation
The analyze subcommand advertises recomputing a summary from an exported tracks.csv, but only printed track counts. The export also carries per-track first/last timestamps and speed estimates, so the summary can additionally report the tracked-activity span and the average/fastest vehicle speed of the run without re-running the model. The congestion level is deliberately not recomputed: it depends on per-frame vehicle densities that only the run pass observes and that tracks.csv does not store.
Pointing `analyze` at a CSV that lacks the expected columns (or at a file that is not a CSV at all) crashed with a raw KeyError / ParserError traceback from inside pandas indexing. Validate the expected columns up front and wrap the read, so both cases exit 1 with an actionable log message instead. Also read with utf-8-sig so exports round-tripped through Excel (which adds a BOM) still parse.
Locks in the new span/speed reporting and the graceful exit codes for a CSV missing expected columns, a header-only export, a non-CSV file and a missing file, so future changes to the export schema or the subcommand surface regressions immediately.
The README showed run and dashboard in the quickstart but never mentioned analyze, so the subcommand was effectively undiscoverable without reading the source. Add a short CLI table with an analyze example.
|
Aclaración de transparencia: este PR lo preparé yo (@jeremarche) con ayuda sustancial de un Lo digo de entrada en lugar de dejar que aparezca más adelante: si alguna parte del cambio |
|
Gracias por el PR, buen trabajo — probé el diff completo a mano (tests, ruff, y algunos casos borde) y los números que ponés en la descripción son correctos. Encontré un bug antes de aprobar: except (pd.errors.ParserError, UnicodeDecodeError) no cubre pandas.errors.EmptyDataError, que es justo lo que tira pd.read_csv con un archivo de 0 bytes (no "solo header" — vacío de verdad, ej. una exportación que falló a mitad de camino o un touch accidental). Lo reproduje: $ python -m traffic_intelligence analyze --input empty.csv Es el mismo traceback crudo que este PR dice estar eliminando. EmptyDataError es hermana de ParserError (ambas heredan de ValueError, no una de la otra), por eso test_analyze_rejects_header_only_csv no lo agarra — ese CSV tiene header, no está realmente vacío. ¿Podés sumar pd.errors.EmptyDataError al tuple del except (o pasar a except ValueError, ya que las tres cuelgan de ahí) y agregar un test con un archivo de 0 bytes? El resto lo apruebo tal cual: la validación de columnas, el cálculo de activity span y velocidad, el utf-8-sig para BOM de Excel, y el README/help actualizados. Con ese fix, lo mergeo. |
|
Hola Felipe, ¡Gracias por la review y por el repro tan preciso! Tenías razón en todo: Apliqué tu opción A: sumé Va como un commit nuevo encima de los que ya revisaste (sin reescribir historia, Gracias de nuevo por el nivel de detalle: se aprende un montón de una review así. Jeremías |
A 0-byte input (an export that died mid-write, an accidental `touch`) makes pd.read_csv raise EmptyDataError, which the except tuple missed: EmptyDataError is a sibling of ParserError (both subclass ValueError), not a subclass of it, so the raw traceback this subcommand promises to eliminate still escaped for that case. The header-only test could not catch it either: a header-only CSV parses zero rows but does parse columns, so it never raises EmptyDataError. Add EmptyDataError to the tuple and cover the 0-byte case with its own test. Kept the explicit tuple rather than broadening to `except ValueError` so the caught failure modes stay documented at the catch site. Spotted by @felipebridge in PR felipebridge#12 review; repro and diagnosis his.
|
Vi que el PR #12 quedó mergeado a main — gracias por la confianza. Y
gracias doble por
la review: tu repro del EmptyDataError me enseñó más que varios cursos
juntos. El fix
quedó en el historial como quinto commit, con su test de archivo de 0 bytes.
Mantengo lo que dejé escrito en el PR: el trabajo lo hice con apoyo fuerte
de IA, con
mis decisiones y mi responsabilidad sobre el diff. Tu review fue justo el
filtro humano
que cazó lo que ni la IA ni yo vimos — creo que el combo funcionó bien así.
Si te sirve, sigo ofrecido para los follow-ups que mencioné (matriz de
Python 3.11/3.12/3.13
en CI, documentar el setup de Docker, helper compartido de lectura de
tracks.csv), y con
gusto hago de segundo par de ojos en futuros PRs si alguna vez querés una
revisión extra.
Gracias de nuevo por la guía para contribuir desde el primer mail.
Saludos,
Jeremías Marchetti
github.com/jeremarche
El lun, 21 sept 2026 a las 15:20, Felipe Bridge ***@***.***>)
escribió:
… Merged #12 <#12>
into main.
—
Reply to this email directly, view it on GitHub
<#12>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/CJF57VVQ7RRNPDSOBLWEZ3T5QFWNZAVCNFSNUABGKJSXA33TNF2G64TZHMYTGNJQGAZTCNZSHE5US43TOVSTWNJVGI4TIOJWGQYDRILWAI>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/CJF57VQFAJUHWUP35IPMCAL5QFWNZA5CNFSNUABQM5UWIORPF5TWS5BNNB2WEL2JONZXKZKFOZSW45CON52GSZTJMNQXI2LPNYXTGMJVGQ4TQNJZG4ZTLJTSMVQXG33OU5WWK3TUNFXW5JLFOZSW45FKMZXW65DFOJPWS33T>
and Android
<https://github.com/notifications/mobile/android/CJF57VQZYLBJJF3RI7DCKJD5QFWNZA5CNFSNUABQM5UWIORPF5TWS5BNNB2WEL2JONZXKZKFOZSW45CON52GSZTJMNQXI2LPNYXTGMJVGQ4TQNJZG4ZTLJTSMVQXG33OU5WWK3TUNFXW5JLFOZSW45FOMZXW65DFOJPWC3TEOJXWSZA>.
Download it today!
You are receiving this because you were mentioned.Message ID:
***@***.***
com>
|
|
Felipe querido,
Espero que te encuentres muy bien.
Te escribo para agradecerte nuevamente el intercambio que tuvimos estos
días. Quedé muy conforme con la dinámica y el pequeño avance que pude
aportar a tu proyecto.
Aprovechando que trabajamos juntos de forma tan reciente, quería pedirte un
gran favor. Como estoy potenciando mi perfil de LinkedIn, significa mucho
para mí contar con una breve recomendación tuya sobre cómo viste mi
desempeño, prolijidad técnica o trabajo en equipo durante estos días.
Sé que tu perfil tiene un gran alcance y tu agenda es ocupada, por lo que
un par de líneas puntuales serán más que suficientes. Si te parece bien, te
comparto el enlace directo para que puedas dejarla de manera ágil:
https://www.linkedin.com/in/jerem%C3%ADas-marchetti-39437639b/
Nuevamente, te agradezco mucho por la predisposición, el feedback de estos
días y tu valioso apoyo.
Te envío un cordial saludo,
Jeremías Marchetti
|
What does this change
Completes and hardens the
analyzesubcommand.analyzeadvertises "recompute a summary from a previously exported tracks.csv",but it only printed track counts. The export also carries per-track first/last
timestamps and speed estimates, so the summary now additionally reports the
tracked-activity span (earliest
first_timestampto latestlast_timestamp) andthe average/fastest estimated vehicle speed — recomputed from the CSV alone, no
model re-run. The congestion level is deliberately not recomputed: it depends on
per-frame vehicle densities that only the
runpass observes and that tracks.csvdoes not store (noted in a code comment so the omission doesn't look accidental).
While there: pointing
analyzeat a CSV that lacks the expected columns (or at afile that isn't a CSV at all) crashed with a raw
KeyError/ParserErrortraceback from inside pandas indexing. The expected columns are now validated up
front and the read is wrapped, so both cases log an actionable message and exit 1.
The read also uses
utf-8-sigso exports round-tripped through Excel (BOM) parse.Finally, the README never mentioned
analyze(or that a CLI table exists at all),so the subcommand was undiscoverable without reading the source; added a short CLI
section.
Related issue
Closes # (none opened — happy to file one if you'd rather track this there)
How was this tested
ruff check src tests dashboard scriptspytest -q(86 passed: 80 pre-existing + 6 new)Ran
analyzeon a generated tracks.csv: counts,Activity span,Average vehicle speedandFastest vehicleprint as expected; on atwo-column CSV it now exits 1 with
... is missing expected column(s): class_name, first_timestamp, ...instead of a traceback.
Checklist
tests/test_cli_analyze.py: happy path (counts/span/speeds), no-speedcalibration (
n/a), missing columns, header-only export, non-CSV bytes,missing file.
README CLI table +
analyzehelp text now mention the recomputed stats.Notes for the review, and ideas I'd be glad to take on as follow-up PRs if useful:
dashboard/data_loader.pyandanalyzeboth re-read tracks.csv; if the exportschema grows, a shared "load + validate export" helper could keep them in sync.
pyproject.tomlpromises>=3.11; a3.11/3.12/3.13 matrix would catch drift early.
CONTRIBUTING, which is a shame for people who don't want a local torch install.