Git Product home page Git Product logo

realtime-py's Introduction

realtime-py

Python Client Library to interface with the Phoenix Realtime Server

Requirements

Python 3 higher

Installation

pip3 install realtime==1.0.2

Installation from source

pip3 install -r requirements.txt
python3 usage.py 

Quick Start

from realtime.connection import Socket

def callback1(payload):
    print("Callback 1: ", payload)

def callback2(payload):
    print("Callback 2: ", payload)

if __name__ == "__main__":
    URL = "ws://localhost:4000/socket/websocket"
    s = Socket(URL)
    s.connect()

    channel_1 = s.set_channel("realtime:public:todos")
    channel_1.join().on("UPDATE", callback1)

    channel_2 = s.set_channel("realtime:public:users")
    channel_2.join().on("*", callback2)

    s.listen()

Sample usage with Supabase

Here's how you could connect to your realtime endpoint using Supabase endpoint. Correct as of 5th June 2021. Please replace SUPABASE_ID and API_KEY with your own SUPABASE_ID and API_KEY. The variables shown below are fake and they will not work if you try to run the snippet.

from realtime.connection import Socket

SUPABASE_ID = "dlzlllxhaakqdmaapvji"
API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MT"


def callback1(payload):
    print("Callback 1: ", payload)

if __name__ == "__main__":
    URL = f"wss://{SUPABASE_ID}.supabase.co/realtime/v1/websocket?apikey={API_KEY}&vsn=1.0.0"
    s = Socket(URL)
    s.connect()

    channel_1 = s.set_channel("realtime:*")
    channel_1.join().on("UPDATE", callback1)
    s.listen()

Then, go to the Supabase interface and toggle a row in a table. You should see a corresponding payload show up in your console/terminal.

realtime-py's People

Contributors

anand2312 avatar dependabot[bot] avatar dhaneshsabane avatar grdsdev avatar j0 avatar juancarlospaco avatar kavalerov avatar lionellloh avatar mansueli avatar markyao6275 avatar matthew-burkard avatar nielsrolf avatar nkitsaini avatar odiseo0 avatar orenwang avatar prettyirrelevant avatar rizkyrajitha avatar silentworks avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

realtime-py's Issues

Feature request: Gracefully close the socket

Feature request

Is your feature request related to a problem? Please describe.

There is a scenario that we need to close the connection and shut down the realtime server. It seems that there's currently no way to do this.

Describe the solution you'd like

Add Socket#close() method, or like realtime-js,. Socket#disconnect().

Describe alternatives you've considered

N/A

Additional context

Handle socket errors gracefully

For a long running realtime subscription, I find that it breaks randomly after a few hours. I would expect this to gracefully reconnect. This using simple https://github.com/supabase-community/realtime-py#sample-usage-with-supabase

2022-02-03 09:37:25,734:ERROR - Connection closed
Traceback (most recent call last):
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 750, in transfer_data
    message = await self.read_message()
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 819, in read_message
    frame = await self.read_data_frame(max_size=self.max_size)
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 895, in read_data_frame
    frame = await self.read_frame(max_size)
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 975, in read_frame
    extensions=self.extensions,
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/framing.py", line 55, in read
    data = await reader(2)
  File "/usr/lib/python3.7/asyncio/streams.py", line 679, in readexactly
    await self._wait_for_data('readexactly')
  File "/usr/lib/python3.7/asyncio/streams.py", line 473, in _wait_for_data
    await self._waiter
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 801, in _read_ready__data_received
    data = self._sock.recv(self.max_size)
ConnectionResetError: [Errno 104] Connection reset by peer

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/me/.local/lib/python3.7/site-packages/realtime/connection.py", line 65, in _listen
    msg = await self.ws_connection.recv()
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 421, in recv
    await self.ensure_open()
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 726, in ensure_open
    raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason
2022-02-03 09:37:29,153:ERROR - Connection with server closed
Traceback (most recent call last):
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 750, in transfer_data
    message = await self.read_message()
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 819, in read_message
    frame = await self.read_data_frame(max_size=self.max_size)
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 895, in read_data_frame
    frame = await self.read_frame(max_size)
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 975, in read_frame
    extensions=self.extensions,
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/framing.py", line 55, in read
    data = await reader(2)
  File "/usr/lib/python3.7/asyncio/streams.py", line 679, in readexactly
    await self._wait_for_data('readexactly')
  File "/usr/lib/python3.7/asyncio/streams.py", line 473, in _wait_for_data
    await self._waiter
  File "/usr/lib/python3.7/asyncio/selector_events.py", line 801, in _read_ready__data_received
    data = self._sock.recv(self.max_size)
