Skip to content

test: type-check testing/src/scenario and fix uncovered errors#2615

Merged
tonyandrewmeyer merged 8 commits into
canonical:mainfrom
tonyandrewmeyer:fix-pyright-scenario-include
Jul 9, 2026
Merged

test: type-check testing/src/scenario and fix uncovered errors#2615
tonyandrewmeyer merged 8 commits into
canonical:mainfrom
tonyandrewmeyer:fix-pyright-scenario-include

Conversation

@tonyandrewmeyer

@tonyandrewmeyer tonyandrewmeyer commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

The pyright include glob testing/src/*.py did not match the subdirectory where the scenario source actually lives (testing/src/scenario/*.py), so that tree was silently unchecked 😞 😢. Add the correct glob and fix the 122 (!) errors that surfaced.

Highlights of the fixes:

  • mocking.py — use dict(x) instead of .copy() on Mapping-typed state fields; cast where the runtime is a dict but the annotation is intentionally Mapping (relation databags, remote_grants).
  • context.py — drop dead type: ignore comments and default the derived app_name to '' so the existing bad-metadata tests still exercise the downstream failure path.
  • state.py — widen internal validator params to Mapping, split from_context()'s **kwargs TypedDict so it no longer overlaps with named parameters, annotate default_factory=dict fields with their element types, and replace the bare '' assigned to CheckInfo.change_id (ChangeID | None) with pebble.ChangeID('').
  • _runtime.py — replace deprecated Iterator return type with Generator, parameterise TemporaryDirectory, normalise Optional unit_id.
  • _consistency_checker.py — cast action-spec lookups through Any so pyright can resolve get()/items() types.
  • _ops_main_mock.py — initialise the loop variable before the try so the except branch never sees an unbound name.

Refs #2613

tonyandrewmeyer and others added 2 commits July 4, 2026 13:41
Since ops 3.8.0, Secret.remote_grants values are frozensets, but
secret_grant and secret_revoke still called .add() and .remove() on
them, raising AttributeError when a charm revoked a pre-existing
grant.

Replace the in-place mutations with reassignment using set operators.

Fixes canonical#2613
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The pyright \`include\` glob \`testing/src/*.py\` did not match the
subdirectory where the scenario source actually lives, so all of
testing/src/scenario/*.py was silently unchecked. Add the correct
glob and fix the errors that surfaced.

Notable fixes:
- mocking.py: use dict(x) instead of .copy() on Mapping-typed state
  fields; cast where the runtime is a dict but the annotation is
  intentionally Mapping (relation databags, remote_grants).
- context.py: raise on missing app_name derivation is deferred (via ''
  fallback) so existing tests can assert the downstream error path;
  drop dead type: ignore comments now that annotations are correct.
- state.py: widen internal helper params to Mapping to match callers,
  split from_context()'s **kwargs TypedDict so it no longer overlaps
  with named parameters, annotate default_factory=dict fields with
  their element types, replace the bare '' assigned to change_id (a
  ChangeID | None) with pebble.ChangeID('').
- _runtime.py: replace deprecated Iterator return type with Generator,
  parameterize TemporaryDirectory, normalise Optional unit_id.
- _consistency_checker.py: cast action spec lookups through Any so
  pyright can resolve get()/items() types.
- _ops_main_mock.py: initialise loop variable before the try block so
  the except branch never sees an unbound name.

Refs canonical#2613
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@tonyandrewmeyer tonyandrewmeyer changed the title fix(testing): Type-check testing/src/scenario and fix uncovered errors test: Type-check testing/src/scenario and fix uncovered errors Jul 4, 2026
Follow-up to the TypedDict rename in from_context(): update the
nitpick_ignore entry so the docs build stays clean.

Refs canonical#2613
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@tonyandrewmeyer tonyandrewmeyer changed the title test: Type-check testing/src/scenario and fix uncovered errors test: type-check testing/src/scenario and fix uncovered errors Jul 4, 2026
The type annotation was simplified to Sequence[Address], and Sphinx
correctly resolves it to ops.testing.Address, so the comment about
prefixing is no longer accurate.

Refs canonical#2613
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@dwilding dwilding left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I bet finding this was a bit of a shock. Thanks for fixing!

Comment thread testing/src/scenario/_ops_main_mock.py Outdated
Comment thread testing/src/scenario/context.py Outdated
Comment thread testing/src/scenario/state.py Outdated
Comment thread testing/src/scenario/mocking.py Outdated
Merge the two TYPE_CHECKING blocks in _ops_main_mock.py, clarify the
app_name fallback comment in context.py, reword the _StateKwargsRest
comment in state.py, and add a comment above the pyright ignores on
_MockPebbleClient._layers/_service_status explaining the design
constraint.

@tromai tromai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Comment thread testing/src/scenario/state.py
Comment thread testing/tests/test_e2e/test_secrets.py

@james-garner-canonical james-garner-canonical left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to just do a drive-by comment when I spotted a couple of things, but I ended up going through all the Scenario changes (not the tests).

Comment thread testing/src/scenario/_ops_main_mock.py Outdated
Comment thread testing/src/scenario/_consistency_checker.py Outdated
Comment thread testing/src/scenario/_ops_main_mock.py Outdated
Comment thread testing/src/scenario/_runtime.py
Comment thread testing/src/scenario/context.py Outdated
Comment thread testing/src/scenario/state.py
Comment thread testing/src/scenario/state.py Outdated
Comment thread testing/src/scenario/state.py
Comment thread testing/src/scenario/state.py Outdated
Comment thread testing/src/scenario/state.py Outdated
tonyandrewmeyer and others added 2 commits July 9, 2026 16:10
Apply james-garner-canonical's review suggestions: prefer pyright ignores
over defensive runtime conversions where the underlying value is known to
be a dict at runtime, drop unnecessary casts, and pipe CharmType through
Ops so Manager.charm no longer needs a cast.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…o-include

# Conflicts:
#	testing/src/scenario/mocking.py

@james-garner-canonical james-garner-canonical left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this, and for addressing my feedback. One minor comment where it wasn't possible to cleanly eliminate a cast by changing our internal typing, where we should probably use an ignore instead so we notice when it's no longer necessary.

Comment thread testing/src/scenario/mocking.py Outdated
Comment on lines +954 to +955
def _layers(self) -> dict[str, pebble.Layer]: # pyright: ignore[reportIncompatibleVariableOverride]
return cast('dict[str, pebble.Layer]', self._container.layers)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case I'd suggest an ignore and explanation so we get alerted when that's no longer necessary.

…rrides

Swap the cast() calls in the _MockPebbleClient._layers and
_service_status property overrides for reportReturnType ignores, so
pyright will flag them when Container.layers/service_statuses are
narrowed to dict and the override is no longer necessary.
@tonyandrewmeyer
tonyandrewmeyer merged commit 7552578 into canonical:main Jul 9, 2026
59 of 60 checks passed
@tonyandrewmeyer
tonyandrewmeyer deleted the fix-pyright-scenario-include branch July 9, 2026 13:03
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.

4 participants