Skip to main content

simple jsonrpc

Project description

Latest Version Supported Python versions Downloads

simplejrpc

1. Getting Started Quickly

1.1 Install SDK

Install the SDK using pip:

pip3 install simplejrpc

Once installed, you can import and use the SDK functions in your project.


2. Service Registration

2.1 Register a Socket File

Since the SDK communicates with the backend process via a Unix Socket file (based on the JSON-RPC 2.0 protocol), you must explicitly specify the socket_path to ensure the service generates a .sock file and exposes communication capabilities.

# main.py
from simplejrpc import ServerApplication

# Specify the Unix Socket file path
socket_path = "/xxx/app.socket"

# Create the application instance
app = ServerApplication(socket_path=socket_path)

✅ Tip: Make sure the path is writable and does not conflict with other services.


2.2 Register a Configuration File (Logging System)

To enable logging, specify the path to a logger config file during initialization. You can also call app.setup_logger(config_path) after the app starts to load the logger config dynamically.

  • Supported format: YAML
  • If not configured, a simple logger provided by loguru is used by default.
# main.py
from simplejrpc import ServerApplication

sock_path = "/xxx/app.sock"
config_path = "/xxx/config.yaml"

# Initialize the app with logger configuration
app = ServerApplication(socket_path=sock_path, config_path=config_path)

# Alternatively, configure the logger after initialization:
# app.setup_logger(config_path)

2.3 Register Methods (Business Routes)

Registering methods exposes functions as interfaces accessible via JSON-RPC.

✅ Default Registration (Using Function Name)

If the method name is not explicitly specified, the system will use the function name by default:

from simplejrpc.response import jsonify


@app.route()  # Registered as 'hello' by default
async def hello():
    return jsonify(data="hello", msg="OK")

✅ Explicit Registration (Specify Method Name)

You can also specify a method name using the name parameter. It’s recommended to keep it consistent with the function name for maintainability:

from simplejrpc.response import jsonify


@app.route(name="hello")  # Explicitly set method name
async def hello():
    return jsonify(data="hello", msg="OK")

⚠️ Note: If name differs from the function name, it may cause confusion during maintenance or calls. Consistent naming is advised.


3. Making Requests


3.1 Request and Response Structure

✅ Supported Parameter Formats

The framework supports two ways of receiving request parameters:

📌 Explicit Parameter Declaration (Recommended)

Use when parameters are fixed and clearly named:

@app.route(name="hello")
async def hello(lang, action):
    # Directly receive request parameters lang and action
    ...

✅ Advantage: Clear typing, easier validation and maintenance.


📌 Dynamic Parameter Handling (*args, **kwargs)

Use when the number of parameters is variable or needs generic processing:

@app.route(name="hello")
async def hello(*args, **kwargs):
    lang = kwargs.get("lang")
    action = kwargs.get("action")
    ...

✅ Standard Response Format

All responses should be returned using jsonify, containing code, data, and msg fields:

from simplejrpc.response import jsonify


@app.route(name="hello")
async def hello():
    return jsonify(code=400, data=True, msg="Operation failed")

✅ Example Response Structure

Success Response:

{
    "jsonrpc": "2.0",
    "result": {
        "code": 200,
        "meta": {
            "endpoint": null,
            "close": 1
        },
        "data": [],
        "msg": "OK"
    },
    "id": 1
}

Error Response:

{
    "jsonrpc": "2.0",
    "result": {
        "code": 400,
        "meta": {
            "endpoint": null,
            "close": 1
        },
        "data": null,
        "msg": "expected value ['start', 'stop']"
    },
    "id": 1
}

3.2 Start the Service

Example server code:

# main.py
import asyncio
from simplejrpc import ServerApplication
from simplejrpc.response import jsonify

socket_path = "/xxx/app.socket"
app = ServerApplication(socket_path)


@app.route(name="hello")
async def hello():
    return jsonify(data="hello", msg="OK")


if __name__ == "__main__":
    asyncio.run(app.run())

Start the service:

$ python3 main.py

3.3 Call Interface (Client Test)

Use the SDK's Request class for testing:

from simplejrpc import Request

# Must match the socket path used by the server
socket_path = "/xxx/app.sock"


def test_hello():
    method = "hello"
    params = {
        "lang": "zh-CN",
        "action": "start"
    }

    request = Request(socket_path)
    result = request.send_request(method, params)
    print("[recv] >", result)

4. Making Requests


4.1 Form Validation

The SDK integrates wtforms to provide a simple yet powerful validation system with support for custom validators.

✅ Example: Define and Use a Form Class

from simplejrpc.schemas import BaseForm, StrRangeValidator, simple
from simplejrpc.response import jsonify


# Custom form class, restricts 'action' to "start" or "stop"
class TestForm(BaseForm):
    action = simple.StringField(
        validators=[StrRangeValidator(allows=["start", "stop"])]
    )


