Skip to content

Conversation

@tonyandrewmeyer
Copy link
Collaborator

testing/tests is added to the files that pyright should check, and the files that are left to do are added to the exclusion list.

Add type annotations to half of the test_e2e test files (the other half are in another PR, #2234).

The class variable gets adjusted in the ruff fixes PR, but we can handle the merge conflict later.
The type: ignore should be able to go away when the storage class gets annotations, which is in another PR in this series. We can handle the merge then.
The class vars are being adjusted in another PR. We can handle the merge later.
The storage type ignore we should be able to remove after the other PRs are merged.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends type checking coverage to the ops-scenario test suite by adding type annotations to half of the test_e2e test files and configuring pyright to check them. The remaining files are explicitly excluded until a follow-up PR.

Key Changes

  • Added type annotations to test functions, fixtures, and event handlers across 9 test files
  • Updated pyright configuration to include testing/tests directory while excluding files not yet annotated
  • Added necessary type narrowing assertions where types could be None

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
pyproject.toml Added testing/tests to pyright includes and specified exclusions for unannotated files
test_storage.py Added type annotations to fixtures and test functions; added type ignore comments for filesystem operations
test_status.py Added EventBase import and return type annotations for all event handlers and test functions
test_secrets.py Added comprehensive type annotations including Literal types for owner parameters and type narrowing assertions
test_rubbish_events.py Added ClassVar annotations for class attributes and type annotations for test functions
test_relations.py Moved StateValidationError import to errors module; added type annotations and cast operations for dynamic types
test_ports.py Moved StateValidationError import to errors module; added return type annotations
test_pebble.py Added TYPE_CHECKING block for LayerDict/ServiceDict; corrected period/timeout to string format; added type annotations throughout
test_manager.py Moved AlreadyEmittedError import to errors module; added type annotations for fixtures and tests
test_juju_log.py Added type annotations to fixtures and test functions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@benhoyt
Copy link
Collaborator

benhoyt commented Dec 14, 2025

Thanks for doing these. Out of interest, did you use a tool to help automate these?

@tonyandrewmeyer
Copy link
Collaborator Author

Thanks for doing these. Out of interest, did you use a tool to help automate these?

Not an agent, but I did use the tab-completion functionality in VS Code a reasonable amount. I find it's particularly useful when what you're doing is very repetitive like this was.

Not sure if you remember or not, but I tried getting Copilot to do this work in the Gothenburg workshop (and then over the following days) and it did a terrible job. I still feel that an agent ought to be able to do this and that I probably just needed a different prompt or configuration, but I wasn't willing to spend more time on that with this ticket.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@benhoyt
Copy link
Collaborator

benhoyt commented Dec 14, 2025

Not an agent, but I did use the tab-completion functionality in VS Code a reasonable amount. I find it's particularly useful when what you're doing is very repetitive like this was.

Not sure if you remember or not, but I tried getting Copilot to do this work...

Yeah, I did remember. I was more curious about whether you'd used a mechanical tool like https://github.com/orsinium-labs/infer-types (have no idea whether it works or is any good).

@tonyandrewmeyer
Copy link
Collaborator Author

I was more curious about whether you'd used a mechanical tool like https://github.com/orsinium-labs/infer-types (have no idea whether it works or is any good).

Ah, interesting. I wasn't aware of such tools, otherwise I probably would have given one a go :)

def mycharm():
class MyCharm(CharmBase):
META = {'name': 'mycharm'}
META: dict[str, Any] = {'name': 'mycharm'}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think the type annotations on the META and ACTIONS attributes get us anything right now tbh. Though why aren't we getting complaints about mutable class attributes needing ClassVar? If we do annotate these it should probably be Mapping[str, Any]. And we should investigate why we're not getting the ClassVar complaint.

Copy link
Contributor

@james-garner-canonical james-garner-canonical Dec 15, 2025

Choose a reason for hiding this comment

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

Kind of superseded by lifting these to the top-level if we can do that, see other comment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think the ClassVar bit comes from ruff, not from pyright. There's overlap here with #2228

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah maybe that's where all the deja vu is coming from. Could we perhaps merge #2228 before working further on these then?



def test_manager(mycharm):
def test_manager(mycharm: Any) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

WDYT about lifting MyCharm and its META and ACTIONS attributes to the top-level like we did for canonical/grafana-agent-operator#355?

I guess this PR will need the -> None annotations stripped as well.


@pytest.mark.parametrize('evt_name', ('rubbish', 'foo', 'bar'))
def test_rubbish_event_raises(mycharm: CharmBase, evt_name: str):
def test_rubbish_event_raises(mycharm: type[CharmBase], evt_name: str):
Copy link
Contributor

Choose a reason for hiding this comment

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

question: why are we not changing CharmBase to ops.CharmBase in this file? Is it because it's covered by another PR?

P.S. I wonder if a type alias for type[ops.CharmBase] would be handy here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was trying to avoid doing the change from from ops import CharmBase to import ops as much as possible to keep the size/scope down. I was originally just doing it when there was a new import needed (most often Framework). Then when I merged in the ruff PR there were a bunch of merge conflicts in most of the imports so I also simplified those.

I guess I could uniformly make this change, but I think it would probably be better as a separate PR, and it would be nice if it was after this one so I don't have to redo those changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 on leaving it for a separate PR

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 on leaving it for a separate PR

return infos

def get_filesystem(self, ctx: Context) -> pathlib.Path:
def get_filesystem(self, ctx: Context[CharmBase]) -> pathlib.Path:
Copy link
Contributor

Choose a reason for hiding this comment

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

Has this become ctx: Context[Any] in the other PR?

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