Merge pull request #151 from tiqi-group/breaking/client_arguments

Breaking: changing allowed client arguments
This commit is contained in:
Mose Müller 2024-08-13 07:04:10 +02:00 committed by GitHub
commit 9aad9dfbc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 37 additions and 22 deletions

View File

@ -170,7 +170,8 @@ import pydase
# Replace the hostname and port with the IP address and the port of the machine where # Replace the hostname and port with the IP address and the port of the machine where
# the service is running, respectively # the service is running, respectively
client_proxy = pydase.Client(hostname="<ip_addr>", port=8001).proxy client_proxy = pydase.Client(url="ws://<ip_addr>:<service_port>").proxy
# client_proxy = pydase.Client(url="wss://your-domain.ch").proxy # if your service uses ssl-encryption
# After the connection, interact with the service attributes as if they were local # After the connection, interact with the service attributes as if they were local
client_proxy.voltage = 5.0 client_proxy.voltage = 5.0
@ -195,7 +196,8 @@ import pydase
class MyService(pydase.DataService): class MyService(pydase.DataService):
# Initialize the client without blocking the constructor # Initialize the client without blocking the constructor
proxy = pydase.Client(hostname="<ip_addr>", port=8001, block_until_connected=False).proxy proxy = pydase.Client(url="ws://<ip_addr>:<service_port>", block_until_connected=False).proxy
# proxy = pydase.Client(url="wss://your-domain.ch", block_until_connected=False).proxy # communicating with ssl-encrypted service
if __name__ == "__main__": if __name__ == "__main__":
service = MyService() service = MyService()

View File

@ -5,9 +5,10 @@ You can connect to the service using the `pydase.Client`. Below is an example of
```python ```python
import pydase import pydase
# Replace the hostname and port with the IP address and the port of the machine # Replace the hostname and port with the IP address and the port of the machine where
# where the service is running, respectively # the service is running, respectively
client_proxy = pydase.Client(hostname="<ip_addr>", port=8001).proxy client_proxy = pydase.Client(url="ws://<ip_addr>:<service_port>").proxy
# client_proxy = pydase.Client(url="wss://your-domain.ch").proxy # if your service uses ssl-encryption
# Interact with the service attributes as if they were local # Interact with the service attributes as if they were local
client_proxy.voltage = 5.0 client_proxy.voltage = 5.0
@ -32,7 +33,8 @@ import pydase
class MyService(pydase.DataService): class MyService(pydase.DataService):
# Initialize the client without blocking the constructor # Initialize the client without blocking the constructor
proxy = pydase.Client(hostname="<ip_addr>", port=8001, block_until_connected=False).proxy proxy = pydase.Client(url="ws://<ip_addr>:<service_port>", block_until_connected=False).proxy
# proxy = pydase.Client(url="wss://your-domain.ch", block_until_connected=False).proxy # communicating with ssl-encrypted service
if __name__ == "__main__": if __name__ == "__main__":
service = MyService() service = MyService()

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "pydase" name = "pydase"
version = "0.8.5" version = "0.9.0"
description = "A flexible and robust Python library for creating, managing, and interacting with data services, with built-in support for web and RPC servers, and customizable features for diverse use cases." description = "A flexible and robust Python library for creating, managing, and interacting with data services, with built-in support for web and RPC servers, and customizable features for diverse use cases."
authors = ["Mose Mueller <mosmuell@ethz.ch>"] authors = ["Mose Mueller <mosmuell@ethz.ch>"]
readme = "README.md" readme = "README.md"

View File

