Skip to content

Commit fc1a6ae

Browse files
authored
Merge pull request #129 from dapper91/dev
- pydantic v1 validator/generator bugs fixed. - aiohttp subapp specification wrong method path fixed. - dispatcher middleware invocation order fixed. - documentation fixed.
2 parents e6714d6 + 88ca831 commit fc1a6ae

File tree

9 files changed

+38
-25
lines changed

9 files changed

+38
-25
lines changed

CHANGELOG.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ Changelog
22
=========
33

44

5+
2.0.1 (2025-10-28)
6+
-------------------
7+
8+
- pydantic v1 validator/generator bugs fixed.
9+
- aiohttp subapp specification wrong method path fixed.
10+
- dispatcher middleware invocation order fixed.
11+
- documentation fixed.
12+
13+
514
2.0.0 (2025-10-24)
615
-------------------
716

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,9 +634,9 @@ and Swagger UI web tool with basic auth:
634634
635635
636636
637-
Specification is available on http://localhost:8080/rpc/api/v1/openapi.json
637+
Specification is available on http://localhost:8080/rpc/api/openapi.json
638638

639-
Web UI is running on http://localhost:8080/rpc/api/v1/swagger/ and http://localhost:8080/rpc/api/v1/redoc/
639+
Web UI is running on http://localhost:8080/rpc/api/swagger/ and http://localhost:8080/rpc/api/redoc/
640640

641641
Swagger UI:
642642
~~~~~~~~~~~

docs/source/pjrpc/quickstart.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,9 @@ and Swagger UI web tool with basic auth:
568568
web.run_app(http_app, host='localhost', port=8080)
569569
570570
571-
Specification is available on http://localhost:8080/rpc/api/v1/openapi.json
571+
Specification is available on http://localhost:8080/rpc/api/openapi.json
572572

573-
Web UI is running on http://localhost:8080/rpc/api/v1/swagger/ and http://localhost:8080/rpc/api/v1/redoc/
573+
Web UI is running on http://localhost:8080/rpc/api/swagger/ and http://localhost:8080/rpc/api/redoc/
574574

575575
Swagger UI:
576576
~~~~~~~~~~~

docs/source/pjrpc/webui.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,9 @@ using flask web framework:
234234
235235
236236
237-
Specification is available on http://localhost:8080/myapp/api/v1/openapi.json
237+
Specification is available on http://localhost:8080/rpc/api/openapi.json
238238

239-
Web UI is running on http://localhost:8080/myapp/api/v1/ui/
239+
Web UI is running on http://localhost:8080/rpc/api/v1/swagger/ and http://localhost:8080/rpc/api/v1/redoc/
240240

241241
Swagger UI
242242
~~~~~~~~~~