ConnectionResetError: [Errno 104] Connection reset by peer

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/me/.local/lib/python3.7/site-packages/realtime/connection.py", line 110, in _keep_alive
    await self.ws_connection.send(json.dumps(data))
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 471, in send
    await self.ensure_open()
  File "/home/me/.local/lib/python3.7/site-packages/websockets/legacy/protocol.py", line 726, in ensure_open
    raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason

Decode binary messages broadcast to client

Feature request

Is your feature request related to a problem? Please describe.

This request will help to reduce the memory usage of Realtime server when broadcasting messages to the client.

Describe the solution you'd like

The solution is to be able to receive and decode binary messages of encoded json payloads from Realtime server.

Additional context

This change will be introduced to realtime-js via supabase/realtime-js#81

Setup Github Actions

Chore

We need a functioning CI checks and tests for this library so that we can ensure everything is working as expected.

Calling `Socket._close()` logs an Exception

Bug report

Describe the bug

When a websocket is closed using Socket._close(), it logs the following error:

ERROR:root:Connection with the server closed.
Traceback (most recent call last):
  File "realtime/connection.py", line 141, in _keep_alive
    await self.ws_connection.send(json.dumps(data))
  File "python3.11/site-packages/websockets/legacy/protocol.py", line 635, in send
    await self.ensure_open()
  File "python3.11/site-packages/websockets/legacy/protocol.py", line 939, in ensure_open
    raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedOK: sent 1000 (OK); then received 1000 (OK)

To Reproduce

Setup a Socket connection and then call Socket._close() using the async method.

Expected behavior

When the socket is explicitly closed by calling Socket._close(), I would expect it to:
a) No longer attempt to reconnect
b) Not log an error about the connection being closed

System information

  • Version of realtime-py: 1.0.6

ANON-KEY not working on change notification

Bug report

Describe the bug

Follow demo step, as

from realtime.connection import Socket

SUPABASE_ID = "dlzlllxhaakqdmaapvji"
API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MT"

def callback1(payload):
    print("Callback 1: ", payload)

if __name__ == "__main__":
    URL = f"wss://{SUPABASE_ID}.supabase.co/realtime/v1/websocket?apikey={API_KEY}&vsn=1.0.0"
    s = Socket(URL)
    s.connect()

    channel_1 = s.set_channel("realtime:*")
    channel_1.join().on("UPDATE", callback1)
    s.listen()

When API_KEY refers to Supabase secret service key, it works as expected.
But when API_KEY refers to ANON Key, it does not work at all -- code runs without compliant but cannot receive notification when change happened in table , even with access authorized by RLS on table.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. use demo code.
  2. toggle API_KEY between ANON_KEY and SERVICE_KEY.
  3. then change something in supabase table.
  4. check difference.

Expected behavior

ANON-KEY , or with authenticated role should receive change notification as SERVICE_KEY.

Hope the document make it clear on authorization method used in this client, and also how RLS could be integrated.

It doesn't work with Supabase

Bug report

Describe the bug

Receive no changes from Supabase Database.

To Reproduce

  1. Run the following code
SUPABASE_ID = <REDACTED>
API_KEY =  <REDACTED>


def callback1(payload):
    print("Callback 1: ", payload)

if __name__ == "__main__":
    URL = f"wss://{SUPABASE_ID}.supabase.co/realtime/v1/websocket?apikey={API_KEY}&vsn=1.0.0"
    s = Socket(URL)
    s.connect()

    channel_1 = s.set_channel("realtime:*")
    channel_1.join().on('*', callback1)
    s.listen()
  1. Go edit tables on Supabase, add row, update row, etc.
  2. Nothing happens

Expected behavior

See logs in the console

Callback 1: something

Screenshots

image

Send Valid User Access Token to Realtime Server

Feature request

Realtime server is now checking every minute to verify the validity of the user access token and storing updated user information from the JWT to Realtime's subscription table (used by Realtime WALRUS).

