remotepy allows Python functions to be called remotely from multiple languages including JavaScript, CSharp and Python
Project description
Remote Py
Remote Py is a powerful RPC (Remote Procedure Call) framework that allows you to write Python functions and expose them as remote services. It provides client interfaces in multiple languages including JavaScript, C#, and Python, enabling seamless cross-platform communication over WebSockets.
Features
- Multi-language Support: Call Python functions from JavaScript (browser), C#, and Python clients
- Bidirectional Communication: Full-duplex communication using WebSockets for real-time interaction
- Easy-to-Use API: Simple decorator-based API (
@remotepy_func,@remotepy_class) for exposing functions - Session Management: Built-in session handling and authentication support with
SessionServer - Real-time Messaging: Pub/Sub broadcasting capabilities for event-driven architectures
- Async Support: Full support for async/await Python functions and generators
- Streaming: Support for generators and async generators for streaming large datasets
- Security Features:
- Rate limiting (100 calls per function per minute by default)
- Input validation
- Password sanitization in logs
- SQL injection protection
- SSL/TLS Support: Secure WebSocket connections with SSL/TLS
- Binary Protocol: Efficient message serialization using MessagePack
- Error Handling: Comprehensive error handling with sanitized error messages
Installation
Production PyPI
pip install remotepy
Test PyPI
If installing from test.pypi.org, you must also specify the regular PyPI as an extra index because test PyPI doesn't have all dependencies:
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ remotepy
Requirements
All required dependencies are automatically installed with the package. The main dependencies include:
numpy- Numerical operationsservice_identity- Service identity verificationtwisted- Network frameworkautobahn- WebSocket implementationcryptography- Cryptographic functionszmq- ZeroMQ messagingmsgpack- Binary serializationpython-dotenv- Environment variable management
Quick Start
Basic Server Example
Create a server file (e.g., server.py):
from remotepy import *
@remotepy_class
class MyPythonServer(WebSocketRPCServerProtocol, SessionServer):
def onConnect(self, request):
print("Client connecting: {}".format(request.peer))
@remotepy_func
def add(self, a, b):
"""
Adds two numbers together.
:param a: First number
:param b: Second number
:return: Sum of a and b
"""
return a + b
@remotepy_func
def greet(self, name):
"""Greets a user by name."""
return f"Hello, {name}!"
def onClose(self, wasClean, code, reason):
print("Client closing connection: ", code, reason)
# Initialize server with database configuration (optional)
db_config = {
'host': 'localhost',
'user': 'your_user',
'password': 'your_password',
'database': 'your_database'
}
server = MyPythonServer(db_config)
server.run("127.0.0.1", 8082)
Server with SSL/TLS
For secure connections:
server = MyPythonServer(db_config)
server.run_ssl(
"0.0.0.0",
8443,
"path/to/private.pem",
"path/to/fullchain.pem"
)
Advanced Features
Async Functions
Remote Py supports both synchronous and asynchronous Python functions:
@remotepy_class
class MyAsyncServer(WebSocketRPCServerProtocol):
@remotepy_func
async def async_process_data(self, data):
"""Process data asynchronously."""
# Simulate async operation
await asyncio.sleep(1)
return {"processed": data, "status": "complete"}
@remotepy_func
def sync_process_data(self, data):
"""Process data synchronously."""
return {"processed": data, "status": "complete"}
Streaming with Generators
Stream large datasets efficiently using generators:
@remotepy_class
class DataServer(WebSocketRPCServerProtocol):
@remotepy_func
def stream_data(self, count):
"""Stream data items one by one."""
for i in range(count):
yield {"index": i, "data": f"item_{i}"}
@remotepy_func
async def async_stream_data(self, count):
"""Stream data asynchronously."""
for i in range(count):
await asyncio.sleep(0.1)
yield {"index": i, "data": f"item_{i}"}
Session Management
Use SessionServer for user authentication and session handling:
from remotepy import *
@remotepy_class
class SecureServer(WebSocketRPCServerProtocol, SessionServer):
def __init__(self, db_config):
super().__init__(db_config)
# Configure email settings for password reset
self.set_email_config(
user="your-email@gmail.com",
server="smtp.gmail.com",
port=587
)
@remotepy_method
def validateLogin(self, sessionid, username, password, remember, currentUrl, afterLoginUrl):
"""Validate user login credentials."""
# Implementation handled by SessionServer
pass
@remotepy_method
def getSessionId(self):
"""Get current session ID."""
return self.SessionState.getSessionId()
Protected Functions
Use decorators to protect functions that require authentication:
from remotepy.websocket.remotepy import remotepy_login_required, remotepy_permitted_to
@remotepy_class
class ProtectedServer(WebSocketRPCServerProtocol, SessionServer):
@remotepy_func
@remotepy_login_required
def get_user_data(self):
"""Requires user to be logged in."""
return {"user": "data"}
@remotepy_func
@remotepy_permitted_to("admin")
def admin_function(self):
"""Requires admin permission."""
return {"admin": "data"}
Pub/Sub Broadcasting
Use PubSubBroadcastServerFactory for real-time event broadcasting:
from remotepy import PubSubBroadcastServerFactory
@remotepy_class
class BroadcastServer(WebSocketRPCServerProtocol):
def __init__(self):
super().__init__()
# Your initialization code
@remotepy_func
def broadcast_message(self, message):
"""Broadcast a message to all connected clients."""
# Implementation for broadcasting
pass
# Use PubSubBroadcastServerFactory for pub/sub functionality
server = BroadcastServer()
server.run("127.0.0.1", 8082, ServerFactory=PubSubBroadcastServerFactory)
Configuration
Environment Variables
Remote Py supports configuration via environment variables. Create a .env file:
REMOTEPY_EMAIL_USER=your-email@gmail.com
REMOTEPY_EMAIL_PASSWORD=your-app-password
REMOTEPY_EMAIL_SERVER=smtp.gmail.com
REMOTEPY_EMAIL_PORT=587
REMOTEPY_RESET_PASSWORD_EMAIL=noreply@yourdomain.com
REMOTEPY_DOMAIN_NAME=https://www.yourdomain.com
If environment variables are not set, Remote Py will use default values for backward compatibility.
Rate Limiting
Rate limiting is enabled by default (100 calls per function per 60 seconds). You can customize this:
# In your server class __init__ or after instantiation
server._rate_limit_window = 60 # Time window in seconds
server._rate_limit_max_calls = 200 # Max calls per window
Client Examples
JavaScript Client
Installation:
The JavaScript client is available as a separate package. For web applications, include the client library in your HTML:
<script language="JavaScript" src="js/remotepy.1.0.0.min.js"></script>
Usage Example:
<!DOCTYPE html>
<html>
<head>
<title>RemotePy Client</title>
</head>
<body>
<script language="JavaScript" src="js/remotepy.1.0.0.min.js"></script>
<script language="JavaScript">
var RemotePy = new RemotePyClient();
window.onload = function() {
RemotePy.serverName = 'ws://localhost:8082';
RemotePy.start();
}
RemotePy.onopen = function() {
console.log("Connected to server");
// Call a remote function
RemotePy.MyPythonServer.add(2, 4, function(sum) {
console.log("Result:", sum); // Output: 6
});
// Call with error handling
RemotePy.MyPythonServer.greet("World", function(result) {
console.log(result); // Output: "Hello, World!"
}, function(error) {
console.error("Error:", error);
});
}
RemotePy.onclose = function() {
console.log("Connection closed");
}
RemotePy.onerror = function(error) {
console.error("Connection error:", error);
}
</script>
</body>
</html>
Python Client
Installation:
pip install remotepy_client
Usage Example:
from remotepy_client.remotepy_rpc_client import RemotePyRPCClientSync
# Server configuration
broker = "ws://localhost"
port = 8082
verbose = False
server_url = f"{broker}:{port}"
# Connect to remotepy server to get the metadata for offered functions
client = RemotePyRPCClientSync(server_url, verbose)
# Build the client connectivity code for all the server functions
client.buildService('')
# Get access to available services
MyPythonServerEngine = client.getService('MyPythonServer')
# Connect to the remotepy server to call server functions
MyPythonServer = MyPythonServerEngine(f"{broker}:{port}", verbose)
# Call remotepy server function synchronously
result = MyPythonServer.add(a=5, b=6, callback=None)
print(result) # Output: 11
# Call with callback
def handle_result(result):
print(f"Received result: {result}")
MyPythonServer.greet(name="Python Client", callback=handle_result)
# Wait for all the threads to finish
client.thread().join()
Async Python Client Example:
import asyncio
from remotepy_client.remotepy_rpc_client import RemotePyRPCClientAsync
async def main():
server_url = "ws://localhost:8082"
client = RemotePyRPCClientAsync(server_url)
await client.connect()
client.buildService('')
MyPythonServer = client.getService('MyPythonServer')(server_url)
# Call async function
result = await MyPythonServer.async_process_data({"key": "value"})
print(result)
await client.close()
asyncio.run(main())
Error Handling
Remote Py provides comprehensive error handling:
- Input Validation: Automatic validation of RPC call parameters
- Rate Limiting: Protection against excessive function calls
- Error Sanitization: Passwords and sensitive data are automatically redacted from error messages
- Connection Handling: Graceful handling of disconnected clients
Error responses follow this format:
{
"funcName": "function_name",
"callId": "call_id",
"error": "Error message (with sensitive data redacted)"
}
Security Features
Rate Limiting
By default, each function is rate-limited to 100 calls per 60-second window. This prevents abuse and DoS attacks.
Input Validation
All RPC calls are validated:
- Function names must be strings (max 256 characters)
- Arguments must be dictionaries
- Potentially dangerous function names are logged (but not blocked for compatibility)
Password Protection
- Passwords are never logged
- Error messages are sanitized to remove password information
- Session IDs are validated and cleaned up after use
SQL Injection Protection
- Schema names are sanitized before use in SQL queries
- Parameterized queries are used for all database operations
API Reference
Decorators
@remotepy_class: Decorates a class to make it a RemotePy server@remotepy_func: Exposes a function for remote calls@remotepy_method: Exposes a method for remote calls (used with SessionServer)@remotepy_login_required: Requires user to be logged in@remotepy_permitted_to(action): Requires specific permission
Server Methods
server.run(ip, port, ServerFactory=None): Start server on specified IP and portserver.run_ssl(ip, port, private_pem_file, fullchain_pem_file, ServerFactory=None): Start server with SSL/TLS
SessionServer Methods
validateLogin(sessionid, username, password, remember, currentUrl, afterLoginUrl): Validate user credentialsgetSessionId(): Get current session IDgetNewSessionId(): Generate a new session IDisLoggedIn(sessionid): Check if user is logged inlogOut(): Log out current sessionset_email_config(...): Configure email settings for password reset
Best Practices
- Use Type Hints: Add type hints to your functions for better documentation
- Error Handling: Always handle errors appropriately in your functions
- Session Management: Use
SessionServerfor applications requiring authentication - Rate Limiting: Adjust rate limits based on your application's needs
- SSL/TLS: Always use SSL/TLS in production environments
- Environment Variables: Store sensitive configuration in environment variables
- Logging: Use Python's logging module instead of print statements
Troubleshooting
Connection Issues
- Ensure the server is running and accessible
- Check firewall settings
- Verify WebSocket URL format (
ws://orwss://)
Rate Limiting
If you encounter rate limit errors, either:
- Increase the rate limit settings
- Reduce the frequency of function calls
- Implement client-side throttling
Session Issues
- Ensure database configuration is correct
- Verify session IDs are being passed correctly
- Check that
SessionServeris properly initialized
Documentation
For more information, visit https://www.remotepy.com
License
This project is proprietary software. All rights reserved. See the LICENSE file for details.
Author
Faraz Farukh Tamboli
- Email: faraz.tamboli@gmail.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file remotepy-0.0.3-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 536.2 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
151aaa7348f0dc9985834bdc67e4558083e439bb851e4c674f97a2dd1d1a1ab5
|
|
| MD5 |
2b49170a67d21c4d16f9f9f2b5fe2f84
|
|
| BLAKE2b-256 |
9d5a97601e3911c59e0537de0941d283dc98a510f327bf74f794121b76a42390
|
File details
Details for the file remotepy-0.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- Upload date:
- Size: 4.5 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d174cbd2d631abff02351b164c6841f3fe1694b2e568873b97e248f88aa6637a
|
|
| MD5 |
3a989829e227a95c4304f62a8981362d
|
|
| BLAKE2b-256 |
b79cc61e465656e740c4c8d77e742d4ec008310c9c15813903321b32f3158579
|
File details
Details for the file remotepy-0.0.3-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 557.0 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d25ec9f325550709eda1b66d31851fe2e8fcf4b5a8fa1cd21f3f3e37dff05f5c
|
|
| MD5 |
78ddbc6e727c612dc6de793668236889
|
|
| BLAKE2b-256 |
7c05b3430cc158ccdd6542a2568cb2abb4f69a46dddbab2f96a133d16e8d76ba
|
File details
Details for the file remotepy-0.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- Upload date:
- Size: 4.5 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5e913c4431c89498431e0191a0d2f45a3846b1f764b1a02743626f81bc712de
|
|
| MD5 |
1857252df3b684ba73637ecaf89dca95
|
|
| BLAKE2b-256 |
aa61b17bce376fe56caa6a01fc584e0c998221c75472cbd590fe756de75cedd6
|
File details
Details for the file remotepy-0.0.3-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 555.1 kB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d4904c01810ac58466151bcb1f45dcc3bcb41b8262ee21955480af83261f3f2
|
|
| MD5 |
debdb88667d35df599a2147babf5f7b8
|
|
| BLAKE2b-256 |
c96435346272f017590b49a7bb7780080d390adab6dd98077d5f083eff111a6d
|
File details
Details for the file remotepy-0.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- Upload date:
- Size: 4.2 MB
- Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1310373e4454f5eddd116e6ef51dc2ec79a9549f4178b4f250f6fee4c35d67f0
|
|
| MD5 |
6c9aa0762ed00c4961f4159a4771d6e7
|
|
| BLAKE2b-256 |
290632691d1c372c545e72fba59bbf8961c166b4e85239264941d80cc1aa4db5
|
File details
Details for the file remotepy-0.0.3-cp39-cp39-win_amd64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp39-cp39-win_amd64.whl
- Upload date:
- Size: 624.9 kB
- Tags: CPython 3.9, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8de6125d9fac111ace2739737012b593b53a3f7def8ce21ccb54cd137edf7b9
|
|
| MD5 |
ae23a6a59d467f9a76830378cb361303
|
|
| BLAKE2b-256 |
dd518396a12d4a7c4b5c21891b0592aa82e91e224d8ddfb41a56759038193bbb
|
File details
Details for the file remotepy-0.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.
File metadata
- Download URL: remotepy-0.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- Upload date:
- Size: 4.2 MB
- Tags: CPython 3.9, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6791f03105a6e29c2f4b1ad0494f5d860b255a273620a22305da74dc01e44f71
|
|
| MD5 |
9444e4a877c39be516c9715aad49a4ea
|
|
| BLAKE2b-256 |
cbb44d0c2e6e09e30601afa730d84a2629e48497912c72b55a40fd743d8220d1
|