Skip to content

Commit 03e7d51

Browse files
committed
feat: new Model.wait_for_idle()
1 parent 9b4e411 commit 03e7d51

16 files changed

Lines changed: 1423 additions & 98 deletions

.github/workflows/test.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ jobs:
7878
- "3.4/stable"
7979
- "3.5/stable"
8080
- "3.6/stable"
81+
new_wait_for_idle:
82+
- "True"
83+
- "False"
8184
steps:
8285
- uses: actions/checkout@v4
8386
- uses: actions/setup-python@v5
@@ -116,7 +119,9 @@ jobs:
116119
# # set model defaults
117120
# juju model-defaults apt-http-proxy=$PROXY apt-https-proxy=$PROXY juju-http-proxy=$PROXY juju-https-proxy=$PROXY snap-http-proxy=$PROXY snap-https-proxy=$PROXY
118121
# juju model-defaults
119-
- run: uvx -p ${{ matrix.python }} tox -e integration
122+
- run: uvx -p ${{ matrix.python }} tox -s -e integration
123+
env:
124+
JUJU_NEW_WAIT_FOR_IDLE: ${{ matrix.new_wait_for_idle }}
120125

121126
integration-quarantine:
122127
name: Quarantined Integration Tests
@@ -144,4 +149,4 @@ jobs:
144149
with:
145150
provider: lxd
146151
juju-channel: ${{ matrix.juju }}
147-
- run: uvx -p ${{ matrix.python }} tox -e integration-quarantine
152+
- run: uvx -p ${{ matrix.python }} tox -s -e integration-quarantine

juju/client/facade.py

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from collections import defaultdict
1515
from glob import glob
1616
from pathlib import Path
17-
from typing import Any, Mapping, Sequence
17+
from typing import Any, Mapping, Sequence, TypeVar, overload
1818

1919
import packaging.version
2020
import typing_inspect
@@ -183,7 +183,7 @@ def ref_type(self, obj):
183183
return self.get_ref_type(obj["$ref"])
184184

185185

186-
CLASSES = {}
186+
CLASSES: dict[str, type[Type]] = {}
187187
factories = codegen.Capture()
188188

189189

@@ -479,37 +479,48 @@ def ReturnMapping(cls): # noqa: N802
479479
def decorator(f):
480480
@functools.wraps(f)
481481
async def wrapper(*args, **kwargs):
482-
nonlocal cls
483482
reply = await f(*args, **kwargs)
484-
if cls is None:
485-
return reply
486-
if "error" in reply:
487-
cls = CLASSES["Error"]
488-
if typing_inspect.is_generic_type(cls) and issubclass(
489-
typing_inspect.get_origin(cls), Sequence
490-
):
491-
parameters = typing_inspect.get_parameters(cls)
492-
result = []
493-
item_cls = parameters[0]
494-
for item in reply:
495-
result.append(item_cls.from_json(item))
496-
"""
497-
if 'error' in item:
498-
cls = CLASSES['Error']
499-
else:
500-
cls = item_cls
501-
result.append(cls.from_json(item))
502-
"""
503-
else:
504-
result = cls.from_json(reply["response"])
505-
506-
return result
483+
return _convert_response(reply, cls=cls)
507484

508485
return wrapper
509486

510487
return decorator
511488

512489

490+
@overload
491+
def _convert_response(response: dict[str, Any], *, cls: type[SomeType]) -> SomeType: ...
492+
493+
494+
@overload
495+
def _convert_response(response: dict[str, Any], *, cls: None) -> dict[str, Any]: ...
496+
497+
498+
def _convert_response(response: dict[str, Any], *, cls: type[Type] | None) -> Any:
499+
if cls is None:
500+
return response
501+
if "error" in response:
502+
cls = CLASSES["Error"]
503+
if typing_inspect.is_generic_type(cls) and issubclass(
504+
typing_inspect.get_origin(cls), Sequence
505+
):
506+
parameters = typing_inspect.get_parameters(cls)
507+
result = []
508+
item_cls = parameters[0]
509+
for item in response:
510+
result.append(item_cls.from_json(item))
511+
"""
512+
if 'error' in item:
513+
cls = CLASSES['Error']
514+
else:
515+
cls = item_cls
516+
result.append(cls.from_json(item))
517+
"""
518+
else:
519+
result = cls.from_json(response["response"])
520+
521+
return result
522+
523+
513524
def make_func(cls, name, description, params, result, _async=True):
514525
indent = " "
515526
args = Args(cls.schema, params)
@@ -663,7 +674,7 @@ async def rpc(self, msg: dict[str, _RichJson]) -> _Json:
663674
return result
664675

665676
@classmethod
666-
def from_json(cls, data):
677+
def from_json(cls, data: Type | str | dict[str, Any] | list[Any]) -> Type | None:
667678
def _parse_nested_list_entry(expr, result_dict):
668679
if isinstance(expr, str):
669680
if ">" in expr or ">=" in expr:
@@ -742,6 +753,9 @@ def get(self, key, default=None):
742753
return getattr(self, attr, default)
743754

744755

756+
SomeType = TypeVar("SomeType", bound=Type)
757+
758+
745759
class Schema(dict):
746760
def __init__(self, schema):
747761
self.name = schema["Name"]

0 commit comments

Comments
 (0)