Describe the solution you'd like

  1. Realtime client pushes the user access token to all channels every heartbeat, which defaults to 30 seconds (see ref, ref, and ref).
  2. Supabase client sends latest and valid user access token on auth events SIGNED_IN and TOKEN_REFRESHED (see ref)*.
  3. Supabase client removes all subscriptions on auth event SIGNED_OUT (see ref)*.

*fix: improve auth for realtime row level security supabase-community/supabase-py#303

Additional context

Realtime Security (WALRUS) will be launched very soon so we'll mention that additional Supabase client libs, like this one, will be compatible with the new Realtime some time in the near future.

X-Client-Info Header

we're rolling out a header similar to Stripe's App-Data in all of the client libs so issues can be debugged more easily between the client and the backend

the javascript libs are done already: supabase/supabase-js#238

the format is: X-Client-Info: supabase-js/1.11.0

for client libs that wrap others (like how supabase-js wraps gotrue-js) we allow the wrapper lib to overwrite the wrapped lib's header (given that we can infer the gotrue-js version based on which supabase-js was used to make the call)

any help with rolling this out here would be incredible

Unable to open a socket connection with self-hosted Supabase

Bug report

Describe the bug

Following the README to connect to a self-hosted Supabase fails with TypeError: 'type' object is not subscriptable

Error log:

➜ pipenv run python -m test
Traceback (most recent call last):
  File "/home/dhanesh/.pyenv/versions/3.8.12/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/home/dhanesh/.pyenv/versions/3.8.12/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/dhanesh/dataDrive/playground/supabase-realtime-test/test.py", line 11, in <module>
    s = Socket(URL)
  File "/home/dhanesh/dataDrive/playground/supabase-realtime-test/.venv/lib/python3.8/site-packages/realtime/connection.py", line 51, in __init__
    self.channels = cast(defaultdict[str, List[Channel]], self.channels)
TypeError: 'type' object is not subscriptable

To Reproduce

Steps to reproduce the behavior:

  1. Follow the README to create a quick script that establishes a socket connection with self-hosted Supabase
  2. Run the script
  3. See error

Expected behavior

The connection should be established with Supabase.

Screenshots

NA

System information

  • OS: Ubuntu 22.04
  • Version of realtime-py: 1.0.0
  • Version of Python: 3.8.12
  • Version of Pipenv: 2022.6.7

Additional context

NA

[DEP]: Add `websockets >=12.0` support

Feature request

There are quite a few packages that are using the newer versions of websocket which makes supabase-py un-usable for a lot of projects where websockets are used.
I have created an issue to update the dependency in supabase-py

Describe the solution you'd like

An updated dependency of websockets >=12.0

Is this package dead?

I would love to use realtime-py for some app backend - but based on the number of commits in the past few months,
I am wondering if this project is dead?

Unable to run `usage.py` successfully

Hi @w3b6x9, @J0, @lionellloh and others,

I tried running the usage.py file after modifying the relevant topics served by Phoenix server.
But the value of channel_obj.joined is False after the channel_obj.join() is invoked. I am not sure what's wrong.

Below is the snippet of modified usage.py:

from realtime.connection import Socket

def callback1(payload):
    print("Callback 1: ", payload)

def callback2(payload):
    print("Callback 2: ", payload)

url = "ws://localhost:4000/socket/websocket"
s = Socket(url)

s.connect()
s.summary()

channel_1 = s.set_channel("robot:status")
channel_2 = s.set_channel("timer:update")

channel_1.join().on("new_msg", callback1)
channel_2.join().on("new_time", callback2)

print(channel_1.joined)
print(channel_2.joined)

if __name__ == "__main__":
    s.listen()

Phoenix Server is running fine with the respective Elixir clients able to send/receive messages with each other.
Moreover, the Phoenix Server output shows the following debug messages when usage.py is ran and I believe this states that the python client is able to connect the server.

[info] CONNECTED TO PhoenixServerWeb.UserSocket in 41µs
  Transport: :websocket
  Serializer: Phoenix.Socket.V1.JSONSerializer
  Parameters: %{}
[info] JOINED robot:status in 17µs
  Parameters: %{}
[info] JOINED timer:update in 7µs
  Parameters: %{}

Kindly highlight what I could have missed here.
Thanks in advance.

Unable to get realtime connection to Supabase locally

