Skip to content

ci: check httpbin-demo example charm with mypy#2339

Closed
james-garner-canonical wants to merge 7 commits intocanonical:mainfrom
james-garner-canonical:26-02+fix+testing-mypy
Closed

ci: check httpbin-demo example charm with mypy#2339
james-garner-canonical wants to merge 7 commits intocanonical:mainfrom
james-garner-canonical:26-02+fix+testing-mypy

Conversation

@james-garner-canonical
Copy link
Copy Markdown
Contributor

@james-garner-canonical james-garner-canonical commented Feb 23, 2026

This PR updates the httpbin-demo example charm to add mypy to its existing linting. I've verified that this linting fails with the reported error without the update to ops/testing.py made in #2343.

To keep this check current, I've updated tool.uv.sources for the charm to pull ops from the local files -- but this introduces a gotcha, since we'd need to relock every time we change the ops version. I've updated the release script to do this, but I wonder if we'd be better off adding a separate CI step instead.


We could add mypy to the linting for our other example charms, the K8s and machine tutorial charms. However, this wouldn't reflect what we actually want charmers to do when following the tutorial, so we shouldn't do so on disc. Instead, it would probably be cleaner to add a custom CI job like below. If we did so, we could use the same approach for the httpbin-demo charm. #2360 implements this approach.

@benhoyt
Copy link
Copy Markdown
Collaborator

benhoyt commented Feb 23, 2026

Excellent, thanks for this. Let's discuss in daily when Tony and Dima are both back (I've added it to the top of the doc).

@dimaqq
Copy link
Copy Markdown
Contributor

dimaqq commented Feb 24, 2026

my 2c: let's bite the bullet: merge, call it out in release notes, but don't bump the major version.

_compatibility_names = [
'CharmBase',
'CharmMeta',
'Container', # If Scenario has been installed, then this will be scenario.Container.
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.

Do we have containers in Harness, at all?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Harness exported the name Container (the object ops.model.Container) for a long time, and that was kept when we added Scenario to the ops.testing namespace to avoid breaking test code that (lazily / incorrectly) would use Container imported from there, like from ops.testing import Container, Harness, ....

Copy link
Copy Markdown
Collaborator

@tonyandrewmeyer tonyandrewmeyer left a comment

Choose a reason for hiding this comment

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

I don't like that this makes CI changes in the same PR (and that's not mentioned at all in the PR summary even though it's in the description). If we want to do that (and I think it's an entirely separate question) then I think it belongs in a dedicated PR.

@james-garner-canonical
Copy link
Copy Markdown
Contributor Author

james-garner-canonical commented Feb 25, 2026

I don't like that this makes CI changes in the same PR (and that's not mentioned at all in the PR summary even though it's in the description). If we want to do that (and I think it's an entirely separate question) then I think it belongs in a dedicated PR.

The CI changes are essentially tests that exercise fix in the PR and would fail on main without the fix.

EDIT: Updated PR summary to mention this.

@tonyandrewmeyer
Copy link
Copy Markdown
Collaborator

I don't like that this makes CI changes in the same PR (and that's not mentioned at all in the PR summary even though it's in the description). If we want to do that (and I think it's an entirely separate question) then I think it belongs in a dedicated PR.

The CI changes are essentially tests that exercise fix in the PR and would fail on main without the fix.

My concern here is that I think the CI change (basically that we are committing to some increased level of support for mypy) is the biggest change here, and adjusting ops.testing is the small side change being done to support that - but that's not how the PR summary or description is written.

If we are going to explicitly support mypy in this way, then I think that merits a dedicated discussion, and a dedicated PR. It can fail at first, or we can make this change first (without needing automated tests), or (my least favourite) with failing tests that we expect to resolve in a follow-up quickly afterwards.

I don't think it's the right approach to have the more significant change as a drive-by.

@james-garner-canonical
Copy link
Copy Markdown
Contributor Author

I don't like that this makes CI changes in the same PR (and that's not mentioned at all in the PR summary even though it's in the description). If we want to do that (and I think it's an entirely separate question) then I think it belongs in a dedicated PR.

The CI changes are essentially tests that exercise fix in the PR and would fail on main without the fix.

My concern here is that I think the CI change (basically that we are committing to some increased level of support for mypy) is the biggest change here, and adjusting ops.testing is the small side change being done to support that - but that's not how the PR summary or description is written.

If we are going to explicitly support mypy in this way, then I think that merits a dedicated discussion, and a dedicated PR. It can fail at first, or we can make this change first (without needing automated tests), or (my least favourite) with failing tests that we expect to resolve in a follow-up quickly afterwards.

I don't think it's the right approach to have the more significant change as a drive-by.

Happy to reframe the PR that way. I guess if we opt to merge #2343 (with manual verification) this PR can become CI changes only.

@benhoyt
Copy link
Copy Markdown
Collaborator

benhoyt commented Feb 27, 2026

Per discussion, change this PR to just "add mypy to the example charms".

tonyandrewmeyer added a commit that referenced this pull request Mar 2, 2026
…le checkers understand it (#2343)

Test code, based on the code in the Matrix thread, but fixed:

```python
from typing import Iterable

import ops
import ops.testing
import pytest

execs: Iterable[ops.testing.Exec] = set()


@pytest.fixture()
def mediawiki_container():
    return ops.testing.Container(
        name="mediawiki",
        can_connect=True,
        execs=execs,
    )


class TestPebbleReadyEvent:
    def test_can_connect(self, ctx: ops.testing.Context[ops.CharmBase], mediawiki_container: ops.testing.Container) -> None:
        state_in = ops.testing.State(containers=[mediawiki_container], leader=True)
        ctx.run(ctx.on.update_status(), state_in)
```

With main:

```
tameyer@tam-canoncial-1:~/w/operator$ uvx --with=pytest --with=ops[testing] mypy --follow-imports=silent /tmp/mypy_example.py                                  
/tmp/mypy_example.py:21: error: List item 0 has incompatible type "ops.model.Container"; expected "scenario.state.Container"  [list-item]
Found 1 error in 1 file (checked 1 source file)
tameyer@tam-canoncial-1:~/w/operator$ uvx --with=pytest --with=ops[testing] pyright /tmp/mypy_example.py 
0 errors, 0 warnings, 0 informations
```

With this branch:

```
tameyer@tam-canoncial-1:~/w/fix-mypy-testing-container$ uvx --with=pytest --with=ops[testing] mypy --follow-imports=silent /tmp/mypy_example.py 
Success: no issues found in 1 source file
tameyer@tam-canoncial-1:~/w/fix-mypy-testing-container$ uvx --with=pytest --with=ops[testing] pyright /tmp/mypy_example.py 
0 errors, 0 warnings, 0 informations
```

By moving the import from `ops.model` to the `except` block, type
checkers like mypy understand that it's one or the other. We also need a
`type: ignore` there because mypy otherwise complains about incompatible
imports.

This is an alternative to #2339.
@james-garner-canonical james-garner-canonical changed the title fix!: drop model.Container from ops.testing for mypy ci: check httpbin-demo example charm with mypy Mar 3, 2026
@james-garner-canonical
Copy link
Copy Markdown
Contributor Author

Closing in favour of:

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