@ -80,12 +80,12 @@ class Client:
if it were local. if it were local.
Args: Args:
hostname (str): url (str):
Hostname of the exposed service this client attempts to connect to. The URL of the pydase Socket.IO server. This should always contain the
Default is "localhost". protocol and the hostname.
port (int): Examples:
Port of the exposed service this client attempts to connect on. - wss://my-service.example.com # for secure connections, use wss
Default is 8001. - ws://localhost:8001
block_until_connected (bool): block_until_connected (bool):
If set to True, the constructor will block until the connection to the If set to True, the constructor will block until the connection to the
service has been established. This is useful for ensuring the client is service has been established. This is useful for ensuring the client is
@ -94,12 +94,11 @@ class Client:
def __init__( def __init__(
self, self,
hostname: str, *,
port: int, url: str,
block_until_connected: bool = True, block_until_connected: bool = True,
): ):
self._hostname = hostname self._url = url
self._port = port
self._sio = socketio.AsyncClient() self._sio = socketio.AsyncClient()
self._loop = asyncio.new_event_loop() self._loop = asyncio.new_event_loop()
self.proxy = ProxyClass(sio_client=self._sio, loop=self._loop) self.proxy = ProxyClass(sio_client=self._sio, loop=self._loop)
@ -107,29 +106,41 @@ class Client:
target=asyncio_loop_thread, args=(self._loop,), daemon=True target=asyncio_loop_thread, args=(self._loop,), daemon=True
) )
self._thread.start() self._thread.start()
self.connect(block_until_connected=block_until_connected)
def connect(self, block_until_connected: bool = True) -> None:
connection_future = asyncio.run_coroutine_threadsafe( connection_future = asyncio.run_coroutine_threadsafe(
self._connect(), self._loop self._connect(), self._loop
) )
if block_until_connected: if block_until_connected:
connection_future.result() connection_future.result()
def disconnect(self) -> None:
connection_future = asyncio.run_coroutine_threadsafe(
self._disconnect(), self._loop
)
connection_future.result()
async def _connect(self) -> None: async def _connect(self) -> None:
logger.debug("Connecting to server '%s:%s' ...", self._hostname, self._port) logger.debug("Connecting to server '%s' ...", self._url)
await self._setup_events() await self._setup_events()
await self._sio.connect( await self._sio.connect(
f"ws://{self._hostname}:{self._port}", self._url,
socketio_path="/ws/socket.io", socketio_path="/ws/socket.io",
transports=["websocket"], transports=["websocket"],
retry=True, retry=True,
) )
async def _disconnect(self) -> None:
await self._sio.disconnect()
async def _setup_events(self) -> None: async def _setup_events(self) -> None:
self._sio.on("connect", self._handle_connect) self._sio.on("connect", self._handle_connect)
self._sio.on("disconnect", self._handle_disconnect) self._sio.on("disconnect", self._handle_disconnect)
self._sio.on("notify", self._handle_update) self._sio.on("notify", self._handle_update)
async def _handle_connect(self) -> None: async def _handle_connect(self) -> None:
logger.debug("Connected to '%s:%s' ...", self._hostname, self._port) logger.debug("Connected to '%s' ...", self._url)
serialized_object = cast( serialized_object = cast(
SerializedDataService, await self._sio.call("service_serialization") SerializedDataService, await self._sio.call("service_serialization")
) )
@ -141,7 +152,7 @@ class Client:
self.proxy._connected = True self.proxy._connected = True
async def _handle_disconnect(self) -> None: async def _handle_disconnect(self) -> None:
logger.debug("Disconnected from '%s:%s' ...", self._hostname, self._port) logger.debug("Disconnected from '%s' ...", self._url)
self.proxy._connected = False self.proxy._connected = False
async def _handle_update(self, data: NotifyDict) -> None: async def _handle_update(self, data: NotifyDict) -> None:

View File

@ -45,7 +45,7 @@ def pydase_client() -> Generator[pydase.Client, None, Any]:
thread = threading.Thread(target=server.run, daemon=True) thread = threading.Thread(target=server.run, daemon=True)
thread.start() thread.start()
client = pydase.Client(hostname="localhost", port=9999) client = pydase.Client(url="ws://localhost:9999")
yield client yield client