Package: python-thingsdb
Python connector for ThingsDBThis library requires Python 3.6 or higher.InstallationQuick usageClientauthenticatecloseconnectconnect_poolget_default_scopeget_event_loopget_roomsis_connectedqueryreconnectrunset_default_scopewait_closedRoommethodspropertiesjoinleaveemitno_joinFailed packagesInstallationJust use pip:pip install python-thingsdbOr, clone the project and use setup.py:python setup.py installQuick usageimportasynciofromthingsdb.clientimportClientasyncdefhello_world():client=Client()# replace `localhost` with your ThingsDB server addressawaitclient.connect('localhost')try:# replace `admin` and `pass` with your username and password# or use a valid token stringawaitclient.authenticate('admin','pass')# perform the hello world code...print(awaitclient.query('''"Hello World!";''')finally:# the will close the client in a nice wayclient.close()awaitclient.wait_closed()# run the hello world exampleasyncio.get_event_loop().run_until_complete(hello_world())ClientThis is an client usingasynciowhich can be used for running queries to
ThingsDB.thingsdb.client.Client(auto_reconnect:bool=True,ssl:Optional[Union[bool,ssl.SSLContext]]=None,loop:Optional[asyncio.AbstractEventLoop]=None)->ClientInitialize a ThingsDB clientArgsauto_reconnect (bool, optional):
When set toTrue, the client will automatically
reconnect when a connection is lost. If set toFalseand the
connection gets lost, one may call thereconnect()method to
make a new connection. The auto-reconnect option will listen to
node changes and automatically start a reconnect loop if theshutting-downstatus is received from the node.
Defaults toTrue.ssl (SSLContext or bool, optional):
Accepts an ssl.SSLContext for creating a secure connection
using SSL/TLS. This argument may simply be set toTruein
which case a context usingssl.PROTOCOL_TLSis created.
Defaults toNone.loop (AbstractEventLoop, optional):
Can be used to run the client on a specific event loop.
If this argument is not used, the default event loop will be
used. Defaults toNone.authenticateasyncClient().authenticate(*auth:Union[str,tuple],timeout:Optional[int]=5)->NoneAuthenticate a ThingsDB connection.Args*auth (str or (str, str)):
Argumentauthcan be be either a string with a token or a
tuple with username and password. (the latter may be provided
as two separate argumentstimeout (int, optional):
Can be be used to control the maximum time in seconds for the
client to wait for response on the authentication request.
The timeout may be set toNonein which case the client will
wait forever on a response. Defaults to 5.closeClient().close()->NoneClose the ThingsDB connection.This method will return immediately so the connection may not be
closed yet after a call toclose(). Use thewait_closed()method
after calling this method if this is required.connectClient().connect(host:str,port:int=9200,timeout:Optional[int]=5)->asyncio.FutureConnect to ThingsDB.This method willonlycreate a connection, so the connection is not
authenticated yet. Use theauthenticate(..)method after creating a
connection before using the connection.Argshost (str):
A hostname, IP address, FQDN to connect to.port (int, optional):
Integer value between 0 and 65535 and should be the port number
where a ThingsDB node is listening to for client connections.
Defaults to 9200.timeout (int, optional):
Can be be used to control the maximum time the client will
attempt to create a connection. The timeout may be set toNonein which case the client will wait forever on a
response. Defaults to 5.ReturnsFuture which should be awaited. The result of the future will be
set toNonewhen successful.Do not use this method if the client is already
connected. This can be checked withclient.is_connected().connect_poolClient().connect_pool(pool:list,*auth:Union[str,tuple])->asyncio.FutureConnect using a connection pool.When using a connection pool, the client will randomly choose a node
to connect to. When a node is going down, it will inform the client
so it will automatically re-connect to another node. Connections will
automatically authenticate so the connection pool requires credentials
to perform the authentication.Examplesawaitconnect_pool(['node01.local',# address as string'node02.local',# port will default to 9200('node03.local',9201),# ..or with an explicit port],"admin","pass")Argspool (list of addresses):
Should be an iterable with node address strings, or tuples
withaddressandportcombinations in a tuple or list.*auth (str or (str, str)):
Argumentauthcan be be either a string with a token or a
tuple with username and password. (the latter may be provided
as two separate argumentsReturnsFuture which should be awaited. The result of the future will be
set toNonewhen successful.Do not use this method if the client is already
connected. This can be checked withclient.is_connected().get_default_scopeClient().get_default_scope()->strGet the default scope.The default scope may be changed with theset_default_scope()method.ReturnsThe default scope which is used by the client when no specific scope is specified.get_event_loopClient().get_event_loop()->asyncio.AbstractEventLoopCan be used to get the event loop.ReturnsThe event loop used by the client.get_roomsClient().get_rooms()->tupleCan be used to get the rooms which are joined by this client.ReturnsAtuplewith uniqueRoominstances.is_connectedClient().is_connected()->boolCan be used to check if the client is connected.ReturnsTruewhen the client is connected elseFalse.queryClient().query(code:str,scope:Optional[str]=None,timeout:Optional[int]=None,**kwargs:Any)->asyncio.FutureQuery ThingsDB.Use this method to runcodein a scope.Argscode (str):
ThingsDB code to run.scope (str, optional):
Run the code in this scope. If not specified, the default scope
will be used. Seehttps://docs.thingsdb.net/v0/overview/scopes/for how to format a scope.timeout (int, optional):
Raise a time-out exception if no response is received within X
seconds. If no time-out is given, the client will wait forever.
Defaults toNone.**kwargs (any, optional):
Can be used to inject variable into the ThingsDB code.ExamplesAlthough we could just as easy have wrote everything in the
ThingsDB code itself, this example shows how to use **kwargs for
injecting variable into code. In this case the variablebook.res=awaitclient.query(".my_book = book;",book={'title':'Manual ThingsDB'})ReturnsFuture which should be awaited. The result of the future will
contain the result of the ThingsDB code when successful.If the ThingsDB code will return with an exception, then this
exception will be translated to a Python Exception which will be
raised. See thingsdb.exceptions for all possible exceptions andhttps://docs.thingsdb.net/v0/errors/for info on the error codes.reconnectasyncClient().reconnect()->Optional[Future]Re-connect to ThingsDB.This method can be used, even when a connection still exists. In case
of a connection pool, a call toreconnect()will switch to another
node. If the client is already re-connecting, this method returnsNone,
otherwise, the reconnectFutureis returned, await of the Future is
possible but not required.runClient().run(procedure:str,*args:Optional[Any],scope:Optional[str]=None,timeout:Optional[int]=None,**kwargs:Any)->asyncio.FutureRun a procedure.Use this method to run a stored procedure in a scope.Argsprocedure (str):
Name of the procedure to run.*args (any):
Arguments which are injected as the procedure arguments.
Instead of positional, the arguments may also be parsed using
keyword arguments but not both at the same time.scope (str, optional):
Run the procedure in this scope. If not specified, the default
scope will be used.
Seehttps://docs.thingsdb.net/v0/overview/scopes/for how to
format a scope.timeout (int, optional):
Raise a time-out exception if no response is received within X
seconds. If no time-out is given, the client will wait forever.
Defaults toNone.**kwargs (any, optional):
Arguments which are injected as the procedure arguments.
Instead of by name, the arguments may also be parsed using
positional arguments but not both at the same time.ReturnsFuture which should be awaited. The result of the future will
contain the result of the ThingsDB procedure when successful.If the ThingsDB code will return with an exception, then this
exception will be translated to a Python Exception which will be
raised. See thingsdb.exceptions for all possible exceptions andhttps://docs.thingsdb.net/v0/errors/for info on the error codes.set_default_scopeClient().set_default_scope(scope:str)->NoneSet the default scope.Can be used to change the default scope which is initially set to@t.Argsscope (str):
Set the default scope. A scope may start with either the/character, or@. Examples:"//stuff","@:stuff","/node"wait_closedasyncClient().wait_closed()->NoneWait for a connection to close.Can be used after calling theclose()method to determine when the
connection is actually closed.RoomRooms can be implemented to listen for events from ThingsDB rooms.Se the example code:fromthingsdb.roomimportRoom,eventclassChat(Room):@event('msg')defon_msg(self,msg):print(msg)This will listen formsgevents on a ThingsDB room. To connect out class to a
room, you have to initialize the class with aroomIdof some ThingsDB code which
returns theroomIdas integer value. For example:# Create a chat instance. In this example we initialize our chat with some ThingsDB codechat=Chat("""//ti// Create .chat room if the room does not exist..has('chat') || .chat = room();// return the roomId..chat.id();""")# Now we can join the room. (we assume that you have a ThingsDB client)awaitchat.join(client)Room Init Argsroom (int/str):
The room Id or ThingsDB code which returns the Id of the room.
Examples are123,'.my_room.id();'scope (str):
Collection scope. If no scope is given, the scope will later
be set to the default client scope once the room is joined.Room MethodsBesides implementing an@eventhandler, a room has also some methods which can be implemented to control or initialize a room.on_init(self) -> NoneCalled when a room is joined. This method will be called only once,
thusnotafter a re-connect like theon_join(..)method. This
method is guaranteed to be calledbeforetheon_join(..)method.on_join(self) -> None:Called when a room is joined. Unlike theon_init(..)method,
theon_join(..)method will be called again after a re-connect.This is an async method and usually the best method to perform
some ThingsDB queries (if required).Unless thewaitargument to the Room.join(..) function is explicitly
set to0orNone, the first call to this method will finish before the
call toRoom.join()is returned.on_leave(self) -> None:Called after a leave room request. This event isnottriggered
by ThingsDB when a client disconnects or when a node is shutting down.on_delete(self) -> None:Called when the room is removed from ThingsDB.on_emit(self, event: str, *args) -> None:Called when no event handler is configured for the event.
By default, theon_emitwill display a "debug" log message when called to
show that no handler for the event is found.Room PropertiesThe following properties are available on a room instance. Note that some properties
might returnNoneas long as a room is not joined.PropertyDescriptionidReturns the roomId.scopeReturns the scope of the room.clientReturns the associated client of the room.joinRoom().join(client:Client,wait:Optional[float]=60.0)->NoneJoins the room.Argsclient(thingsdb.client.Client):
ThingsDB client instance.wait(float):
Max time (in seconds) to wait for the firston_joincall.
If wait is set to0orNone, the join method will not wait for
the firston_joincall to happen.leaveRoom().leave()->NoneLeave the room. If the room is not found, aLookupErrorwill be raised.emitRoom().emit(event:str,*args:Optional[Any],)->asyncio.FutureEmit an event to a room.Argsevent (str):
Name of the event to emit.*args (any):
Additional argument to send with the event.ReturnsFuture which should be awaited. The result of the future will
be set toNonewhen successful.no_joinRoom().no_join(client:Client)->NoneOnly translate the code(or test the Id)to a room Id. This is useful if you only
want to use the room to emit events and not listen to events.Argsclient(thingsdb.client.Client):
ThingsDB client instance.Failed packagesset_package_fail_file(fn:str='')->NoneConfigure a file name to dump the last failed package.Only the MessagePack data will be stored in this file, not the package
header. This is useful for debugging packages which fail to unpack.
Note that only a single fail file can be used which is active (or not) for
all clients.When empty (''), a failed package willnotbe dumped to file.fromthingsdb.clientimportset_package_fail_fileset_package_fail_file('/tmp/thingsdb-invalid-data.mp')# When a package is received which fails to unpack, the data from this package# will be stored to file.