Coverage for src/prisma/generator/jsonrpc.py: 94%
60 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-27 18:25 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-27 18:25 +0000
1from __future__ import annotations
3import sys
4import json
5import logging
6from typing import Any, Dict, List, Type, Union, Optional
7from pathlib import Path
8from typing_extensions import Literal, TypedDict
10from pydantic import Field
12from .models import BaseModel
13from .._compat import model_json
15log: logging.Logger = logging.getLogger(__name__)
18__all__ = ('Manifest',)
21class Request(BaseModel):
22 # JSON RPC protocol version
23 jsonrpc: str = '2.0'
25 # identifies a request
26 id: int
28 # request intention
29 method: str
31 # request payload
32 params: Optional[Dict[str, Any]] = None
35class SuccessResponse(BaseModel):
36 id: int
37 jsonrpc: str = '2.0'
38 result: Optional[Dict[str, Any]] = None
41class ErrorData(TypedDict):
42 code: int
43 message: str
44 data: object
47class ErrorResponse(BaseModel):
48 id: int
49 error: ErrorData
50 jsonrpc: str = '2.0'
53Response = Union[SuccessResponse, ErrorResponse]
55EngineType = Literal[
56 'prismaFmt',
57 'queryEngine',
58 'libqueryEngine',
59 'migrationEngine',
60 'introspectionEngine',
61]
64class Manifest(BaseModel):
65 """Generator metadata"""
67 prettyName: str = Field(alias='name')
68 defaultOutput: Union[str, Path] = Field(alias='default_output')
69 denylist: Optional[List[str]] = None
70 requiresEngines: Optional[List[EngineType]] = Field(alias='requires_engines', default=None)
71 requiresGenerators: Optional[List[str]] = Field(alias='requires_generators', default=None)
74# TODO: proper types
75method_mapping: Dict[str, Type[Request]] = {
76 'getManifest': Request,
77 'generate': Request,
78}
81def readline() -> Optional[str]:
82 try:
83 line = input()
84 except EOFError:
85 log.debug('Ignoring EOFError')
86 return None
88 return line
91def parse(line: str) -> Request:
92 log.debug('Parsing JSONRPC request line %s', line)
94 data = json.loads(line)
95 try:
96 method = data['method']
97 except (KeyError, TypeError):
98 # TODO
99 raise
100 else:
101 request_type = method_mapping.get(method)
102 if request_type is None: 102 ↛ 103line 102 didn't jump to line 103, because the condition on line 102 was never true
103 raise RuntimeError(f'Unknown method: {method}')
105 return request_type(**data)
108def reply(response: Response) -> None:
109 dumped = model_json(response) + '\n'
110 print(dumped, file=sys.stderr, flush=True) # noqa: T201
111 log.debug('Replied with %s', dumped)