Skip to content

feat(cli): add bfabric-cli workunit diff command - #568

Merged
leoschwarz merged 6 commits into
mainfrom
feat/workunit-diff
Jul 31, 2026
Merged

feat(cli): add bfabric-cli workunit diff command#568
leoschwarz merged 6 commits into
mainfrom
feat/workunit-diff

Conversation

@leoschwarz

@leoschwarz leoschwarz commented Jul 24, 2026

Copy link
Copy Markdown
Member
  • Add bfabric-cli workunit diff command to compare to workunits including their parameters.
  • Add EntityUri.normalize to normalize e.g. a pasted https://…/bfabric/workunit/show.html?id=346001&tab=details to an EntityUri.

🤖 Prepared with assistance from Claude Opus 5 via Claude Code.

Compare two workunits side by side (name, parameters, output/input
resources, status, application, container, input dataset), highlighting
differences in rich tables. Each reference is an entity URI or a numeric
workunit ID; --only-diff collapses output to the differing rows.
Replace the EntityUri validation regex with urllib.parse-based parsing and
add EntityUri.from_web_url, which normalizes a URL as copied from the
browser into the canonical entity URI: extra query parameters (e.g.
&tab=details) and the fragment are dropped, host case and a default port
are normalized. The result compares and hashes equal to the entity's
canonical EntityUri, so a pasted URL works as an EntityResult/cache key.

The EntityUri constructor stays strict and now hints at from_web_url when
it rejects such a URL; its other rejections name the actual problem
(scheme/host, path, query) instead of a blanket "Invalid Entity URI".
Credentials in the URL are now rejected outright and the localhost
exemption is case-insensitive.

bfabric-cli workunit diff parses its references leniently, so a workunit
URL pasted from the browser resolves instead of erroring out.
EntityUri.from_web_url becomes EntityUri.normalize, naming the guarantee it
gives (a canonical URI) rather than the shape of its input, and trims its
docstring to the repo's terser convention.

_parse_uri_components drops from 48 to 37 lines with no change to what it
accepts: strict mode now reuses the lenient parse and then requires the URI
to have been canonical, the components model is constructed directly instead
of via model_validate on a dict, and the instance is rebuilt from netloc
instead of reassembling host and port (which also fixes IPv6 hosts).

Two error messages move: a strict-mode non-numeric or missing id now reports
that specifically instead of the generic "expected query 'id=<entity_id>'"
hint, and a malformed port surfaces as a pydantic ValidationError.
The existing guidance only covered restating default values, so nothing said
which style to write (Sphinx :param: dominates; a handful of older modules
still carry Google-style Args:/Returns: blocks) or how much to write. Add
both, plus the trap that a cyclopts command docstring is its --help text and
must not be trimmed like an internal helper's.
_resolve_workunit mapped a failed URI parse to a None sentinel and then
re-branched on it, spreading one decision over two conditionals. Test the
numeric case first instead, so the URI branch can raise directly; the parse
error is translated so a typo'd reference still reports that an ID would
also be accepted.
@leoschwarz
leoschwarz marked this pull request as ready for review July 31, 2026 11:56
@leoschwarz
leoschwarz merged commit 7cb1368 into main Jul 31, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant