Python: the shell module
Every Python notebook has the Shell scope in scope as the module shell. The notebook runs from shell import * before the first cell, so the names below are available as written. This page lists them as of this release, and describes how a name, an argument and a result map between C# and Python.
For guides with examples, see Python notebooks.
Not the `curiosity` Python SDK
The Python SDK is a pip package that connects to a workspace from outside, with a token. The shell module exists only inside a Python notebook and has no connection to configure: it is the scope of the administrator who opened the notebook.
The module is generated when the first Python notebook opens, by reflection over the scope class, and kept for later notebooks. A member added to the scope appears in the module without a change here; the list below is what exists today. Its docstring lists the same members: print(shell.__doc__).
Names
Values
Evaluated once, when the notebook starts.
| Name | Type | Description |
|---|---|---|
graph |
ScopedGraph |
The graph, with the full access of a Shell script. In a sandboxed notebook it is a ReadOnlyGraph. |
current_user |
UID128 |
The UID of the administrator who opened the notebook. Pass it to calls that take a user, q(current_user), to see what that user sees. |
chat_ai |
ChatAI |
Helper for chat AI operations. |
agent_ai |
AgentAI |
Helper for running agents. |
structured_ai |
StructuredAI |
Helper for structured AI calls. |
tracker |
QueryTracker |
The performance tracker shared by every query created in the scope. |
progress_reporter |
IUserProgressReporter |
Reports progress to the UI. A notebook has none attached, so it does nothing visible. |
Functions
| Signature | Returns | Description |
|---|---|---|
q() |
IQuery |
A new query. The members of the query are the graph query language in snake_case. |
q(user_uid) |
IQuery |
A new query that sees what that user sees. |
query() |
IQuery |
Same as q(). |
query(user_uid) |
IQuery |
Same as q(user_uid). |
is_cancellation_requested() |
bool |
Whether the running cell was asked to stop. A function, not a value, because the answer changes while a cell runs. |
throw_if_cancellation_requested() |
None |
Ends the cell as stopped if it was asked to stop. |
dataframe(query, *fields) |
pandas DataFrame |
The query's nodes as a DataFrame. Added for notebooks. See below. |
query_rows(query, *fields) |
list[dict] |
The same rows as dictionaries. Added for notebooks. |
The notebook also imports the flint module.
Not available from Python
A name is left out of the module, and listed at the end of its docstring, when Python cannot call it:
| C# member | Python name | Why |
|---|---|---|
CancellationToken |
cancellation_token |
A .NET struct, not a Studio type. Use is_cancellation_requested(). |
RunEndpointAsync<T> |
run_endpoint_async |
Takes a type argument. |
RunToolAsync<T> |
run_tool_async |
Takes a type argument. |
RunTaskAsync(…) |
run_task_async |
Takes a delegate. |
GetSecretAsync(SecretUID) |
get_secret_async |
Takes a SecretUID, which Python cannot build. |
CreateHttpClient() |
create_http_client |
Returns a .NET HttpClient, which Python cannot use. |
The two secrets and HTTP names are in the Shell scope of a C# notebook; in a sandboxed scope they do not exist.
Naming
Python names are snake_case. The module and every object it returns use the same rule, so completion, dir() and error messages show Python names, and the C# spelling is still accepted when you type it.
| C# | Python |
|---|---|
Q |
q |
StartAt |
start_at |
CurrentUser |
current_user |
AsUIDEnumerable |
as_uid_enumerable |
RunEndpointAsync |
run_endpoint_async |
Parameter userUID |
Keyword user_uid |
A word boundary is a lower-case letter or digit followed by an upper-case letter (StartAt, Base64Encode), and the last capital of an acronym before a word (UIDEnumerable). Keyword arguments match without regard to case or underscores, so q(user_uid=x) and q(userUID=x) are the same call. Names that end in _async keep the suffix and still wait for the result.
Objects
A value of a Studio type, such as the result of q(), is a host object. Reading an attribute reads a property; calling an attribute calls a method.
- Reach. Only members declared by a Studio type are reachable. The members of
objectand the .NET framework (GetType(),GetHashCode()) are not, andInternalsis not reachable on any type. Reading a name that is not reachable raisesAttributeError. - Overloads. When a method has several overloads, each is tried in order, fewest parameters first, and the first one every argument converts to is called. When none fits, the call raises
TypeErrorlisting each overload and why it did not fit. - Optional parameters take their default. Keywords name parameters.
- Not callable from Python: methods that take a delegate or a type argument, and indexers.
- Iteration. An object that is a collection can be used in a
forloop, inlist(...)and withlen(...). - Text.
print(obj)shows the object's text form,<Query>when it has none.
Arguments
| Python | Converts to |
|---|---|
None |
null |
bool |
bool |
int |
Any integer type, or float, double, decimal; an int that does not fit moves on to the next overload |
float |
double, float, decimal |
str |
string; an enum member, by name; a Guid; any type that reads from text, such as a UID |
bytes |
byte[] |
list, tuple |
An array, a List<T> or an IEnumerable<T>, converting each item |
dict |
A Dictionary<K, V> or an IDictionary<K, V> |
| A host object | The object itself, where the parameter accepts its type |
Anything for object |
The natural .NET value: long, double, string, bool, List<object> |
Results
| From the scope | In Python |
|---|---|
bool, numbers, string, char |
bool, int or float, str |
Task, Task<T>, ValueTask<T> |
The result, after waiting for it |
| An enum | str, the member name |
A UID, a Guid, a date or time, a Type |
str, its text form |
byte[] |
bytes |
| A dictionary | dict |
| A list or array of any other type | list, up to 1,000,000 items; more raises MemoryError |
| An object of a Studio type | A host object |
| Any other type | str, its text form |
Waiting for results
A method that returns a task is waited for before Python sees its result, by blocking the thread that runs the cell. That is safe because each cell runs on a thread of its own. The wait honors a stop: the cell's token is the scope's CancellationToken.
Errors
| Raised in the scope | Python |
|---|---|
ArgumentException, FormatException |
ValueError |
KeyNotFoundException |
KeyError |
UnauthorizedAccessException |
PermissionError |
NotSupportedException, NotImplementedException |
NotImplementedError |
OperationCanceledException |
Not catchable: the cell ends as stopped (KeyboardInterrupt) |
| Any other exception | RuntimeError: <Type>: <message> |
dataframe and query_rows
dataframe(query, *fields)
query_rows(query, *fields)
query is a query, or a list of nodes such as list(q().start_at("Ticket").as_enumerable()). With no fields, the columns are UID, Type, then every field in the order it is first seen. With fields, only those columns, in that order; "Timestamp" can be named. A node without a field has None there.
- Fields hidden by the schema are not included.
- Node types that never leave the server, such as secrets and tokens, are dropped from a query, as
emitdrops them. - Values are
int,float,str,boolandlist. A time or a UID is its text. - More than 100,000 nodes raises
RuntimeErrorwithA table takes at most 100000 rows. Narrow the query first.Nothing is cut silently.
dataframe imports pandas when it is called. query_rows returns the same rows without it.
df = dataframe(q().start_at("Ticket"), "Status", "Priority")
df.groupby("Status").size()