I am currently trying to use realtime.connection.Socket() with Supabase locally. I am following this guild (https://supabase.com/docs/guides/local-development). I am using a MacBook Pro with an M1 chip, realtime==0.0.4.

From the Supabase guide, I have run "supabase start" and "docker ps" in the terminal:
Terminal screenshot

Sample code to run:

from realtime.connection import Socket
# local service key
SUPA_SERVICE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSJ9.vI9obAHOGyVVKa3pD--kJlyxp-Z2zV9UUMAhKpNLAcU"

HOST_PORT = 54321

SUPA_REALTIME_URL = f"wss://localhost:{HOST_PORT}/realtime/v1/websocket?apikey={SUPA_SERVICE_KEY}&vsn=1.0.0"

s = Socket(SUPA_REALTIME_URL)
s.connect()

After running this code I get:
Screenshot 2022-06-28 at 13 24 58

Could this be because of the SUPA_REALTIME_URL being incorrect? I have tried several different HOST_PORT shown in "docker ps" with no success.

Having trouble with Supabase usage example

Hi there! I'm new to Supabase, but I'm very excited about the realtime functionality. When I try to run the example script from README.md, it connects to my Supabase database without issues, but I'm not receiving updates when table rows are modified.

I've tried:

  1. Setting the "Source" for supabase_realtime to "All tables" (this was not on by default – not sure if this is necessary for the example to work)
  2. Replacing "UPDATE" with "*"
  3. Checking the value of channel_1.joined (it returns False, similar to #29)

Please let me know if there's something simple I'm missing!

Support WALRUS (Postgres RLS) Integration with Realtime Server

Feature request

Is your feature request related to a problem? Please describe.

Currently, Realtime server sends all database changes to all connected clients despite Postgres Row Level Security policies. This poses security concerns when developers wish to broadcast database changes containing sensitive data to an authorized subset of connected clients based on tables with RLS enabled and row security policies.

Realtime server will integrate WALRUS (Write Ahead Log Realtime Unified Security), which means there are some changes that lib clients need to make in order to support this new security functionality.

Describe the solution you'd like

The following changes will need to be made:

  • Pass user auth token, if available, as channel params with key user_token when subscribing client to Realtime channel.
  • Update Realtime transformers to pass through changes when they're already arrays.
    Realtime w/ WALRUS will pass Postgres array types as [1, 2, 3], _int4, and ["a", "b", "c"], _text, instead of "{1,2,3}" (_int4/_text) so this can be forwarded without any transformations. However, clients should maintain backward compatibility so they should still be able to handle stringified Postgres array (e.g. "{1,2,3}") cases.

The changes have already been applied to supabase-js and realtime-js and their PRs can be referenced while making the necessary changes:

  • Passing user auth token as user_token

feat: add user_token when creating realtime channel subscription supabase-community/supabase-py#270

  • Update Realtime transformers (including bug fixes)

feat: update transformers to accept already transformed walrus changes supabase-community/realtime-py#50

fix: error parsing JSON when transforming array data types supabase-community/supabase-py#113

The bug fixes include longstanding issues with transformers in realtime-js where range types are first JSON parsed (which results in an error sometimes due to Postgres' range exclusive and inclusive bounds) and how stringified (e.g. "{1,2,3}") array types are split (can't always split on "," in cases like _daterange). Please see PR for additional context.

Additional context

We're looking to launch WALRUS in Realtime at the end of November, and all developers using the JS client will have to do is version bump their supabase-js to v1.2.0, which contains all the changes described above.

Please reach out if there's any questions and definitely tag me to confirm PRs if you'd like! Thank you!

Python realtime with RLS

Bug report

Describe the bug

Unable to catch event if policy checking if user is authentificated exists on table.

To Reproduce

Python client code:

from realtime.connection import Socket

SUPABASE_URL = "project_id"
SUPABASE_KEY = "anon_key"

realtime_url = f"wss://{SUPABASE_URL}/realtime/v1/websocket?apikey={SUPABASE_KEY}"


def callback(event):
    print(event)


s = Socket(realtime_url)
s.connect()

channel = s.set_channel("realtime:*")
channel.join().on("*", callback)
s.listen()

It is work for public tables, but when we want to enable RLS and allow to CRUD only for authentificated users with following policy:

CREATE POLICY "User Is Authentificated" ON "public"."myTable"
AS PERMISSIVE FOR ALL
TO authenticated
USING (true)

Expected behavior

Be able to authentificate with Bearer JWT token as user

System information

  • Version of realtime-py: 1.0.2

Next release

This issue should have been a discussion but since discussions aren't open I guess it's fine if we discuss it here.

Is there a goal or roadmap for a next release, something planned?

Payload option for Channel.join() function

Feature request

Is your feature request related to a problem? Please describe.

For an integration project, I need to specify some additional payload, when joining a channel. Therefore, I'd like to enhance the Channel.join function for being able to pass a payload like this:

# common connection and channel setup

join_payload = { 
    "key1": value1,
    "key2": value2
}

channel.join(payload)

Describe the solution you'd like

The Channel._join function foresees already the usage of some payload:

        join_req = dict(topic=self.topic, event="phx_join",
                        payload={}, ref=None)

Therefore, I would add a payload parameter to the join functions, like this:

    def join(self, payload:dict = {}) -> Channel:
        # ...

    async def _join(self, payload:dict) -> None:
        # ...
        join_req = dict(topic=self.topic, event="phx_join",
                        payload=payload, ref=None)
        # ...

Describe alternatives you've considered

n/a

Additional context

This would also effect my ticket #133.

Socket disconnect after a while

Hi!

I am facing an issue both in local (Mac OS Sonoma 14.2) and deployed on render.com.

Basically after a while the socket close without receiving further updates and I get this error:

2024-01-26 04:04:08,363:ERROR - Connection with the server closed.
Traceback (most recent call last):
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 959, in transfer_data
message = await self.read_message()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 1029, in read_message
frame = await self.read_data_frame(max_size=self.max_size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 1104, in read_data_frame
frame = await self.read_frame(max_size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 1161, in read_frame
frame = await Frame.read(
^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/websockets/legacy/framing.py", line 68, in read
data = await reader(2)
^^^^^^^^^^^^^^^
File "/opt/render/project/python/Python-3.11.0/lib/python3.11/asyncio/streams.py", line 726, in readexactly
raise exceptions.IncompleteReadError(incomplete, n)
asyncio.exceptions.IncompleteReadError: 0 bytes read on a total of 2 expected bytes
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/realtime/connection.py", line 76, in _listen
msg = await self.ws_connection.recv()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 568, in recv
await self.ensure_open()
File "/opt/render/project/src/.venv/lib/python3.11/site-packages/websockets/legacy/protocol.py", line 930, in ensure_open
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: no close frame received or sent

To Reproduce

  1. Launch the server with python main.py
  2. Wait a while without receiving updates on the socket

Expected behavior

The socket should't disconnect.

Additional context

This is my current python code

if __name__ == "__main__":
    URL = f"wss://{os.getenv('SUPABASE_ID')}.supabase.co/realtime/v1/websocket?apikey={os.getenv('SUPABASE_SERVICE_KEY')}&vsn=1.0.0"
    s = Socket(URL)
    s.connect()

    channel_1 = s.set_channel("realtime:public:todos")
    channel_1.join().on("INSERT", lambda msg: asyncio.ensure_future(callback(msg)))

    s.listen()

Add Test Suite For Realtime-py

Currently, we have stub tests but they don't cover code within the realtime-py.

We're hoping to add coveralls and write additional tests for the library ideally using pytest or similar.

Bump Websockets version?

Hi there! Would it be possible to bump the websockets version to the current 11.0.2 - the older version is causing conflicts with common packages (like Prefect.io) that use the latest version.

Asynchronous API Alternatives

Feature request

Is your feature request related to a problem? Please describe.

I want to be able to have asynchronous tasks parallel to realtime-py. Basically the same mentioned @albertpurnama in a comment to #66 . While #66 is about using listen() in separate thread, this request and I guess the one from @albertpurnma, is to have an official public asynchronous API, instead of using private _ functions.

Describe the solution you'd like

I would like to add async siblings to the following functions:

  • Socket.listen -> Socket.listen_async
  • Socket.connect -> Socket.connect_async
  • Channel.join -> Channel.join_async

This would the naming convention proposed here. I know this is no official document. But I couldn't find a better one.

The async function are basically a public wrapper around the private async functions.

Furthermore, I don't know if my list above is sufficient. Please extend the list. But it was sufficient, when I tried it some time ago.

Describe alternatives you've considered

Instead of creating a wrapper for the private async functions, they could be renamed.

But this would create more implementation effort for this ticket, and I like the idea of having a public function, which remains unchanged, even if internal stuff changes.

Additional context

n/a

Unable to use channels to SEND from Python to Phoenix?

Documentation and examples show how to listen from messages from Phoenix, but sending to phoenix is not documented, nor is it clear that this is even possible.

🐘 tbrowne@suprabonds:~$ ipy
Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
Type 'copyright', 'credits' or 'license' for more information
IPython 8.0.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from realtime.connection import Socket
In [2]: import inspect
In [3]: def c1(payload):
   ...:     print("C1", payload)
In [4]: URL = "ws://localhost:4000/socket/websocket"
In [5]: s = Socket(URL)
In [6]: s.connect()  # this works fine as I can see it working on Phoenix side
2022-06-19 18:20:06,987:INFO - Connection was successful
In [7]: chan1 = s.set_channel("ping")
In [8]: chan1.join().on("UPDATE", c1)
Out[8]: <realtime.channel.Channel at 0x7f988a08f3d0>
In [9]: for a in inspect.getmembers(chan1):
   ...:     print(a)
('__class__', <class 'realtime.channel.Channel'>)
('__delattr__', <method-wrapper '__delattr__' of Channel object at 0x7f988a08f3d0>)
('__dict__', {'socket': <realtime.connection.Socket object at 0x7f988a0bef70>, 'topic': 'ping', 'params': {}, 'listeners': [CallbackListener(event='UPDATE', callback=<function c1 at 0x7f988b056f70>)], 'joined': False})
('__dir__', <built-in method __dir__ of Channel object at 0x7f988a08f3d0>)
('__doc__', '\n    `Channel` is an abstraction for a topic listener for an existing socket connection.\n    Each Channel has its own topic and a list of event-callbacks that responds to messages.\n    Should only be instantiated through `connection.Socket().set_chanel(topic)`\n    Topic-Channel has a 1-many relationship.\n    ')
('__eq__', <method-wrapper '__eq__' of Channel object at 0x7f988a08f3d0>)
('__format__', <built-in method __format__ of Channel object at 0x7f988a08f3d0>)
('__ge__', <method-wrapper '__ge__' of Channel object at 0x7f988a08f3d0>)
('__getattribute__', <method-wrapper '__getattribute__' of Channel object at 0x7f988a08f3d0>)
('__gt__', <method-wrapper '__gt__' of Channel object at 0x7f988a08f3d0>)
('__hash__', <method-wrapper '__hash__' of Channel object at 0x7f988a08f3d0>)
('__init__', <bound method Channel.__init__ of <realtime.channel.Channel object at 0x7f988a08f3d0>>)
('__init_subclass__', <built-in method __init_subclass__ of type object at 0x2071780>)
('__le__', <method-wrapper '__le__' of Channel object at 0x7f988a08f3d0>)
('__lt__', <method-wrapper '__lt__' of Channel object at 0x7f988a08f3d0>)
('__module__', 'realtime.channel')
('__ne__', <method-wrapper '__ne__' of Channel object at 0x7f988a08f3d0>)
('__new__', <built-in method __new__ of type object at 0x9075a0>)
('__reduce__', <built-in method __reduce__ of Channel object at 0x7f988a08f3d0>)
('__reduce_ex__', <built-in method __reduce_ex__ of Channel object at 0x7f988a08f3d0>)
('__repr__', <method-wrapper '__repr__' of Channel object at 0x7f988a08f3d0>)
('__setattr__', <method-wrapper '__setattr__' of Channel object at 0x7f988a08f3d0>)
('__sizeof__', <built-in method __sizeof__ of Channel object at 0x7f988a08f3d0>)
('__str__', <method-wrapper '__str__' of Channel object at 0x7f988a08f3d0>)
('__subclasshook__', <built-in method __subclasshook__ of type object at 0x2071780>)
('__weakref__', None)
('_join', <bound method Channel._join of <realtime.channel.Channel object at 0x7f988a08f3d0>>)
('join', <bound method Channel.join of <realtime.channel.Channel object at 0x7f988a08f3d0>>)
('joined', False)
('listeners', [CallbackListener(event='UPDATE', callback=<function c1 at 0x7f988b056f70>)])
('off', <bound method Channel.off of <realtime.channel.Channel object at 0x7f988a08f3d0>>)
('on', <bound method Channel.on of <realtime.channel.Channel object at 0x7f988a08f3d0>>)
('params', {})
('socket', <realtime.connection.Socket object at 0x7f988a0bef70>)
('topic', 'ping')

As you can see Python inspect module does not show anything on channel chan1 that might look like a method for sending. Could you elucidate on if / how one can use this library for two-way comms? Thanks.

error while using Socket(URL).connect()

Error :

Traceback (most recent call last):
  File "/usr/lib/python3.9/socket.py", line 953, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

Screenshots

Here is my script that produces the error
image

System information

  • OS: Linux,Parrot os
  • Version of supabase-client == 0.2.5
  • Version of python == 3.9.2
  • version of realtime == 0.0.5

Additional context

Also i cant seem to install realtime version 0.1.1a0

ERROR: Could not find a version that satisfies the requirement realtime==0.1.1a0 (from versions: 0.0.2, 0.0.3, 0.0.4, 0.0.5)
ERROR: No matching distribution found for realtime==0.1.1a0`pip install realtime==0.1.1a0 

Update websockets dependency version

realtime-py uses websockets = "^9.1" which is outdated causing realtime-py to be incompatible with other libraries using later versions of websockets such as uvicorn.

poetry add supabase
Using version ^0.5.3 for supabase

Updating dependencies
Resolving dependencies... (2.4s)

  SolverProblemError

  Because no versions of supabase match >0.5.3,<0.6.0
   and supabase (0.5.3) depends on realtime (>=0.0.4,<0.0.5), supabase (>=0.5.3,<0.6.0) requires realtime (>=0.0.4,<0.0.5).
  And because no versions of realtime match >0.0.4,<0.0.5
   and realtime (0.0.4) depends on websockets (>=9.1,<10.0), supabase (>=0.5.3,<0.6.0) requires websockets (>=9.1,<10.0).
  And because uvicorn (0.17.6) depends on websockets (>=10.0)
   and no versions of uvicorn match >0.17.6,<0.18.0, supabase (>=0.5.3,<0.6.0) is incompatible with uvicorn (>=0.17.6,<0.18.0).
  So, because supa-test depends on both uvicorn (^0.17.6) and supabase (^0.5.3), version solving failed.

  at ~/.poetry/lib/poetry/puzzle/solver.py:241 in _solve
      237│             packages = result.packages
      238│         except OverrideNeeded as e:
      239│             return self.solve_in_compatibility_mode(e.overrides, use_latest=use_latest)
      240│         except SolveFailure as e:
    → 241│             raise SolverProblemError(e)
      242│ 
      243│         results = dict(
      244│             depth_first_search(
      245│                 PackageNode(self._package, packages), aggregate_package_nodes

Realtime RLS Broadcasts Errors

Realtime RLS will be broadcasting database changes with errors so that clients can capture what went wrong when listening to database changes.

Please see here for the current error states: https://github.com/supabase/walrus/tree/generic_claims#error-states.

Realtime RLS will broadcast errors as either null (no errors) or an array of strings (at least one error present).

Here are two example Realtime RLS JSON payloads with errors:

{
      "columns": [{"name": "id", "type": "int8"}, {"name": "details", "type": "text"}],
      "commit_timestamp": "2021-12-28T23:59:38.984538+00:00",
      "schema": "public",
      "table": "todos",
      "type": "UPDATE",
      "old_record": {"details": "previous test", "id": 12, "user_id": 1},
      "record": {"details": "test...", "id": 12, "user_id": 1},
      "errors": ["Error 413: Payload Too Large"]
}
{
      "columns": [],
      "commit_timestamp": null,
      "schema": "public",
      "table": "todos",
      "type": "UPDATE",
      "old_record": {},
      "record": {},
      "errors": ["Error.."]
}

Notice:

  • columns will always be an array but can be empty
  • commit_timestamp will either be a string or null
  • old_record/record will always be an object but can be empty

Using realtime.listen() in a separate thread

Hello,

Is it possible to use the realtime.listen() function in a separate thread?
All my trials have failed so far causing following exception:

raise RuntimeError('There is no current event loop in thread %r.'

at the line: loop = asyncio.get_event_loop() # TODO: replace with get_running_loop in connection.py

Cheers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.