Skip to content

Commit b5455a5

Browse files
committed
Tidy + type annotations
1 parent 0979bd1 commit b5455a5

7 files changed

+108
-61
lines changed

cylc/uiserver/data_store_mgr.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from functools import partial
3838
from pathlib import Path
3939
import time
40+
from typing import Optional
4041

4142
from cylc.flow.id import Tokens
4243
from cylc.flow.network.server import PB_METHOD_MAP
@@ -361,12 +362,11 @@ def reconcile_update(self, topic, delta, w_id):
361362
except Exception as exc:
362363
self.log.exception(exc)
363364

364-
async def entire_workflow_update(self, ids=None):
365+
async def entire_workflow_update(self, ids: Optional[list] = None) -> None:
365366
"""Update entire local data-store of workflow(s).
366367
367368
Args:
368-
ids (list): List of workflow external IDs.
369-
369+
ids: List of workflow external IDs.
370370
371371
"""
372372
if ids is None:

cylc/uiserver/handlers.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import json
1919
import getpass
2020
import socket
21-
from typing import Callable, Union
21+
from typing import TYPE_CHECKING, Callable, Union
2222

2323
from graphene_tornado.tornado_graphql_handler import TornadoGraphQLHandler
2424
from graphql import get_default_backend
@@ -35,6 +35,9 @@
3535
from cylc.uiserver.authorise import Authorization, AuthorizationMiddleware
3636
from cylc.uiserver.websockets import authenticated as websockets_authenticated
3737

38+
if TYPE_CHECKING:
39+
from graphql.execution import ExecutionResult
40+
3841

3942
ME = getpass.getuser()
4043

@@ -337,8 +340,8 @@ def context(self):
337340
def prepare(self):
338341
super().prepare()
339342