pjrpc/server/dispatcher.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ def __init__(
559559
self._max_batch_size = max_batch_size
560560
self._executor = executor or BasicAsyncExecutor()
561561

562-
self._request_handler = self._wrap_handle_request()
562+
self._rpc_request_handler = self._wrap_handle_rpc_request()
563563

564564
async def dispatch(self, request_text: str, context: ContextType) -> Optional[tuple[str, tuple[int, ...]]]:
565565
"""
@@ -596,12 +596,12 @@ async def dispatch(self, request_text: str, context: ContextType) -> Optional[tu
596596
)
597597
else:
598598
responses = (
599-
resp for resp in await self._executor.execute(self._request_handler, request, context)
599+
resp for resp in await self._executor.execute(self._handle_request, request, context)
600600
if not isinstance(resp, UnsetType)
601601
)
602602
response = self._batch_response(tuple(responses))
603603
else:
604-
response = await self._request_handler(request, context)
604+
response = await self._handle_request(request, context)
605605

606606
if not isinstance(response, UnsetType):
607607
response_text = self._json_dumper(response.to_json(), cls=self._json_encoder)
@@ -617,18 +617,19 @@ def add_middlewares(self, *middlewares: AsyncMiddlewareType[ContextType], before
617617
else:
618618
self._middlewares = self._middlewares + list(middlewares)
619619

620-
self._request_handler = self._wrap_handle_request()
620+
self._rpc_request_handler = self._wrap_handle_rpc_request()
621+
622+
def _wrap_handle_rpc_request(self) -> Callable[[Request, ContextType], Awaitable[MaybeSet[Response]]]:
623+
request_handler = self._handle_rpc_request
621624

622-
def _wrap_handle_request(self) -> Callable[[Request, ContextType], Awaitable[MaybeSet[Response]]]:
623-
request_handler = self._handle_request
624625
for middleware in reversed(self._middlewares):
625626
request_handler = ft.partial(middleware, handler=request_handler)
626627

627628
return request_handler
628629

629630
async def _handle_request(self, request: Request, context: ContextType) -> MaybeSet[Response]:
630631
try:
631-
return await self._handle_rpc_request(request, context)
632+
return await self._rpc_request_handler(request, context)
632633
except pjrpc.exceptions.JsonRpcError as e:
633634
logger.info("method execution error %s(%r): %r", request.method, request.params, e)
634635
error = e

pjrpc/server/integration/aiohttp.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ def __init__(
6161
self._endpoints: dict[str, AioHttpDispatcher] = {}
6262
self._subapps: dict[str, Application] = {}
6363

64+
@property
65+
def prefix(self) -> str:
66+
return self._prefix
67+
6468
@property
6569
def http_app(self) -> web.Application:
6670
"""
@@ -149,7 +153,7 @@ def generate_spec(self, spec: specs.Specification, base_path: str = '', endpoint
149153
app_endpoints = self._endpoints
150154
for prefix, subapp in self._subapps.items():
151155
for subprefix, dispatcher in subapp.endpoints.items():
152-
app_endpoints[utils.join_path(prefix, subprefix)] = dispatcher
156+
app_endpoints[utils.join_path(prefix, subapp._prefix, subprefix)] = dispatcher
153157

154158
methods = {
155159
utils.remove_prefix(dispatcher_endpoint, endpoint): dispatcher.registry.values()

pjrpc/server/specs/extractors/pydantic_v1.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,20 +135,19 @@ def extract_response_schema(
135135
) -> tuple[dict[str, Any], dict[str, dict[str, Any]]]:
136136
return_model = self._build_result_model(method_name, method)
137137

138-
response_model: type[pd.BaseModel]
139-
error_models = tuple(
140-
pd.create_model(
141-
error.__name__,
142-
__base__=JsonRpcResponseError[JsonRpcError[Literal[error.CODE], Any]], # type: ignore[name-defined]
143-
__config__=pydantic.config.get_config(
138+
error_models: list[type[pd.BaseModel]] = []
139+
for error in errors or []:
140+
class ErrorModel(pydantic.BaseModel):
141+
Config = pydantic.config.get_config(
144142
dict(
145143
self._config_args,
146144
title=error.__name__,
147145
json_schema_extra=dict(description=f'**{error.CODE}** {error.MESSAGE}'),
148146
),
149-
),
150-
) for error in errors or []
151-
)
147+
)
148+
__root__: JsonRpcResponseError[JsonRpcError[Literal[error.CODE], Any]] # type: ignore[name-defined]
149+
150+
error_models.append(pd.create_model(error.__name__, __base__=ErrorModel))
152151

153152
class ResponseModel(pydantic.BaseModel):
154153
Config = pydantic.config.get_config(dict(title=f"{to_camel(method_name)}Response"))

pjrpc/server/validators/pydantic_v1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def validate_params(self, params: Optional['JsonRpcParamsT']) -> dict[str, Any]:
7171
except pydantic.ValidationError as e:
7272
raise base.ValidationError(*e.errors()) from e
7373

74-
return {field_name: obj.__dict__[field_name] for field_name in fields}
74+
return {field_name: obj.__dict__[field_name] for field_name in model_fields}
7575

7676
def _build_validation_model(self, method_name: str) -> type[pydantic.BaseModel]:
7777
schema = self._build_validation_schema(self._signature)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pjrpc"
3-
version = "2.0.0"
3+
version = "2.0.1"
44
description = "Extensible JSON-RPC library"
55
authors = ["Dmitry Pershin <[email protected]>"]
66
license = "Unlicense"

0 commit comments

Comments
 (0)