Skip to content

refactor: narrow optional edge ends and vertex names with a checked helper - #88

Merged
petercorke merged 2 commits into
mainfrom
refactor/narrow-with-helpers
Oct 31, 2026
Merged

petercorke merged 2 commits into
mainfrom
refactor/narrow-with-helpers

Conversation

@petercorke

Copy link
Copy Markdown
Owner

Part of #23.

What

16 assert statements in PGraph.py (Bandit B101) existed only to tell mypy that an optional value was set. Fourteen are now gone:

Was Now
assert e.v1 is not None and e.v2 is not None (11 places: edge layout, the edge artist, plot(), incidence(), _attach of both graph types, Edge.next, Edge.endpoints) v1, v2 = e._ends()
assert v.name is not None (3 places: remove_vertex, path_UCS, path_Astar) v._require_name()

Edge._ends() and Vertex._require_name() return the value or raise ValueError, in the manner of the existing Graph._require_cost(). mypy sees the narrowed type, and the check is real: it is not removed by python -O, which is what B101 warns about.

The two asserts left (the coordinate of a candidate in near(), the graph in Vertex.connect()) are type narrowing too, with no helper that would make them clearer. They are commented as such and marked # nosec B101. I did not exclude B101 for src/, in line with RTB and bdsim, which exclude it only for tests/.

Behaviour

Nothing changes for a connected edge or a named vertex, which is every edge and vertex in a graph. An unconnected Edge() now raises ValueError("the edge is not connected to two vertices") from .endpoints and .next(), where it raised AssertionError (and next() raised ValueError("should not happen")).

Performance

_attach runs for every edge added, so the helper adds a call on that path. Measured against main (git archive main src, three runs each, best of 7 within a run) on 90,000 edges over 30,000 vertices:

main this branch
UGraph.add_edge 114.5, 114.9, 115.8 ms 112.8, 113.7, 115.5 ms
DGraph.add_edge 114.6, 116.1, 114.7 ms 114.5, 112.2, 112.6 ms

No difference beyond noise (about 1.3 µs per edge either way). My path_UCS benchmark (0.5 ms) found no path, so it says nothing about the search itself; the change there is only the final loop that builds the parent names.

Tests

  • Edge._ends() / endpoints / next() on a connected edge, on an unconnected Edge(), and next() of a vertex that is not an end
  • Vertex._require_name() with and without a name

pytest tests: 777 passed. mypy src: clean.

🤖 Generated with Claude Code

…elper

Fourteen of the sixteen assert statements in PGraph.py only told mypy that an
optional value was set: the ends of an edge (v1 and v2 are None until it is
connected) and the name of a vertex (None until it is in a graph).  Bandit
reports each as B101, and python -O removes them.

Add Edge._ends(), which returns both vertices or raises ValueError, and
Vertex._require_name(), which returns the name or raises ValueError, in the
manner of Graph._require_cost().  They replace the asserts, so the narrowing
is still there for mypy and the check is a real one.  The two asserts left
(the coordinate of a candidate in near(), the graph in Vertex.connect()) are
type narrowing too, and are marked # nosec B101.

A connected edge behaves as before.  An unconnected one, which no graph
holds, now raises ValueError from endpoints and next() instead of
AssertionError (or, from next(), "should not happen").

Part of #23.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 4 complexity · 0 duplication

Metric Results
Complexity 4
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.05%. Comparing base (343a0f2) to head (7adc047).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #88      +/-   ##
==========================================
+ Coverage   97.98%   98.05%   +0.06%     
==========================================
  Files           4        4              
  Lines        1586     1590       +4     
==========================================
+ Hits         1554     1559       +5     
+ Misses         32       31       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@petercorke
petercorke merged commit bffb7be into main Oct 31, 2026
12 checks passed
@petercorke
petercorke deleted the refactor/narrow-with-helpers branch October 31, 2026 03:35
@petercorke petercorke mentioned this pull request Oct 31, 2026
10 tasks
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