From 91fef2ab90e0893b411dd439fb88d373948e574e Mon Sep 17 00:00:00 2001 From: Tony Meyer Date: Tue, 27 Aug 2024 08:45:18 +1200 Subject: [PATCH] chore: add compatibility with the next ops release (#178) The next release of ops has some backwards-incompatible changes to private methods. This PR does the minimum to keep Scenario working with the current version of ops and the next release. I'll open a ticket for doing a nicer version of this where the new `_JujuContext` class is used (which would presumably mean requiring the new version of ops). But this will let people continue upgrading their ops as long as they're using the latest 6.x of Scenario. The relevant ops PR is: https://github.com/canonical/operator/pull/1313 --- pyproject.toml | 2 +- scenario/ops_main_mock.py | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f83a1011..4fbb741c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "ops-scenario" -version = "6.1.5" +version = "6.1.6" authors = [ { name = "Pietro Pasotti", email = "pietro.pasotti@canonical.com" } diff --git a/scenario/ops_main_mock.py b/scenario/ops_main_mock.py index b18c7f02..8b2845c8 100644 --- a/scenario/ops_main_mock.py +++ b/scenario/ops_main_mock.py @@ -3,6 +3,7 @@ # See LICENSE file for licensing details. import inspect import os +import pathlib import sys from typing import TYPE_CHECKING, Any, Optional, Sequence, cast @@ -15,7 +16,7 @@ from ops.log import setup_root_logging # use logger from ops.main so that juju_log will be triggered -from ops.main import CHARM_STATE_FILE, _Dispatcher, _get_charm_dir, _get_event_args +from ops.main import CHARM_STATE_FILE, _Dispatcher, _get_event_args from ops.main import logger as ops_logger if TYPE_CHECKING: # pragma: no cover @@ -33,6 +34,17 @@ class BadOwnerPath(RuntimeError): """Error raised when the owner path does not lead to a valid ObjectEvents instance.""" +# TODO: Use ops.jujucontext's _JujuContext.charm_dir. +def _get_charm_dir(): + charm_dir = os.environ.get("JUJU_CHARM_DIR") + if charm_dir is None: + # Assume $JUJU_CHARM_DIR/lib/op/main.py structure. + charm_dir = pathlib.Path(f"{__file__}/../../..").resolve() + else: + charm_dir = pathlib.Path(charm_dir).resolve() + return charm_dir + + def _get_owner(root: Any, path: Sequence[str]) -> ops.ObjectEvents: """Walk path on root to an ObjectEvents instance.""" obj = root @@ -75,7 +87,17 @@ def _emit_charm_event( f"Use Context.run_custom instead.", ) - args, kwargs = _get_event_args(charm, event_to_emit) + try: + args, kwargs = _get_event_args(charm, event_to_emit) + except TypeError: + # ops 2.16+ + import ops.jujucontext # type: ignore + + args, kwargs = _get_event_args( + charm, + event_to_emit, + ops.jujucontext._JujuContext.from_dict(os.environ), # type: ignore + ) ops_logger.debug("Emitting Juju event %s.", event_name) event_to_emit.emit(*args, **kwargs) @@ -159,7 +181,16 @@ def setup(state: "State", event: "Event", context: "Context", charm_spec: "_Char charm_class = charm_spec.charm_type charm_dir = _get_charm_dir() - dispatcher = _Dispatcher(charm_dir) + try: + dispatcher = _Dispatcher(charm_dir) + except TypeError: + # ops 2.16+ + import ops.jujucontext # type: ignore + + dispatcher = _Dispatcher( + charm_dir, + ops.jujucontext._JujuContext.from_dict(os.environ), # type: ignore + ) dispatcher.run_any_legacy_hook() framework = setup_framework(charm_dir, state, event, context, charm_spec)