crandas.script#

Functionalities to record scripts.

The user can package a crandas script by first executing crandas.script.record(). Then, every query that is executed will be recorded in a script. This does not modify the output: the user still needs to be able to execute the queries, e.g. by being connected to a test environment, or by setting session.dry_run = True.

After executing all their queries, the user can run crandas.script.save(filename), which will package the script into a json-formatted file. The session.analyst_key is included into the file. This file can be sent to the approvers to be signed off.

After receiving the signed query file from the approvers, it can be loaded using crandas.script.load(filename). Now the user, possibly being connected to a different VDL server that requires authorization, can execute the same script as they executed when recording the script. Note that exactly the same queries have to be executed as before, in the same order.

class crandas.script.Script(mode, name=None, auth_tag=None, session=None, map_dummy_handles=False, stepless=False)#

Bases: object

A script represents a sequence of VDL commands, that can be automatically recorded, then approved, and later executed on a different VDL instance.

A script consists of a number of “steps”, each referred to by its script_step.

The function of a script is to internally link the inputs/outputs of operations, so that for example the output of step 0 is the input to step 1.

An active (not-closed) script is either recording or executing. When recording, each crandas command that is executed and sent to the server is locally appended to a list, with a script_step that is one higher than the last script_step. When all of the desired commands have been run, the script can be saved to a JSON-formatted file using Script.save(). This script can subsequently be authorized by approvers.

An authorized script can be loaded using Script.load(). The resulting script is put in executing mode. For each crandas command that is executed, it is expected to exactly match the next command in the script. The matching authorization is then used, and sent along to the server.

Besides the above approach of having an increasing script_step for each executed crandas command, scripts may additionally contain stepless queries, that do not have any associated script_step. These commands may be recorded once and executed arbitrarily many times, and are useful for commands that need to be executed a variable number of times. To put a recording or executing script in stepless mode, use:

>>> script.stepless = True

To get back to regular “stepped” mode, use:

>>> script.stepless = False

When recording, any crandas command that is executed is then added to the script without a script step. When executing, any crandas command is then matched to the stepless queries in the script.

Limitations: since the step numbers are used to link the outputs and inputs of different steps, the outputs of stepless queries cannot be used as the inputs of other (stepless or stepped) queries. Stepless queries are especially useful together with placeholders, e.g. crandas.placeholders.Any.

get_inputs()#

Get the input tables used in the current script.

This returns a dictionary of Reference -> List[str], where the reference maps to a list of descriptions (currently, source code lines) of the queries.

print_inputs()#

Print the input tables used in the current script.

resolve_references(obj)#

Recursively modify obj (atom, list, or dict) in-place, replacing each value of type Reference by the corresponding step placeholder.

property run_tag#

For each script execution, we generate a random 32-byte run_tag, to distinguish different executions of the same script to the server.

save(target, analyst_key=True)#

Save the recorded script to a file.

Parameters:
  • target (str | Path | file-like object) – The path to save the script to, or a file-like object (such as the result of a call to open).

  • analyst_key (VerifyKey | SigningKey | str | Path | False | True (default)) –

    A script will generally include the analyst_key of the user that created the script. The user may specify a signing or verification key to include, either as a key object, or a path to load the key from disk.

    Alternatively, if True (the default), the current crandas.base.session analyst_key will be used. If False, no analyst key will be included in the script.

enum crandas.script.ScriptMode(value)#

Bases: Enum

An enumeration.

Valid values are as follows:

RECORDING = <ScriptMode.RECORDING: 0>#
EXECUTING = <ScriptMode.EXECUTING: 1>#
CLOSED = <ScriptMode.CLOSED: 2>#
crandas.script.current_script()#

Returns the currently recording/loaded script.

crandas.script.dummy_name_for(handle)#

Returns the name used in testing environments for the table with handle handle.

crandas.script.load(path)#

Load a script from a file for execution.

crandas.script.record(name=None, map_dummy_handles=True)#

Start recording a new script.

Use this command before running a sequence of crandas commands. Afterwards, use script.save(filename) to save the script to a file. The script can subsequently be authorized by approvers. When the approved script is received, use script.load() to load it, and then you may execute the exact same sequence of commands, in the same order, as you did when recording the script.

Parameters:
  • name (str (optional)) – A name to attach to the script

  • map_dummy_handles (bool) – Unless the user sets this to False, this causes all hexadecimal table handles that are used during recording to map to the table name dummy_name(handle). To upload tables with this name, use the dummy_for argument to a VDL query command, e.g. crandas.upload_pandas_dataframe(df, dummy_for="<handle>").

crandas.script.save(target, analyst_key=True)#

Save the recorded script to a file.

See Script.save().

crandas.script.stepless()#

Context manager to facilitate stepless recording/execution. See Script for details on stepless queries.

Example usage:

# Outside the script
handles = [crandas.DataFrame({"a": [i]}).handle for i in range(5)]

# Inside the script
tables = []
with stepless():
    for handle in handles:
        table = cd.get_table(handle, map_dummy_handles=False)
        tables.append(table)

all_rows = crandas.concat(placeholders.Any(tables))