.. _specification: Specification: ============== ``pjrpc`` has built-in `OpenAPI `_ and `OpenRPC `_ specification generation support implemented by :py:class:`pjrpc.server.specs.openapi.OpenAPI` and :py:class:`pjrpc.server.specs.openrpc.OpenRPC` respectively. To enable schema generation you should pass specification generator instance to the JSON-RPC application. .. code-block:: python json_rpc = integration.JsonRPC( '/api/v1', spec=specs.OpenAPI( info=specs.Info(version="1.0.0", title="User storage"), servers=[ specs.Server( url='http://127.0.0.1:8080', ), ], security_schemes=dict( basic=specs.SecurityScheme( type=specs.SecuritySchemeType.HTTP, scheme='basic', ), ), schema_extractor=extractors.pydantic.PydanticSchemaExtractor(), ui=specs.SwaggerUI(), ), ) OpenAPI specification will be available on ``/api/v1/openapi.json`` path. Path suffix can be overridden by passing ``path`` parameter to a specification generator. For more information about the specification see `OpenAPI Specification `_. OpenRPC specification generation looks pretty the same: .. code-block:: python json_rpc = integration.JsonRPC( '/api/v1', spec=specs.OpenRPC( info=specs.Info(version="1.0.0", title="User storage"), servers=[ specs.Server( name='test', url='http://127.0.0.1:8080/api/v1/', summary='test server', ), ], schema_extractor=extractors.pydantic.PydanticSchemaExtractor(), ), ) OpenRPC specification will be available on ``/api/v1/openrpc.json`` path. Method description, tags, errors, examples, parameters and return value schemas can be provided by hand using :py:func:`pjrpc.server.specs.openapi.annotate` decorator or automatically extracted using schema extractor. ``pjrpc`` provides two schema extractors: :py:class:`pjrpc.server.specs.extractors.pydantic.PydanticSchemaExtractor` and :py:class:`pjrpc.server.specs.extractors.docstring.DocstringSchemaExtractor`. They uses `pydantic `_ models or python docstrings for method summary, description, errors, examples and schema extraction respectively. You can implement your own schema extractor inheriting it from :py:class:`pjrpc.server.specs.extractors.BaseSchemaExtractor` and implementing abstract methods. Multiple schema extractors could be used simultaneously using parameter ``schema_extractors``. Final schema will be merged using that extractors in reverse order (former extractor rewrites the result of the later ones). .. code-block:: python @specs.annotate( tags=['users'], errors=[AlreadyExistsError], examples=[ specs.MethodExample( summary="Simple example", params=dict( user={ 'name': 'John', 'surname': 'Doe', 'age': 25, }, ), result={ 'id': 'c47726c6-a232-45f1-944f-60b98966ff1b', 'name': 'John', 'surname': 'Doe', 'age': 25, }, ), ], ) @methods.add @validator.validate def add_user(user: UserIn) -> UserOut: """ Creates a user. :param object user: user data :return object: registered user :raise AlreadyExistsError: user already exists """ for existing_user in flask.current_app.users_db.values(): if user.name == existing_user.name: raise AlreadyExistsError() user_id = uuid.uuid4().hex flask.current_app.users_db[user_id] = user return UserOut(id=user_id, **user.dict())