@@ -10,68 +10,203 @@ class Buildin:
1010 #
1111
1212 async def collection_info (self , collection : U [int , str ]) -> dict :
13+ """Returns information about a specific collection.
14+
15+ This function requires QUERY privileges on the requested collection,
16+ or CHANGE privileges on the @thingsdb scope.
17+
18+ This function does not generate a change.
19+ """
1320 return await self .query (
14- f 'collection_info(collection)' ,
21+ 'collection_info(collection)' ,
1522 collection = collection ,
1623 scope = '@t' )
1724
18- async def collections_info (self ):
25+ async def collections_info (self ) -> list :
26+ """Returns collection information about all collections in ThingsDB.
27+ """
1928 return await self .query ('collections_info()' , scope = '@t' )
2029
2130 async def del_collection (self , collection : U [int , str ]):
31+ """Delete a collection.
32+
33+ This function generates a change.
34+ """
2235 return await self .query (
23- f 'del_collection(collection)' ,
36+ 'del_collection(collection)' ,
2437 collection = collection ,
2538 scope = '@t' )
2639
2740 async def del_expired (self ):
41+ """Delete all expired tokens.
42+
43+ Requires GRANT privileges on the @thingsdb scope.
44+
45+ This function generates a change.
46+ """
2847 return await self .query ('del_expired()' , scope = '@t' )
2948
3049 async def del_module (self , name : str ):
31- return await self .query (f'del_module(key)' , name = name , scope = '@t' )
50+ """Delete a module. A SIGTERM signal will be send to the process for
51+ the module which might cancel running futures.
52+
53+ This function generates a change.
54+ """
55+ return await self .query ('del_module(key)' , name = name , scope = '@t' )
3256
3357 async def del_node (self , node_id : int ):
34- return await self .query (f'del_node(id)' , id = node_id , scope = '@t' )
58+ """Delete a node from ThingsDB.
59+
60+ Before deleting a node, the node must be offline. As long is the node
61+ is active, you are not allowed to delete the node. See shutdown for
62+ shutting down a node by using a query.
63+
64+ This function generates a change.
65+ """
66+ return await self .query ('del_node(id)' , id = node_id , scope = '@t' )
3567
3668 async def del_token (self , key : str ):
37- return await self .query (f'del_token(key)' , key = key , scope = '@t' )
69+ """Delete a token.
70+
71+ This function requires GRANT privileges on the @thingsdb scope unless
72+ the given token belongs to the logged on user. In the latter case,
73+ only CHANGE privileges are required.
74+
75+ This function generates a change.
76+ """
77+ return await self .query ('del_token(key)' , key = key , scope = '@t' )
3878
3979 async def del_user (self , name : str ):
40- return await self . query ( f'del_user(name)' , name = name , scope = '@t' )
80+ """Delete a user.
4181
42- # TODO: deploy module
82+ It is not possible to delete your own user account and a bad_data_err()
83+ will be raised in case you try to. Any tokens associated with the user
84+ will also be deleted.
85+
86+ This function requires GRANT privileges on the @thingsdb scope.
87+
88+ This function generates a change.
89+ """
90+ return await self .query ('del_user(name)' , name = name , scope = '@t' )
91+
92+ async def deploy_module (
93+ self ,
94+ name : str ,
95+ data : Optional [U [bytes , str ]] = None ):
96+ """Deploy a module on all nodes.
97+
98+ The module must be configured first, using the new_module() function.
99+ This function is used to write the module data (or plain python code)
100+ to the module. After deploying the code, the module will be restarted
101+ on every node.
102+
103+ Before deploying a module, it is strongly recommended to use a
104+ development environment before deploying the module into production.
105+
106+ When the `data` argument is None, no data will be overwritten but the
107+ module will be restarted on all nodes. This might be useful if you want
108+ to force a module restart on all nodes.
109+
110+ This function generates a change.
111+ """
112+ return await self .query (
113+ 'deploy_module(name, data)' ,
114+ name = name ,
115+ data = data ,
116+ scope = '@t' )
43117
44118 async def grant (self , target : U [int , str ], user : str , mask : int ):
119+ """Grant, collection or general, privileges to a user.
120+
121+ Access to a user is provided by setting a bit mask to either the @node,
122+ @thingsdb or a @collection scope.
123+
124+ To use this function, at least CHANGE privileges on the @thingsdb scope
125+ and GRANT privileges on the target scope are required.
126+
127+ It is not possible to set privileges on a specific node scope.
128+ Therefore scope @node will apply to all nodes in ThingsDB.
129+
130+ The following pre-defined masks are available:
131+ (from thingsdb import Access)
132+
133+ Mask | Description
134+ ----------------- | ------------
135+ Access.QUERY (1) | Gives read access.
136+ Access.CHANGE (2) | Gives modify access.
137+ Access.GRANT (4) | Gives modify and grant (and revoke) privileges.
138+ Access.JOIN (8) | Gives join (and leave) privileges.
139+ Access.RUN (16) | Gives run procedures access.
140+ Access.FULL (31) | A mask for full privileges.
141+
142+ It is not possible to have GRANT privileges without also having CHANGE
143+ privileges. However, ThingsDB automatically applies the required
144+ privileges so when setting for example GRANT privileges, ThingsDB makes
145+ sure that the user also gets CHANGE privileges.
146+
147+ This function generates a change.
148+ """
45149 return await self .query (
46- f 'grant(target, user, mask)' ,
150+ 'grant(target, user, mask)' ,
47151 target = target ,
48152 user = user ,
49153 mask = mask ,
50154 scope = '@t' )
51155
52156 async def has_collection (self , name : str ):
53- return await self .query (f'has_collection(name)' , name = name , scope = '@t' )
157+ """Determines if a collection exists in ThingsDB.
158+
159+ This function does not generate a change.
160+ """
161+ return await self .query ('has_collection(name)' , name = name , scope = '@t' )
54162
55163 async def has_module (self , name : str ):
56- return await self .query (f'has_module(name)' , name = name , scope = '@t' )
164+ """Determines if a module exists in ThingsDB.
165+
166+ The scope restriction of the module has no impact on the result of this
167+ function.
168+
169+ This function does not generate a change.
170+ """
171+ return await self .query ('has_module(name)' , name = name , scope = '@t' )
57172
58173 async def has_node (self , node_id : int ):
59- return await self .query (f'has_node(id)' , id = node_id , scope = '@t' )
174+ """Determines if a node exists in ThingsDB.
175+
176+ This function does not generate a change.
177+ """
178+ return await self .query ('has_node(id)' , id = node_id , scope = '@t' )
60179
61180 async def has_token (self , token : str ):
62- return await self .query (f'has_token(token)' , token = token , scope = '@t' )
181+ """Determines if a token exists in ThingsDB.
182+
183+ This function requires GRANT privileges on the @thingsdb scope.
184+
185+ This function does not generate a change.
186+ """
187+ return await self .query ('has_token(token)' , token = token , scope = '@t' )
63188
64189 async def has_user (self , name : str ):
65- return await self .query (f'has_user(name)' , name = name , scope = '@t' )
190+ """Determines if a user exists in ThingsDB.
191+
192+ This function requires GRANT privileges on the @thingsdb scope.
193+
194+ This function does not generate a change.
195+ """
196+ return await self .query ('has_user(name)' , name = name , scope = '@t' )
66197
67198 async def module_info (self , name : str ) -> dict :
68- return await self .query (f 'module_info(name)' , name = name , scope = '@t' )
199+ return await self .query ('module_info(name)' , name = name , scope = '@t' )
69200
70201 async def modules_info (self ) -> list :
71202 return await self .query ('modules_info()' , scope = '@t' )
72203
73204 async def new_collection (self , name : str ):
74- return await self .query (f'new_collection(name)' , name = name , scope = '@t' )
205+ """Create a new collection.
206+
207+ This function generates a change.
208+ """
209+ return await self .query ('new_collection(name)' , name = name , scope = '@t' )
75210
76211 # TODO: new module
77212 # TODO: new node
@@ -86,35 +221,43 @@ async def new_token(
86221 expiration_time = int (datetime .datetime .timestamp (expiration_time ))
87222
88223 return await self .query (
89- f 'new_token(user, expiration_time, description)' ,
224+ 'new_token(user, expiration_time, description)' ,
90225 user = user ,
91226 expiration_time = expiration_time ,
92227 description = description ,
93228 scope = '@t' )
94229
95230 async def new_user (self , name : str ):
96- return await self .query (f'new_user(name)' , name = name , scope = '@t' )
231+ """Creates a new user to ThingsDB. The new user is created without a
232+ password, token and access privileges. You probably want to set a
233+ password or add a new token, and assign some privileges using grant(…).
234+
235+ This function requires GRANT privileges on the @thingsdb scope.
236+
237+ This function generates a change.
238+ """
239+ return await self .query ('new_user(name)' , name = name , scope = '@t' )
97240
98241 async def rename_collection (
99242 self ,
100243 collection : U [int , str ],
101244 new_name : str ) -> None :
102245 return await self .query (
103- f 'rename_collection(collection, new_name)' ,
246+ 'rename_collection(collection, new_name)' ,
104247 collection = collection ,
105248 new_name = new_name ,
106249 scope = '@t' )
107250
108251 async def rename_module (self , name : str , new_name : str ) -> None :
109252 return await self .query (
110- f 'rename_module(name, new_name)' ,
253+ 'rename_module(name, new_name)' ,
111254 name = name ,
112255 new_name = new_name ,
113256 scope = '@t' )
114257
115258 async def rename_user (self , name : str , new_name : str ) -> None :
116259 return await self .query (
117- f 'rename_user(name, new_name)' ,
260+ 'rename_user(name, new_name)' ,
118261 name = name ,
119262 new_name = new_name ,
120263 scope = '@t' )
@@ -123,7 +266,7 @@ async def rename_user(self, name: str, new_name: str) -> None:
123266
124267 async def revoke (self , target : U [int , str ], user : str , mask : int ):
125268 return await self .query (
126- f 'revoke(target, user, mask)' ,
269+ 'revoke(target, user, mask)' ,
127270 target = target ,
128271 user = user ,
129272 mask = mask ,
@@ -134,25 +277,40 @@ async def revoke(self, target: U[int, str], user: str, mask: int):
134277
135278 async def set_password (self , user : str , new_password : str = None ) -> None :
136279 return await self .query (
137- f 'set_password(user, new_password)' ,
280+ 'set_password(user, new_password)' ,
138281 user = user ,
139282 new_password = new_password ,
140283 scope = '@t' )
141284
142285 async def set_time_zone (self , collection : U [int , str ], zone : str ):
286+ """By default each collection will be created with time zone UTC.
287+
288+ This function can be used to change the time zone for a collection. If
289+ changed, the functions datetime(..) and timeval(..) will use the
290+ collections time zone unless specified otherwise. See time_zones_info()
291+ for a list of all available timezones.
292+
293+ Use collection_info(..) to view the current time zone for a collection.
294+
295+ This function generates a change.
296+ """
143297 return await self .query (
144- f 'set_time_zone(collection, zone)' ,
298+ 'set_time_zone(collection, zone)' ,
145299 collection = collection ,
146300 zone = zone ,
147301 scope = '@t' )
148302
149303 async def time_zones_info (self ) -> list :
304+ """Returns all available time zones in ThingsDB.
305+
306+ This function does not generate a change.
307+ """
150308 return await self .query ('time_zones_info()' , scope = '@t' )
151309
152310 async def user_info (self , user : Optional [str ] = None ) -> dict :
153311 if user is None :
154312 return await self .query ('user_info()' , scope = '@t' )
155- return await self .query (f 'user_info(user)' , user = user , scope = '@t' )
313+ return await self .query ('user_info(user)' , user = user , scope = '@t' )
156314
157315 async def users_info (self ) -> list :
158316 return await self .query ('users_info()' , scope = '@t' )
@@ -186,22 +344,47 @@ async def has_backup(self, backup_id: int, scope='@n'):
186344
187345 # TODO: new_backup
188346
189- async def node_info (self , scope = '@n' ):
347+ async def node_info (self , scope = '@n' ) -> dict :
190348 return await self .query ('node_info()' , scope = scope )
191349
192350 async def nodes_info (self , scope = '@n' ) -> list :
193351 return await self .query ('nodes_info()' , scope = scope )
194352
195353 async def reset_counters (self , scope = '@n' ) -> None :
354+ """Resets the counters for the ThingsDB node you are connected too.
355+
356+ Other nodes are not affected. This will set the started_at counter
357+ value to the current UNIX time-stamp in seconds and all other counters
358+ to 0 (zero).
359+
360+ This function does not generate a change.
361+ """
196362 return await self .query ('reset_counters()' , scope = scope )
197363
198- async def restart_module (self , name : str ):
199- return await self .query (f'restart_module(name)' , name = name , scope = '@t' )
364+ async def restart_module (self , name : str ) -> None :
365+ """Restarts a given module on the select node scope.
366+
367+ If you want to restart the module on all nodes, you can use the
368+ deploy_module(name, None) function with None as second argument.
369+
370+ This function does not generate a change.
371+ """
372+ return await self .query ('restart_module(name)' , name = name , scope = '@t' )
200373
201374 async def set_log_level (self , log_level : str , scope = '@n' ) -> None :
202375 assert log_level in ('DEBUG' , 'INFO' , 'WARNING' , 'ERROR' , 'CRITICAL' )
203376 return await self .query (
204- f 'set_log_level(log_level)' , log_level = log_level , scope = scope )
377+ 'set_log_level(log_level)' , log_level = log_level , scope = scope )
205378
206379 async def shutdown (self , scope = '@n' ) -> None :
380+ """Shutdown the node in the selected scope.
381+
382+ This is a clean shutdown, allowing all other nodes (and clients) to
383+ disconnect. Be CAREFUL using this function!!!
384+
385+ At least CHANGE privileges on the @node scope are required to shutdown
386+ a node.
387+
388+ This function does not generate a change.
389+ """
207390 return await self .query ('shutdown()' , scope = scope )
0 commit comments