@@ -101,19 +101,19 @@ def get_names(self, account_ids: list[str]) -> list[str]:
101
101
def user_search (self , query : str ) -> UserSearchResult :
102
102
"""
103
103
Search for existing users by name or email address.
104
-
104
+
105
105
Args:
106
106
query (str): A query, e.g., partial name, email address, etc.
107
-
107
+
108
108
Returns:
109
109
list[UserSearchResult]: array of dicts with account_id, name,
110
110
first_name, last_name, last_active (in ms since epoch),
111
111
created (in ms since epoch) and email_address_verified.
112
-
112
+
113
113
Examples:
114
-
114
+
115
115
Search for myself:
116
-
116
+
117
117
>>> import cocalc_api; hub = cocalc_api.Hub(api_key="sk...")
118
118
>>> hub.system.user_search('w')
119
119
[{'account_id': 'd0bdabfd-850e-4c8d-8510-f6f1ecb9a5eb',
@@ -123,10 +123,10 @@ def user_search(self, query: str) -> UserSearchResult:
123
123
'last_active': 1756503700052,
124
124
'created': 1756056224470,
125
125
'email_address_verified': None}]
126
-
126
+
127
127
You can search by email address to ONLY get the user
128
128
that has that email address:
129
-
129
+
130
130
>>> hub.system.user_search('[email protected] ')
131
131
[{'account_id': 'd0bdabfd-850e-4c8d-8510-f6f1ecb9a5eb',
132
132
'first_name': 'W',
@@ -145,6 +145,39 @@ class Projects:
145
145
def __init__ (self , parent : "Hub" ):
146
146
self ._parent = parent
147
147
148
+ def get (self ,
149
+ fields : Optional [list [str ]] = None ,
150
+ all : Optional [bool ] = False ,
151
+ project_id : Optional [str ] = None ):
152
+ """
153
+ Get data about projects that you are a collaborator on. Only gets
154
+ recent projects by default; set all=True to get all projects.
155
+
156
+ Args:
157
+ fields (Optional[list[str]]): the fields about the project to get.
158
+ default: ['project_id', 'title', 'last_edited', 'state'], but see
159
+ https://github.com/sagemathinc/cocalc/blob/master/src/packages/util/db-schema/projects.ts
160
+ all (Optional[bool]): if True, return ALL your projects,
161
+ not just the recent ones. False by default.
162
+ project_id (Optional[string]): if given as a project_id, gets just the
163
+ one project (as a length of length 1).
164
+
165
+ Returns:
166
+ list[dict[str,Any]]: list of projects
167
+ """
168
+ if fields is None :
169
+ fields = ['project_id' , 'title' , 'last_edited' , 'state' ]
170
+ v : list [dict [str , Any ]] = [{}]
171
+ for field in fields :
172
+ v [0 ][field ] = None
173
+ if project_id :
174
+ v [0 ]['project_id' ] = project_id
175
+ query : dict [str , list [dict [str , None ]]] = {}
176
+ table = 'projects_all' if all else 'projects'
177
+ query [table ] = v
178
+ result = self ._parent .db .query (query )
179
+ return result [table ]
180
+
148
181
@api_method ("projects.copyPathBetweenProjects" )
149
182
def copy_path_between_projects (
150
183
self ,
@@ -224,6 +257,26 @@ def remove_collaborator(self, project_id: str, account_id: str):
224
257
"""
225
258
...
226
259
260
+ @api_method ("projects.start" )
261
+ def start (self , project_id : str ):
262
+ """
263
+ Start a project.
264
+
265
+ Args:
266
+ project_id (str): project_id of the project to start
267
+ """
268
+ ...
269
+
270
+ @api_method ("projects.stop" )
271
+ def stop (self , project_id : str ):
272
+ """
273
+ Stop a project.
274
+
275
+ Args:
276
+ project_id (str): project_id of the project to stop
277
+ """
278
+ ...
279
+
227
280
228
281
class Jupyter :
229
282
@@ -265,19 +318,19 @@ def execute(
265
318
266
319
Returns:
267
320
Any: JSON response containing execution results.
268
-
321
+
269
322
Examples:
270
323
Execute a simple sum using a Jupyter kernel:
271
-
324
+
272
325
>>> import cocalc_api; hub = cocalc_api.Hub(api_key="sk-...")
273
- >>> hub.jupyter.execute(history=['a=100;print(a)'],
326
+ >>> hub.jupyter.execute(history=['a=100;print(a)'],
274
327
input='sum(range(a+1))',
275
328
kernel='python3')
276
329
{'output': [{'data': {'text/plain': '5050'}}], ...}
277
-
330
+
278
331
Factor a number using the sagemath kernel in a specific project:
279
-
280
- >>> hub.jupyter.execute(history=['a=2025'], input='factor(a)', kernel='sagemath',
332
+
333
+ >>> hub.jupyter.execute(history=['a=2025'], input='factor(a)', kernel='sagemath',
281
334
... project_id='6e75dbf1-0342-4249-9dce-6b21648656e9')
282
335
{'output': [{'data': {'text/plain': '3^4 * 5^2'}}], ...}
283
336
"""
@@ -314,21 +367,21 @@ def query(self, query: dict[str, Any]) -> dict[str, Any]:
314
367
"""
315
368
Do a user query. The input is of one of the following forms, where the tables are defined at
316
369
https://github.com/sagemathinc/cocalc/tree/master/src/packages/util/db-schema
317
-
370
+
318
371
- `{"table-name":{"key":"value", ...}}` with no None values sets one record in the database
319
- - `{"table-name":[{"key":"value", "key2":None...}]}` gets an array of all matching records
372
+ - `{"table-name":[{"key":"value", "key2":None...}]}` gets an array of all matching records
320
373
in the database, filling in None's with the actual values.
321
374
- `{"table-name:{"key":"value", "key2":None}}` gets one record, filling in None's with actual values.
322
-
375
+
323
376
This is used for most configuration, e.g., user names, project descriptions, etc.
324
377
325
378
Args:
326
379
query (dict[str, Any]): Object that defines the query, as explained above.
327
-
380
+
328
381
Examples:
329
-
382
+
330
383
Get and also change your first name:
331
-
384
+
332
385
>>> import cocalc_api; hub = cocalc_api.Hub(api_key="sk...")
333
386
>>> hub.db.query({"accounts":{"first_name":None}})
334
387
{'accounts': {'first_name': 'William'}}
@@ -346,8 +399,11 @@ def __init__(self, parent: "Hub"):
346
399
self ._parent = parent
347
400
348
401
@api_method ("messages.send" )
349
- def send (self , subject : str , body : str , to_ids : list [str ],
350
- reply_id : Optional [int ]) -> int :
402
+ def send (self ,
403
+ subject : str ,
404
+ body : str ,
405
+ to_ids : list [str ],
406
+ reply_id : Optional [int ] = None ) -> int :
351
407
"""
352
408
Send a message to one or more users.
353
409
@@ -365,9 +421,10 @@ def send(self, subject: str, body: str, to_ids: list[str],
365
421
@api_method ("messages.get" )
366
422
def get (
367
423
self ,
368
- limit : Optional [int ],
369
- offset : Optional [int ],
370
- type : Optional [Literal ["received" , "sent" , "new" , "starred" , "liked" ]],
424
+ limit : Optional [int ] = None ,
425
+ offset : Optional [int ] = None ,
426
+ type : Optional [Literal ["received" , "sent" , "new" , "starred" ,
427
+ "liked" ]] = None ,
371
428
) -> list [MessageType ]:
372
429
"""
373
430
Get your messages.
@@ -418,23 +475,27 @@ def get(self, name: str):
418
475
419
476
Args:
420
477
name (str) - name of the organization
421
-
478
+
422
479
Returns:
423
480
Any: ...
424
481
"""
425
482
raise NotImplementedError
426
483
427
484
@api_method ("org.set" )
428
- def set (self , name : str , title : Optional [str ], description : Optional [str ],
429
- email_address : Optional [str ], link : Optional [str ]):
485
+ def set (self ,
486
+ name : str ,
487
+ title : Optional [str ] = None ,
488
+ description : Optional [str ] = None ,
489
+ email_address : Optional [str ] = None ,
490
+ link : Optional [str ] = None ):
430
491
"""
431
492
Set properties of an organization.
432
493
433
494
Args:
434
495
name (str): name of the organization
435
496
title (Optional[str]): the title of the organization
436
497
description (Optional[str]): description of the organization
437
- email_address (Optional[str]): email address to reach the organization
498
+ email_address (Optional[str]): email address to reach the organization
438
499
(nothing to do with a cocalc account)
439
500
link (Optional[str]): a website of the organization
440
501
"""
@@ -467,8 +528,12 @@ def add_user(self, name: str, user: str):
467
528
raise NotImplementedError
468
529
469
530
@api_method ("org.createUser" )
470
- def create_user (self , name : str , email : str , firstName : Optional [str ],
471
- lastName : Optional [str ], password : Optional [str ]) -> str :
531
+ def create_user (self ,
532
+ name : str ,
533
+ email : str ,
534
+ firstName : Optional [str ] = None ,
535
+ lastName : Optional [str ] = None ,
536
+ password : Optional [str ] = None ) -> str :
472
537
"""
473
538
Create a new cocalc account that is a member of the
474
539
named organization.
@@ -478,10 +543,10 @@ def create_user(self, name: str, email: str, firstName: Optional[str],
478
543
email (str): email address
479
544
firstName (Optional[str]): optional first name of the user
480
545
lastName (Optional[str]): optional last name of the user
481
- password (Optional[str]): optional password (will be randomized if
546
+ password (Optional[str]): optional password (will be randomized if
482
547
not given; you can instead use create_token to grant temporary
483
548
account access).
484
-
549
+
485
550
Returns:
486
551
str: account_id of the new user
487
552
"""
@@ -496,10 +561,10 @@ def create_token(self, user: str) -> TokenType:
496
561
497
562
Args:
498
563
user (str): email address or account_id
499
-
564
+
500
565
Returns:
501
566
TokenType: token that grants temporary access
502
-
567
+
503
568
Notes:
504
569
The returned `TokenType` has the following fields:
505
570
@@ -528,10 +593,10 @@ def get_users(self, name: str) -> OrganizationUser:
528
593
529
594
Args:
530
595
name (str): name of the organization
531
-
596
+
532
597
Returns:
533
598
list[OrganizationUser]
534
-
599
+
535
600
Notes:
536
601
The returned `OrganizationUser` has the following fields:
537
602
@@ -547,7 +612,7 @@ def message(self, name: str, subject: str, body: str):
547
612
"""
548
613
Send a message from you to every account that is a member of
549
614
the named organization.
550
-
615
+
551
616
Args:
552
617
name (str): name of the organization
553
618
subject (str): plain text subject of the message
0 commit comments