340-
@web.authenticated
341-
async def execute(self, *args, **kwargs):
343+
@web.authenticated # type: ignore[arg-type]
344+
async def execute(self, *args, **kwargs) -> 'ExecutionResult':
342345
# Use own backend, and TornadoGraphQLHandler already does validation.
343346
return await self.schema.execute(
344347
*args,

cylc/uiserver/resolvers.py

+46-15
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,22 @@
1919
import os
2020
from copy import deepcopy
2121
from subprocess import Popen, PIPE, DEVNULL
22+
from typing import (
23+
TYPE_CHECKING, Any, Dict, Iterable, List, Union
24+
)
2225

2326
from graphql.language.base import print_ast
2427

25-
from cylc.flow.network.resolvers import BaseResolvers
2628
from cylc.flow.data_store_mgr import WORKFLOW
29+
from cylc.flow.network.resolvers import BaseResolvers
30+
31+
32+
if TYPE_CHECKING:
33+
from logging import Logger
34+
from graphql import ResolveInfo
35+
from cylc.flow.data_store_mgr import DataStoreMgr
36+
from cylc.flow.id import Tokens
37+
from cylc.uiserver.workflows_mgr import WorkflowsManager
2738

2839

2940
# show traceback from cylc commands
@@ -180,33 +191,47 @@ async def play(cls, workflows, args, workflows_mgr, log):
180191
class Resolvers(BaseResolvers):
181192
"""UI Server context GraphQL query and mutation resolvers."""
182193

183-
workflows_mgr = None
184-
185-
def __init__(self, data, log, **kwargs):
194+
def __init__(
195+
self,
196+
data: 'DataStoreMgr',
197+
log: 'Logger',
198+
workflows_mgr: 'WorkflowsManager',
199+
**kwargs
200+
):
186201
super().__init__(data)
187202
self.log = log
203+
self.workflows_mgr = workflows_mgr
188204

189205
# Set extra attributes
190206
for key, value in kwargs.items():
191207
if hasattr(self, key):
192208
setattr(self, key, value)
193209

194210
# Mutations
195-
async def mutator(self, info, *m_args):
211+
async def mutator(
212+
self,
213+
info: 'ResolveInfo',
214+
command: str,
215+
w_args: Dict[str, Any],
216+
_kwargs: Dict[str, Any],
217+
_meta: Dict[str, Any]
218+
) -> List[Dict[str, Any]]:
196219
"""Mutate workflow."""
197-
req_meta = {}
198-
_, w_args, _, _ = m_args
199-
req_meta['auth_user'] = info.context.get(
200-
'current_user', 'unknown user')
220+
req_meta = {
221+
'auth_user': info.context.get( # type: ignore[union-attr]
222+
'current_user', 'unknown user'
223+
)
224+
}
201225
w_ids = [
202226
flow[WORKFLOW].id
203227
for flow in await self.get_workflows_data(w_args)]
204228
if not w_ids:
205229
return [{
206230
'response': (False, 'No matching workflows')}]
207231
# Pass the request to the workflow GraphQL endpoints
208-
_, variables, _, _ = info.context.get('graphql_params')
209-
232+
_, variables, _, _ = info.context.get( # type: ignore[union-attr]
233+
'graphql_params'
234+
)
210235
# Create a modified request string,
211236
# containing only the current mutation/field.
212237
operation_ast = deepcopy(info.operation)
@@ -216,14 +241,20 @@ async def mutator(self, info, *m_args):
216241
'request_string': print_ast(operation_ast),
217242
'variables': variables,
218243
}
219-
return await self.workflows_mgr.multi_request(
244+
return await self.workflows_mgr.multi_request( # type: ignore # TODO
220245
'graphql', w_ids, graphql_args, req_meta=req_meta
221246
)
222247

223-
async def service(self, info, *m_args):
248+
async def service(
249+
self,
250+
info: 'ResolveInfo',
251+
command: str,
252+
workflows: Iterable['Tokens'],
253+
kwargs: Dict[str, Any]
254+
) -> List[Union[bool, str]]:
224255
return await Services.play(
225-
m_args[1]['workflows'],
226-
m_args[2],
256+
workflows,
257+
kwargs,
227258
self.workflows_mgr,
228259
log=self.log
229260
)

cylc/uiserver/schema.py

+22-14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"""
2121

2222
from functools import partial
23+
from typing import TYPE_CHECKING, Any, List, Optional
2324

2425
import graphene
2526
from graphene.types.generic import GenericScalar
@@ -36,25 +37,32 @@
3637
sstrip,
3738
)
3839

40+
if TYPE_CHECKING:
41+
from graphql import ResolveInfo
42+
from cylc.uiserver.resolvers import Resolvers
3943

40-
async def mutator(root, info, command=None, workflows=None,
41-
exworkflows=None, **args):
44+
45+
async def mutator(
46+
root: Optional[Any],
47+
info: 'ResolveInfo',
48+
*,
49+
command: str,
50+
workflows: Optional[List[str]] = None,
51+
**kwargs: Any
52+
):
4253
"""Call the resolver method that act on the workflow service
4354
via the internal command queue."""
4455
if workflows is None:
4556
workflows = []
46-
if exworkflows is None:
47-
exworkflows = []
48-
w_args = {
49-
'workflows': [Tokens(w_id) for w_id in workflows],
50-
'exworkflows': [Tokens(w_id) for w_id in exworkflows],
51-
}
52-
if args.get('args', False):
53-
args.update(args.get('args', {}))
54-
args.pop('args')
55-
56-
resolvers = info.context.get('resolvers')
57-
res = await resolvers.service(info, command, w_args, args)
57+
parsed_workflows = [Tokens(w_id) for w_id in workflows]
58+
if kwargs.get('args', False):
59+
kwargs.update(kwargs.get('args', {}))
60+
kwargs.pop('args')
61+
62+
resolvers: 'Resolvers' = (
63+
info.context.get('resolvers') # type: ignore[union-attr]
64+
)
65+
res = await resolvers.service(info, command, parsed_workflows, kwargs)
5866
return GenericResponse(result=res)
5967

6068

cylc/uiserver/tests/conftest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@
3434
PbWorkflow,
3535
PbFamilyProxy,
3636
)
37-
from cylc.flow.network import ZMQSocketBase
37+
from cylc.flow.network.client import WorkflowRuntimeClient
3838
from cylc.flow.workflow_files import ContactFileFields as CFF
3939

4040
from cylc.uiserver.data_store_mgr import DataStoreMgr
4141
from cylc.uiserver.workflows_mgr import WorkflowsManager
4242

4343

44-
class AsyncClientFixture(ZMQSocketBase):
44+
class AsyncClientFixture(WorkflowRuntimeClient):
4545
pattern = zmq.REQ
4646
host = ''
4747
port = 0

cylc/uiserver/tests/test_workflows_mgr.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ async def test_workflow_request_client_timeout(
4848
async_client.will_return(ClientTimeout)
4949
ctx, msg = await workflow_request(client=async_client, command='')
5050
assert not ctx
51-
assert 'timeout' in msg.lower()
51+
assert 'timeout' in msg.lower() # type: ignore[attr-defined]
5252

5353

5454
@pytest.mark.asyncio

cylc/uiserver/workflows_mgr.py

+28-23
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@
2626
from contextlib import suppress
2727
from getpass import getuser
2828
import sys
29+
from typing import (
30+
TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple
31+
)
2932

3033
import zmq.asyncio
3134

3235
from cylc.flow.id import Tokens
3336
from cylc.flow.exceptions import ClientError, ClientTimeout
34-
from cylc.flow.network import API
37+
from cylc.flow.network import API, MSG_TIMEOUT
3538
from cylc.flow.network.client import WorkflowRuntimeClient
36-
from cylc.flow.network import MSG_TIMEOUT
3739
from cylc.flow.network.scan import (
3840
api_version,
3941
contact_info,
@@ -42,32 +44,35 @@
4244
)
4345
from cylc.flow.workflow_files import ContactFileFields as CFF
4446

47+
if TYPE_CHECKING:
48+
from logging import Logger
49+
50+
4551
CLIENT_TIMEOUT = 2.0
4652

4753

4854
async def workflow_request(
49-
client,
50-
command,
51-
args=None,
52-
timeout=None,
53-
req_context=None,
55+
client: WorkflowRuntimeClient,
56+
command: str,
57+
args: Optional[Dict[str, Any]] = None,
58+
timeout: Optional[float] = None,
59+
req_context: Optional[str] = None,
5460
*,
55-
log=None,
56-
req_meta=None
57-
):
61+
log: Optional['Logger'] = None,
62+
req_meta: Optional[Dict[str, Any]] = None
63+
) -> Tuple[str, object]:
5864
"""Workflow request command.
5965
6066
Args:
61-
client (WorkflowRuntimeClient): Instantiated workflow client.
62-
command (str): Command/Endpoint name.
63-
args (dict): Endpoint arguments.
64-
timeout (float): Client request timeout (secs).
65-
req_context (str): A string to identifier.
66-
req_meta (dict): Meta data related to request, e.g. auth_user
67+
client: Instantiated workflow client.
68+
command: Command/Endpoint name.
69+
args: Endpoint arguments.
70+
timeout: Client request timeout (secs).
71+
req_context: A string to identifier.
72+
req_meta: Meta data related to request, e.g. auth_user
6773
6874
Returns:
6975
tuple: (req_context, result)
70-
7176
"""
7277
if req_context is None:
7378
req_context = command
@@ -277,13 +282,13 @@ async def update(self):
277282

278283
async def multi_request(
279284
self,
280-
command,
281-
workflows,
282-
args=None,
283-
multi_args=None,
285+
command: str,
286+
workflows: Iterable[str],
287+
args: Optional[Dict[str, Any]] = None,
288+
multi_args: Optional[Dict[str, Any]] = None,
284289
timeout=None,
285-
req_meta=None
286-
):
290+
req_meta: Optional[Dict[str, Any]] = None
291+
) -> List[object]:
287292
"""Send requests to multiple workflows."""
288293
if args is None:
289294
args = {}

0 commit comments

Comments
 (0)