Skip to content

Commit

Permalink
Merge pull request #39 from dapper91/dev
Browse files Browse the repository at this point in the history
- starlette integration added
- django integration added
- sub endpoints support implemented
  • Loading branch information
dapper91 authored Sep 1, 2021
2 parents 4c744e1 + 39f50a1 commit b2fc556
Show file tree
Hide file tree
Showing 32 changed files with 1,365 additions and 47 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

1.3.2 (2021-08-30)
------------------

- starlette integration added
- django integration added
- sub endpoints support implemented


1.3.1 (2021-08-24)
------------------

Expand Down
6 changes: 4 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Extra requirements
- `requests <https://requests.readthedocs.io>`_
- `httpx <https://www.python-httpx.org/>`_
- `openapi-ui-bundles <https://github.com/dapper91/python-openapi-ui-bundles>`_
- `starlette <https://www.starlette.io/>`_
- `django <https://www.djangoproject.com>`_


Documentation
Expand Down Expand Up @@ -484,8 +486,8 @@ and Swagger UI web tool with basic auth:
class AuthenticatedJsonRPC(integration.JsonRPC):
@auth.login_required
def _rpc_handle(self) -> flask.Response:
return super()._rpc_handle()
def _rpc_handle(self, dispatcher: pjrpc.server.Dispatcher) -> flask.Response:
return super()._rpc_handle(dispatcher)
class JSONEncoder(pjrpc.JSONEncoder):
Expand Down
2 changes: 2 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Extra requirements
- `requests <https://requests.readthedocs.io>`_
- `httpx <https://www.python-httpx.org/>`_
- `openapi-ui-bundles <https://github.com/dapper91/python-openapi-ui-bundles>`_
- `starlette <https://www.starlette.io/>`_
- `django <https://www.djangoproject.com>`_


The User Guide
Expand Down
4 changes: 2 additions & 2 deletions docs/source/pjrpc/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,8 @@ Swagger UI web tool with basic auth:
class AuthenticatedJsonRPC(integration.JsonRPC):
@auth.login_required
def _rpc_handle(self) -> flask.Response:
return super()._rpc_handle()
def _rpc_handle(self, dispatcher: pjrpc.server.Dispatcher) -> flask.Response:
return super()._rpc_handle(dispatcher)
class JSONEncoder(pjrpc.JSONEncoder):
Expand Down
4 changes: 2 additions & 2 deletions docs/source/pjrpc/webui.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ using flask web framework:
class AuthenticatedJsonRPC(integration.JsonRPC):
@auth.login_required
def _rpc_handle(self) -> flask.Response:
return super()._rpc_handle()
def _rpc_handle(self, dispatcher: pjrpc.server.Dispatcher) -> flask.Response:
return super()._rpc_handle(dispatcher)
class JSONEncoder(pjrpc.JSONEncoder):
Expand Down
22 changes: 22 additions & 0 deletions examples/django/manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?",
) from exc
execute_from_command_line(sys.argv)


if __name__ == '__main__':
main()
Empty file.
29 changes: 29 additions & 0 deletions examples/django/mysite/jsonrpc/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import uuid
from typing import Any

import pydantic
import pjrpc.server
import pjrpc.server.specs.extractors.pydantic
from pjrpc.server.specs import extractors, openapi as specs


class JSONEncoder(pjrpc.server.JSONEncoder):
def default(self, o: Any) -> Any:
if isinstance(o, pydantic.BaseModel):
return o.dict()
if isinstance(o, uuid.UUID):
return str(o)

return super().default(o)


spec = specs.OpenAPI(
info=specs.Info(version="1.0.0", title="User storage"),
servers=[
specs.Server(
url='http://127.0.0.1:8000',
),
],
schema_extractor=extractors.pydantic.PydanticSchemaExtractor(),
ui=specs.SwaggerUI(),
)
151 changes: 151 additions & 0 deletions examples/django/mysite/jsonrpc/posts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import uuid
from collections import defaultdict

import pydantic
from django.http.request import HttpRequest

import pjrpc.server.specs.extractors.pydantic
from pjrpc.server.validators import pydantic as validators
from pjrpc.server.specs import openapi as specs

methods = pjrpc.server.MethodRegistry()
validator = validators.PydanticValidator()
db = defaultdict(dict)


class PostIn(pydantic.BaseModel):
"""
Post data.
"""

title: str
content: str


class PostOut(PostIn):
"""
Created post data.
"""

id: uuid.UUID


class AlreadyExistsError(pjrpc.exc.JsonRpcError):
"""
Post already registered error.
"""

code = 2003
message = "post already exists"


class NotFoundError(pjrpc.exc.JsonRpcError):
"""
Post not found error.
"""

code = 2004
message = "post not found"


@specs.annotate(
tags=['posts'],
errors=[AlreadyExistsError],
examples=[
specs.MethodExample(
summary="Simple example",
params=dict(
post={
'title': 'Super post',
'content': 'My first post',
},
),
result={
'id': 'c47726c6-a232-45f1-944f-60b98966ff1b',
'title': 'Super post',
'content': 'My first post',
},
),
],
)
@methods.add(context='request')
@validator.validate
def add_post(request: HttpRequest, post: PostIn) -> PostOut:
"""
Creates a post.
:param request: http request
:param object post: post data
:return object: created post
:raise AlreadyExistsError: post already exists
"""

post_id = uuid.uuid4().hex
db['posts'][post_id] = post

return PostOut(id=post_id, **post.dict())


@specs.annotate(
tags=['posts'],
errors=[NotFoundError],
examples=[
specs.MethodExample(
summary="Simple example",
params=dict(
post_id='c47726c6-a232-45f1-944f-60b98966ff1b',
),
result={
'id': 'c47726c6-a232-45f1-944f-60b98966ff1b',
'title': 'Super post',
'content': 'My first post',
},
),
],
)
@methods.add(context='request')
@validator.validate
def get_post(request: HttpRequest, post_id: uuid.UUID) -> PostOut:
"""
Returns a post.
:param request: http request
:param object post_id: post id
:return object: registered post
:raise NotFoundError: post not found
"""

post = db['posts'].get(post_id)
if not post:
raise NotFoundError()

return PostOut(**post.dict())


@specs.annotate(
tags=['posts'],
errors=[NotFoundError],
examples=[
specs.MethodExample(
summary='Simple example',
params=dict(
post_id='c47726c6-a232-45f1-944f-60b98966ff1b',
),
result=None,
),
],
)
@methods.add(context='request')
@validator.validate
def delete_post(request: HttpRequest, post_id: uuid.UUID) -> None:
"""
Deletes a post.
:param request: http request
:param object post_id: post id
:raise NotFoundError: post not found
"""

post = db['posts'].pop(post_id, None)
if not post:
raise NotFoundError()
Loading

0 comments on commit b2fc556

Please sign in to comment.