def replace_workflow_module(project_id, branch_id, module_id): """Replace a module in the current project workflow branch and execute the resulting workflow. Request ------- { "packageId": "string", "commandId": "string", "arguments": [] } """ # Abort with BAD REQUEST if request body is not in Json format or does not # contain the expected elements. cmd = srv.validate_json_request( request, required=['packageId', 'commandId', 'arguments']) # Extend and execute workflow. This will throw a ValueError if the command # cannot be parsed. try: # Result is None if project, branch or module are not found. modules = api.workflows.replace_workflow_module( project_id=project_id, branch_id=branch_id, module_id=module_id, package_id=cmd['packageId'], command_id=cmd['commandId'], arguments=cmd['arguments']) if not modules is None: return jsonify(modules) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown project \'' + project_id + '\' branch \'' + branch_id + '\' or module \'' + module_id + '\'')
def create_project(): """Create a new project. The request is expected to contain a Json object with an optional list of properties as (key,value)-pairs. Request ------- { "properties": [ { "key": "string", "value": "string" } ] } """ # Abort with BAD REQUEST if request body is not in Json format or if any # of the provided project properties is not a dict with key and value. obj = srv.validate_json_request(request, required=['properties']) if not isinstance(obj['properties'], list): raise srv.InvalidRequest('expected a list of properties') properties = deserialize.PROPERTIES(obj['properties']) # Create project and return the project descriptor try: return jsonify(api.projects.create_project(properties)), 201 except ValueError as ex: raise srv.InvalidRequest(str(ex))
def update_branch(project_id, branch_id): """Update properties for a given project workflow branch. Expects a set of key,value-pairs in the request body. Properties with given key but missing value will be deleted. Request ------- { "properties": [ { "key": "string", "value": "string" } ] } """ # Abort with BAD REQUEST if request body is not in Json format or does not # contain a properties key. obj = srv.validate_json_request(request, required=['properties']) # Update properties for the given branch and return branch descriptor. properties = deserialize.PROPERTIES(obj['properties'], allow_null=True) try: # Result is None if project or branch are not found. branch = api.branches.update_branch(project_id=project_id, branch_id=branch_id, properties=properties) if not branch is None: return jsonify(branch) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown project \'' + project_id + '\' or branch \'' + branch_id + '\'')
def append_branch_head(project_id, branch_id): """Append a module to the workflow that is at the HEAD of the given branch. Request ------- { "packageId": "string", "commandId": "string", "arguments": [] } """ # Abort with BAD REQUEST if request body is not in Json format or does not # contain the expected elements. cmd = srv.validate_json_request( request, required=['packageId', 'commandId', 'arguments']) # Extend and execute workflow. This will throw a ValueError if the command # cannot be parsed. try: # Result is None if project or branch are not found module = api.workflows.append_workflow_module( project_id=project_id, branch_id=branch_id, package_id=cmd['packageId'], command_id=cmd['commandId'], arguments=cmd['arguments'], ) if not module is None: return jsonify(module) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown project \'' + project_id + '\' or branch \'' + branch_id + '\'')
def update_project(project_id): """Update the set of user-defined properties. Expects a Json object with a list of property update statements. These statements are (key,value) pairs, where the value is optional (i.e., missing value for delete statements). Request ------- { "properties": [ { "key": "string", "value": "scalar or list of scalars" } ] } """ # Abort with BAD REQUEST if request body is not in Json format or if any # of the project property update statements are invalid. obj = srv.validate_json_request(request, required=['properties']) if not isinstance(obj['properties'], list): raise srv.InvalidRequest('expected a list of properties') # Update project and return the project descriptor. If no project with # the given identifier exists the update result will be None properties = deserialize.PROPERTIES(obj['properties'], allow_null=True) try: pj = api.projects.update_project(project_id, properties) if not pj is None: return jsonify(pj) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown project \'' + project_id + '\'')
def execute_task(): """Execute a task against a given project context. Request ------- { "id": "string", "command": { "packageId": "string", "commandId": "string", "arguments": [ null ] }, "context": [ { "id": "string", "name": "string" } ], "resources": {} } """ # Abort with BAD REQUEST if request body is not in Json format or does not # contain the expected elements. obj = srv.validate_json_request( request, required=[labels.ID, labels.COMMAND, labels.CONTEXT], optional=[labels.RESOURCES]) # Validate module command cmd = obj[labels.COMMAND] for key in [ labels.COMMAND_PACKAGE, labels.COMMAND_ID, labels.COMMAND_ARGS ]: if not key in cmd: raise srv.InvalidRequest('missing element \'' + key + '\' in command specification') # Get database state context = dict() for ds in obj[labels.CONTEXT]: for key in [labels.ID, labels.NAME]: if not key in ds: raise srv.InvalidRequest('missing element \'' + key + '\' in dataset identifier') context[ds[labels.NAME]] = ds[labels.ID] try: # Execute module. Result should not be None. result = api.tasks.execute_task( project_id=config.project_id, task_id=obj[labels.ID], command=ModuleCommand(package_id=cmd[labels.COMMAND_PACKAGE], command_id=cmd[labels.COMMAND_ID], arguments=cmd[labels.COMMAND_ARGS], packages=api.engine.packages), context=context, resources=obj[labels.RESOURCES] if labels.RESOURCES in obj else None) return jsonify(result) except ValueError as ex: raise srv.InvalidRequest(str(ex))
def create_dataset(): """Create a new dataset in the datastore for the project. The dataset schema and rows are given in the request body. Dataset annotations are optional. The expected request body format is: { "columns": [ { "id": 0, "name": "string", "type": "string" } ], "rows": [ { "id": 0, "values": [ "string" ] } ], "annotations": [ { "columnId": 0, "rowId": 0, "key": "string", "value": "string" } ] } """ # Validate the request obj = srv.validate_json_request( request, required=[labels.COLUMNS, labels.ROWS], optional=[labels.ANNOTATIONS] ) columns = deserialize.DATASET_COLUMNS(obj[labels.COLUMNS]) rows = [deserialize.DATASET_ROW(row) for row in obj[labels.ROWS]] annotations = None if labels.ANNOTATIONS in obj: annotations = DatasetMetadata() for anno in obj[labels.ANNOTATIONS]: a = deserialize.ANNOTATION(anno) if a.column_id is None: annotations.rows.append(a) elif a.row_id is None: annotations.columns.append(a) else: annotations.cells.append(a) try: dataset = api.datasets.create_dataset( project_id=config.project_id, columns=columns, rows=rows, annotations=annotations ) return jsonify(dataset) except ValueError as ex: raise srv.InvalidRequest(str(ex))
def create_branch(project_id): """Create a new branch for a project. Expects a description of the parent workflow in the request body together with an optional list of branch properties (e.g., containing a branch name). Request ------- { "source": { "branchId": "string", "workflowId": "string" "moduleId": "string" }, "properties": [ { "key": "string", "value": "string" } ] } """ # Abort with BAD REQUEST if request body is not in Json format or does not # contain the expected elements. obj = srv.validate_json_request(request, required=['properties'], optional=['source']) # Get the branch point. If the source is given the dictionary should at # most contain the three identifier branch_id = None workflow_id = None module_id = None if 'source' in obj: source = obj['source'] for key in source: if key == 'branchId': branch_id = source[key] elif key == 'workflowId': workflow_id = source[key] elif key == 'moduleId': module_id = source[key] else: raise srv.InvalidRequest('invalid element \'' + key + '\' for branch point') # Get the properties for the new branch properties = deserialize.PROPERTIES(obj['properties']) # Create a new workflow. The result is the descriptor for the new workflow # or None if the specified project does not exist. Will raise a ValueError # if the specified workflow version or module do not exist try: branch = api.branches.create_branch(project_id=project_id, branch_id=branch_id, workflow_id=workflow_id, module_id=module_id, properties=properties) if not branch is None: return jsonify(branch) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown project \'' + project_id + '\'')
def create_dataset(project_id): """Create a new dataset in the datastore for the given project. The dataset schema and rows are given in the request body. Dataset annotations are optional. The expected request body format is: { "columns": [ { "id": 0, "name": "string", "type": "string" } ], "rows": [ { "id": 0, "values": [ "string" ] } ], "annotations": [ { "columnId": 0, "rowId": 0, "key": "string", "value": "string" } ] } """ # Validate the request obj = srv.validate_json_request(request, required=[labels.COLUMNS, labels.ROWS], optional=[labels.PROPERTIES]) columns = deserialize.DATASET_COLUMNS(obj[labels.COLUMNS]) rows = [deserialize.DATASET_ROW(row) for row in obj[labels.ROWS]] properties = obj.get(labels.PROPERTIES, dict()) try: dataset = api.datasets.create_dataset(project_id=project_id, columns=columns, rows=rows, properties=properties) if not dataset is None: return jsonify(dataset) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown project \'' + project_id + '\'')
def update_dataset_annotation(dataset_id): """Update an annotation that is associated with a component of the given dataset. Request ------- { "columnId": 0, "rowId": 0, "key": "string", "oldValue": "string", or "int", or "float" "newValue": "string", or "int", or "float" } """ # Validate the request obj = srv.validate_json_request( request, required=['key'], optional=['columnId', 'rowId', 'key', 'oldValue', 'newValue'] ) # Create update statement and execute. The result is None if no dataset with # given identifier exists. key = obj[labels.KEY] if labels.KEY in obj else None column_id = obj[labels.COLUMN_ID] if labels.COLUMN_ID in obj else None row_id = obj[labels.ROW_ID] if labels.ROW_ID in obj else None old_value = obj[labels.OLD_VALUE] if labels.OLD_VALUE in obj else None new_value = obj[labels.NEW_VALUE] if labels.NEW_VALUE in obj else None try: annotations = api.datasets.update_annotation( project_id=config.project_id, dataset_id=dataset_id, key=key, column_id=column_id, row_id=row_id, old_value=old_value, new_value=new_value ) if not annotations is None: return jsonify(annotations) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown dataset \'' + dataset_id + '\'')
def update_task_state(task_id): """Update the state of a running task.""" # Abort with BAD REQUEST if request body is not in Json format or does not # contain the expected elements. obj = srv.validate_json_request(request, required=[labels.STATE], optional=[ labels.STARTED_AT, labels.FINISHED_AT, labels.OUTPUTS, labels.PROVENANCE ]) # Update task state. The contents of the request body depend on the value of # the new task state. The request body is evaluated by the API. The API will # raise a ValueError if the request body is invalid. The result is None if # the project or task are unknown. try: # Result is None if task is not found. result = api.tasks.update_task_state(task_id=task_id, state=obj[labels.STATE], body=obj) if not result is None: return jsonify(result) except ValueError as ex: raise srv.InvalidRequest(str(ex)) raise srv.ResourceNotFound('unknown task \'' + task_id + '\'')