# Specify socket path and register app
socket_path = "/xxx/app.socket"
app = ServerApplication(socket_path)


# Specify 'form' to trigger validation automatically
@app.route(name="hello", form=TestForm)
async def hello(lang, action):
    return jsonify(data=[1, 2, 3], msg="OK")

✅ Custom Validators

You can create custom validation logic by extending BaseValidator.

A custom validator class must inherit from BaseValidator and implement the validator(form, field) method. Only two parameters are accepted: the form instance and the field instance.

from simplejrpc import BaseValidator


class TestValidator(BaseValidator):
    def validator(self, form, field):
        # Custom logic: value must be uppercase
        if field.data and not field.data.isupper():
            raise ValueError("Field must be uppercase")

Use the custom validator in your form:

class TestForm(BaseForm):
    action = simple.StringField(
        validators=[
            StrRangeValidator(allows=["start", "stop"]),
            TestValidator()
        ]
    )

4.2 Exception Handling

The framework includes a built-in exception handling system. Just raise exceptions, and the framework will format them into standard JSON-RPC error responses.

✅ Example

from simplejrpc.exceptions import RPCException


@app.route(name="hello", form=TestForm)
async def hello(lang, action):
    raise RPCException("Test error")  # Automatically caught and formatted

✅ Custom Exception Classes

The framework provides a base exception class that can be extended:

class UnauthorizedError(RPCException):
    """Unauthorized"""

class ValidationError(RPCException):
    """Validation failed"""

class FileNotFoundError(RPCException):
    """File not found"""

class ValueError(RPCException):
    """Value error"""

class RuntimeError(RPCException):
    """Runtime error"""

4.3 Internationalization (i18n)

The SDK supports multilingual output using .ini files, driven by the lang parameter in each request.

✅ Initialize Language Configuration

Your project root should include an i18n/ directory:

project/
├── main.py
└── i18n/
    ├── zh-CN.ini
    └── en.ini

Initialize with GI18n():

GI18n(i18n_dir="i18n", lang="zh-CN")

⚠️ Each request should include a lang parameter, which the framework uses to set the language.


✅ Example 1: Basic Translation

en.ini

TEST_I18N = "test"

Python usage:

from simplejrpc import i18n

print(i18n.translate("TEST_I18N"))  # Output: test

✅ Example 2: Placeholder Translation (Parameterized)

en.ini

TEST_I18N = "test{}"

Python usage:

from simplejrpc import  i18n

print(i18n.translate_ctx("TEST_I18N", "i18n"))  # Output: testi18n

✅ Supported Languages

Language Code Description Region/Note
en English Default
zh-CN Simplified Chinese Mainland China
zh-TW Traditional Chinese Taiwan/Hong Kong
ja Japanese Japan
ru Russian Russia

4.4 Middleware Support

The framework supports middleware for handling common logic before and after request processing, such as logging, authentication, or performance analysis.

✅ Example Usage

from simplejrpc import ServerApplication
from simplejrpc.interfaces import RPCMiddleware


class CustomMiddleware(RPCMiddleware):
    def process_request(self, request, context):
        print("[Before] Incoming request:", request)
        return request

    def process_response(self, response, context):
        print("[After] Outgoing response:", response)
        return response


# Register middleware
app = ServerApplication("/xxx/app.sock")
app.middleware(CustomMiddleware())

Would you like this translated version exported into a PDF or Markdown file?

Feedback

Open a ticket / fork the project on Gitee.

Open a ticket / fork the project on Github.

Here is the fully translated version of your documentation from Chinese to English:


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simplejrpc-2.1.7.tar.gz (49.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simplejrpc-2.1.7-py2.py3-none-any.whl (51.1 kB view details)

Uploaded Python 2Python 3

File details

Details for the file simplejrpc-2.1.7.tar.gz.

File metadata

  • Download URL: simplejrpc-2.1.7.tar.gz
  • Upload date:
  • Size: 49.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for simplejrpc-2.1.7.tar.gz
Algorithm Hash digest
SHA256 edc4ff96baa7386a187aedba4e5df79c9320bd8a4047bb03e57a1851242d1957
MD5 ea4375af97b7a1584fbafbe9aae87839
BLAKE2b-256 51df94b2ab1e6f8c5aefbc648fc8c9d875b12b1b68cfa28dcdde5c2addc75cf6

See more details on using hashes here.

File details

Details for the file simplejrpc-2.1.7-py2.py3-none-any.whl.

File metadata

  • Download URL: simplejrpc-2.1.7-py2.py3-none-any.whl
  • Upload date:
  • Size: 51.1 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for simplejrpc-2.1.7-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 9647fe5c67641c18561cbb5ac789e00ca9bc4920761c0b3d051d0fde8666c534
MD5 b9700352cd7e2c7fa76e10403a5e3aa0
BLAKE2b-256 7d7ad0013ce0e0f784ba58fc932e679c7070ce6bf7c768223228109d7da29019

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page