Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: use ops._main._Manager in Scenario #1491

Merged

Conversation

tonyandrewmeyer
Copy link
Contributor

@tonyandrewmeyer tonyandrewmeyer commented Dec 3, 2024

The ops._main._Manager class started out as the Ops class in Scenario, but went through significant modifications before it was added in ops. This PR merges those changes back into Scenario, so that it's also using the _Manager class. Other than generally simplifying the code, this also means that Scenario is even more consistent with using ops in production.

This includes some small refactoring in ops to make this cleaner:

  • ops._main._emit_charm_event is only used by _Manager, so logically belongs inside that class. This also makes it much simpler to have a subclass override the behaviour.
  • Allow passing a JujuContext to _Manager, so that it can be populated by something other than os.environ.
  • Allow _Manager subclasses to override how the charm metadata is loaded.
  • Allow _Manager subclasses to execute code after committing but before the framework is closed.
  • Support a dispatch path that uses _ rather than - in event names (Scenario consistently uses _, even though this would always be - from Juju - feel free to push back on this, requiring Scenario to undo the _ conversion when populating the context).

The Scenario runtime and ops_main_mock modules are renamed to properly indicate that everything inside of them is an implementation detail and should be considered private by Scenario users. This is a breaking change but we're considering it a bug fix and not one that requires a major release, given that the documentation and top-level namespace were already clear on this. Note that the first commit does the rename and nothing else - but GitHub shows only one of the files as a rename (I think because too much content has then changed). It might be easier to read through the commits separately when reviewing.

Significant Scenario refactoring:

  • UnitStateDB is moved from runtime to ops_main_mock, and it no longer (re) opens the SQLiteStorage - it instead takes a reference to the one that's in the framework, so that we're consistently using the same underlying storage, without relying on the filename being consistent (this eases moving to :memory: in the future).
  • As far as I can tell, runtime._OpsMainContext is completely unused and missed being removed in previous refactoring, so it's entirely deleted.
  • Loading and storing deferred events and stored state into the state database is moved from the runtime to the manager subclass.
  • The Ops class survives, but is now a subclass of the ops._main._Manager class. A reasonable amount of functionality is now removed (because the parent handles it), and the remaining code is specifically for handling the testing framework.

A few type hints are added in some tests where I was working on fixing the test and it helped to do that.

Fixes #1425

@tonyandrewmeyer tonyandrewmeyer changed the title Use ops manager take 3 refactor!: use ops._main._Manager in Scenario Dec 3, 2024
@tonyandrewmeyer
Copy link
Contributor Author

I had thought this might break #1445, but I seem to still get auto-completion for mgr.charm attributes with the branch, and pyright still finds bad typing with mgr.charm attributes, so it seems to be ok.

@tonyandrewmeyer tonyandrewmeyer marked this pull request as ready for review December 4, 2024 08:15
Copy link
Contributor

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

Choose a reason for hiding this comment

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

Looks good!

@@ -1,4 +1,5 @@
import copy
import typing
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a blocker.

  1. Should we use from __future__ import annotations instead? With type and list.
  2. If not, do we want import typing or from typing import List, Type ...?

I'm fine with leaving it as is for now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have #1336 - I'm not sure if we want to do individual modules before that or not.

In terms of the import style, I interpreted the guide as saying that objects can be imported from typing, not that they must or should be, but that's not clear, so maybe I'm wrong there.

Copy link
Contributor

Choose a reason for hiding this comment

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

my 2c: incremental future annotations are great.

class MyCharm(CharmBase):
on = _CharmEvents()
class MyCharm(ops.CharmBase):
on = _CharmEvents() # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a blocker. Is looking into making this type: ignore unnecessary something we'd want to do in future? (I haven't looked at how on is typed recently)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Potentially, yes. It has an ignore in the main definition plus gets redefined when type checking. I'm sure we could do better.

Copy link
Collaborator

@benhoyt benhoyt left a comment

Choose a reason for hiding this comment

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

Looks good, thanks!

testing/src/scenario/_consistency_checker.py Outdated Show resolved Hide resolved
@tonyandrewmeyer tonyandrewmeyer merged commit 0ad731a into canonical:main Dec 9, 2024
32 checks passed
@tonyandrewmeyer tonyandrewmeyer deleted the use-ops-manager-take-3 branch December 9, 2024 01:42
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.

Remove testing.Ops, use ops.main.Manager instead
4 participants