|
28 | 28 | from .annotationhelper import _get_annotations, _set_annotations |
29 | 29 | from .bundle import BundleHandler, get_charm_series, is_local_charm |
30 | 30 | from .charmhub import CharmHub |
31 | | -from .client import client, connector |
32 | | -from .client.connection import Connection |
| 31 | +from .client import client, connection, connector |
33 | 32 | from .client.overrides import Caveat, Macaroon |
34 | 33 | from .constraints import parse as parse_constraints |
35 | 34 | from .controller import ConnectedController, Controller |
|
60 | 59 |
|
61 | 60 | if TYPE_CHECKING: |
62 | 61 | from .application import Application |
| 62 | + from .client._definitions import FullStatus |
63 | 63 | from .machine import Machine |
64 | 64 | from .relation import Relation |
65 | 65 | from .remoteapplication import ApplicationOffer, RemoteApplication |
@@ -267,7 +267,9 @@ def apply_delta(self, delta): |
267 | 267 | entity = self.get_entity(delta.entity, delta.get_id()) |
268 | 268 | return entity.previous(), entity |
269 | 269 |
|
270 | | - def get_entity(self, entity_type, entity_id, history_index=-1, connected=True): |
| 270 | + def get_entity( |
| 271 | + self, entity_type, entity_id, history_index=-1, connected=True |
| 272 | + ) -> ModelEntity | None: |
271 | 273 | """Return an object instance for the given entity_type and id. |
272 | 274 |
|
273 | 275 | By default the object state matches the most recent state from |
@@ -295,6 +297,11 @@ class ModelEntity: |
295 | 297 | """An object in the Model tree""" |
296 | 298 |
|
297 | 299 | entity_id: str |
| 300 | + model: Model |
| 301 | + _history_index: int |
| 302 | + connected: bool |
| 303 | + connection: connection.Connection |
| 304 | + _status: str |
298 | 305 |
|
299 | 306 | def __init__( |
300 | 307 | self, |
@@ -616,6 +623,9 @@ async def resolve( |
616 | 623 | class Model: |
617 | 624 | """The main API for interacting with a Juju model.""" |
618 | 625 |
|
| 626 | + connector: connector.Connector |
| 627 | + state: ModelState |
| 628 | + |
619 | 629 | def __init__( |
620 | 630 | self, |
621 | 631 | max_frame_size=None, |
@@ -660,7 +670,7 @@ def is_connected(self): |
660 | 670 | """Reports whether the Model is currently connected.""" |
661 | 671 | return self._connector.is_connected() |
662 | 672 |
|
663 | | - def connection(self) -> Connection: |
| 673 | + def connection(self) -> connection.Connection: |
664 | 674 | """Return the current Connection object. It raises an exception |
665 | 675 | if the Model is disconnected |
666 | 676 | """ |
@@ -914,7 +924,10 @@ def add_local_charm(self, charm_file, series="", size=None): |
914 | 924 | instead. |
915 | 925 |
|
916 | 926 | """ |
917 | | - conn, headers, path_prefix = self.connection().https_connection() |
| 927 | + connection = self.connection() |
| 928 | + assert connection |
| 929 | + |
| 930 | + conn, headers, path_prefix = connection.https_connection() |
918 | 931 | path = "%s/charms?series=%s" % (path_prefix, series) |
919 | 932 | headers["Content-Type"] = "application/zip" |
920 | 933 | if size: |
@@ -1212,11 +1225,12 @@ def name(self): |
1212 | 1225 | return self._info.name |
1213 | 1226 |
|
1214 | 1227 | @property |
1215 | | - def info(self): |
| 1228 | + def info(self) -> ModelInfo: |
1216 | 1229 | """Return the cached client.ModelInfo object for this Model. |
1217 | 1230 |
|
1218 | 1231 | If Model.get_info() has not been called, this will return None. |
1219 | 1232 | """ |
| 1233 | + assert self._info is not None |
1220 | 1234 | return self._info |
1221 | 1235 |
|
1222 | 1236 | @property |
@@ -1306,11 +1320,13 @@ async def _all_watcher(): |
1306 | 1320 | del allwatcher.Id |
1307 | 1321 | continue |
1308 | 1322 | except websockets.ConnectionClosed: |
1309 | | - monitor = self.connection().monitor |
| 1323 | + connection = self.connection() |
| 1324 | + assert connection |
| 1325 | + monitor = connection.monitor |
1310 | 1326 | if monitor.status == monitor.ERROR: |
1311 | 1327 | # closed unexpectedly, try to reopen |
1312 | 1328 | log.warning("Watcher: connection closed, reopening") |
1313 | | - await self.connection().reconnect() |
| 1329 | + await connection.reconnect() |
1314 | 1330 | if monitor.status != monitor.CONNECTED: |
1315 | 1331 | # reconnect failed; abort and shutdown |
1316 | 1332 | log.error( |
@@ -2624,7 +2640,7 @@ async def get_action_status(self, uuid_or_prefix=None, name=None): |
2624 | 2640 | results[tag.untag("action-", a.action.tag)] = a.status |
2625 | 2641 | return results |
2626 | 2642 |
|
2627 | | - async def get_status(self, filters=None, utc=False): |
| 2643 | + async def get_status(self, filters=None, utc=False) -> FullStatus: |
2628 | 2644 | """Return the status of the model. |
2629 | 2645 |
|
2630 | 2646 | :param str filters: Optional list of applications, units, or machines |
@@ -2959,15 +2975,15 @@ async def _get_source_api(self, url): |
2959 | 2975 | async def wait_for_idle( |
2960 | 2976 | self, |
2961 | 2977 | apps: list[str] | None = None, |
2962 | | - raise_on_error=True, |
2963 | | - raise_on_blocked=False, |
2964 | | - wait_for_active=False, |
2965 | | - timeout=10 * 60, |
2966 | | - idle_period=15, |
2967 | | - check_freq=0.5, |
2968 | | - status=None, |
2969 | | - wait_for_at_least_units=None, |
2970 | | - wait_for_exact_units=None, |
| 2978 | + raise_on_error: bool = True, |
| 2979 | + raise_on_blocked: bool = False, |
| 2980 | + wait_for_active: bool = False, |
| 2981 | + timeout: float | None = 10 * 60, |
| 2982 | + idle_period: float = 15, |
| 2983 | + check_freq: float = 0.5, |
| 2984 | + status: str | None = None, |
| 2985 | + wait_for_at_least_units: int | None = None, |
| 2986 | + wait_for_exact_units: int | None = None, |
2971 | 2987 | ) -> None: |
2972 | 2988 | """Wait for applications in the model to settle into an idle state. |
2973 | 2989 |
|
@@ -3035,12 +3051,12 @@ async def wait_for_idle( |
3035 | 3051 | raise JujuError(f"Expected a List[str] for apps, given {apps}") |
3036 | 3052 |
|
3037 | 3053 | apps = apps or self.applications |
3038 | | - idle_times = {} |
3039 | | - units_ready = set() # The units that are in the desired state |
3040 | | - last_log_time = None |
| 3054 | + idle_times: dict[str, datetime] = {} |
| 3055 | + units_ready: set[str] = set() # The units that are in the desired state |
| 3056 | + last_log_time: datetime | None = None |
3041 | 3057 | log_interval = timedelta(seconds=30) |
3042 | 3058 |
|
3043 | | - def _raise_for_status(entities, status): |
| 3059 | + def _raise_for_status(entities: dict[str, list[str]], status: Any): |
3044 | 3060 | if not entities: |
3045 | 3061 | return |
3046 | 3062 | for entity_name, error_type in ( |
|
0 commit comments