Skip to main content

Pynocchio: Making remote calls as easy-peasy as pie!

Pynocchio offers an innovative way to use Python libraries remotely through RPC. Inspired by the idea of puppets and puppeteers, it provides unparalleled flexibility, allowing you to customize the communication protocol, serialization method, and even the way objects are managed and stored on the remote side.

📑 Table of Contents

🔧 Installation

📦 Pynocchio is available on PyPI. Get it in no time:

pip install pynocchio

🚀 Getting Started

Dive into Pynocchio and tap into its powerful features! This simple guide will use virtual producer (client) and consumer (server) abstractions to help you grasp its core concepts and functionalities.

1 - Server Side

import pynocchio as pn
import numpy as local_numpy

message_queue = []
reply_queue = {}

# Memory Server Type
consumer = pn.VirtualConsumer(
  pn.VirtualStorage(), # Memory Storage Type
  message_queue,
  reply_queue)

# Assign the lib tree you'll accept to execute
pn.serve(local_numpy, consumer)

# Consume Client's requests
consumer.listen()

2 - Client Side

import pynocchio as pn
import numpy as local_numpy

message_queue = []
reply_queue = {}


# Memory Client type
producer = pn.VirtualProducer(message_queue, reply_queue)

# Mirror all numpy classes, functions and attributes
np = pn.control(local_numpy, producer)

# Run as if you were executing it locally
x_ptr = np.array([1, 2, 3])
y_ptr = np.array([4, 5, 6])
result = x_ptr + y_ptr

result.retrieve()

📡 Choose how you send and receive the remote calls!

Picking a protocol is a breeze! Pynocchio provides the flexibility to use your preferred communication protocol. To give an example, this is how we can send and receive our commands using WebSockets.

1 - Pynocchio Websocket Server

import asyncio

import numpy as local_numpy
import pynocchio as pn
from pynocchio.consumer.abstract import AbstractConsumer
from pynocchio.store.virtual_store import VirtualStore
from pynocchio.serde.capnp.deserialize import _deserialize
from pynocchio.serde.capnp.serialize import _serialize
from typing import Any
from websockets.server import serve


class WebsocketConsumer(AbstractConsumer):
    def __init__(self, storage, websocket):
        super().__init__(storage)
        self.websocket = websocket
        self.reply_queue = []

    async def execute(self, ptr: bytes):
        ptr = _deserialize(ptr, from_bytes=True)
        self.puppet_module.execute(
            pointer=ptr,storage=self.storage,
            reply_callback=self.reply,
        )
        if self.reply_queue:
            message = _serialize(self.reply_queue.pop(0), to_bytes=True)
            await self.websocket.send(message)

    def reply(self, obj_id: str, obj: Any):
        self.reply_queue.append(obj)


async def listen(websocket):
    consumer = WebsocketConsumer(VirtualStore(), websocket=websocket)
    pn.serve(module=local_numpy,consumer=consumer)
    async for message in websocket:
        await consumer.execute(message)

async def main():
    async with serve(listen, "localhost", 8765):
        await asyncio.Future()  # run forever


asyncio.run(main())

2 - Pynocchio Websocket Client

import numpy as local_numpy
import pynocchio as pn
from pynocchio.producer.abstract import AbstractProducer
from pynocchio.pointer.abstract import Pointer
from pynocchio.pointer.object_pointer import GetPointer
from pynocchio.serde.capnp.deserialize import _deserialize
from pynocchio.serde.capnp.serialize import _serialize
from websockets.sync.client import connect



class WebSocketsProducer(AbstractProducer):
    def __init__(self):
        self.socket = connect("ws://localhost:8765")
        super().__init__()

    def send(self, ptr: Pointer):
        msg = _serialize(ptr, to_bytes=True)
        self.socket.send(msg)

    def request(self, ptr: GetPointer):
        msg = _serialize(ptr, to_bytes=True)
        self.socket.send(msg)
        response = self.socket.recv()
        return _deserialize(response, from_bytes=True)

# Parse Numpy Library and set the Websocket Producer.
producer = WebSocketsProducer()
np = pn.control(module=local_numpy, producer=producer)

# Perform remote numpy calls and retrieve the result!
np.ALLOW_THREADS
x_ptr = np.array([1, 2, 3, 4, 5, 6])
x_ptr = x_ptr + x_ptr
my_result = x_ptr.retrieve()
producer.socket.close()

💾 Storage

Store your way! Pynocchio lets you be in charge:

  • Relational Databases 🗃:
    • e.g., MySQL, PostgreSQL
  • NoSQL Databases 📊:
    • e.g., MongoDB, Cassandra
  • In-memory 🚀:
    • e.g., Redis
  • Custom Storage 🔒:
    • Craft your own storage backend.
# Switching storage backends is straightforward
remote.configure(storage=pynocchio.storage.MongoDB)

🔄 Serialization

Encode and decode your data your way:

  • JSON 📝:
    • The universal choice.
  • MessagePack 🎛:
    • Compact binary format.
  • Protobuf 📦:
    • For those intricate data structures.
  • Custom Serialization ⚙️:
    • Roll your own encoder-decoder combo.
# Shifting serialization methods is a snap
remote.configure(serialization=pynocchio.serialization.MessagePack)

📚 Documentation

For more detailed insights, head over to our Wiki or peek into the docs/ directory.

🤝 Contributing

Wish to contribute to Pynocchio? Fantastic! Check our CONTRIBUTING.md guide to get started.

🙏 Acknowledgements

A massive shoutout to Name and all our wonderful contributors.

📃 License

Pynocchio is under the Apache 2.0 License. Delve into LICENSE.md for all the legalities.

📞 Contact

Queries? Suggestions? Drop us an email at ionesiojr@gmail.com.

🎉 Special Thanks

Kudos to all our backers, contributors, and supporters for making Pynocchio a reality. You rock!

Metadata

Release files for spycular 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spycular 0.1.0
File Size Uploaded Provenance Actions
spycular-0.1.0.tar.gz 69.2 kB Without provenance Details for spycular-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for spycular 0.1.0
File Interpreter ABI Platform Actions
spycular-0.1.0-py3-none-any.whl Python 3 none any Details for spycular-0.1.0-py3-none-any.whl

Total release size: 149.5 kB

Release files / spycular-0.1.0.tar.gz

Download URL spycular-0.1.0.tar.gz
Size 69.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d955073811e3fe6a48450c6d6f9d753e5d2d08d1fde1124f0b72545562d7b154
BLAKE2b-256 checksum
How to use checksums
4c4c8204077a45ccb3b7cdce2cdd83c26519353b7df77f98f48a5e145c095747
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.6.1 CPython/3.10.8 Linux/5.15.90.1-microsoft-standard-WSL2

Release files / spycular-0.1.0-py3-none-any.whl

Download URL spycular-0.1.0-py3-none-any.whl
Size 80.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3fccda26f71f111732857a722866313ac73dd46a87dff0cf5bcef954e4f265e3
BLAKE2b-256 checksum
How to use checksums
c90baeba32a89a4e76e05d3b3bc7eab39b60692d06a1b5d4bf7a8dcfaad77a7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.6.1 CPython/3.10.8 Linux/5.15.90.1-microsoft-standard-WSL2

Security for spycular 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page