Adding a simple endpoint that describes what scripts are currently available, along with a brief description.
This commit is contained in:
parent
7194d7d374
commit
94f828dfd6
25
crc/api.yml
25
crc/api.yml
|
@ -680,7 +680,21 @@ paths:
|
|||
type: string
|
||||
format: binary
|
||||
example: '<?xml version="1.0" encoding="UTF-8"?><bpmn:definitions></bpmn:definitions>'
|
||||
|
||||
/list_scripts:
|
||||
get:
|
||||
operationId: crc.api.tools.list_scripts
|
||||
summary: Returns an list of scripts, along with their descriptions
|
||||
tags:
|
||||
- Configurator Tools
|
||||
responses:
|
||||
'201':
|
||||
description: The list of scripts
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Script"
|
||||
components:
|
||||
schemas:
|
||||
User:
|
||||
|
@ -969,3 +983,12 @@ components:
|
|||
message:
|
||||
type: string
|
||||
example: "You do not have permission to view the requested study."
|
||||
Script:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
format: string
|
||||
example: "random_fact"
|
||||
description:
|
||||
type: string
|
||||
example: "Returns a random fact about a topic. Provide an argument of either 'cat', 'norris', or 'buzzword'"
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import io
|
||||
import json
|
||||
import uuid
|
||||
from io import BytesIO
|
||||
|
||||
import connexion
|
||||
import jinja2
|
||||
from docxtpl import DocxTemplate
|
||||
from flask import send_file
|
||||
from jinja2 import Template, UndefinedError
|
||||
|
||||
from crc.api.common import ApiError, ApiErrorSchema
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.complete_template import CompleteTemplate
|
||||
from crc.services.file_service import FileService
|
||||
|
||||
from crc.scripts.script import Script
|
||||
import crc.scripts
|
||||
|
||||
def render_markdown(data, template):
|
||||
"""
|
||||
|
@ -48,3 +44,17 @@ def render_docx(data):
|
|||
raise ApiError(code="invalid", message=str(e))
|
||||
except Exception as e:
|
||||
raise ApiError(code="invalid", message=str(e))
|
||||
|
||||
|
||||
def list_scripts():
|
||||
"""Provides a list of scripts that can be called by a script task."""
|
||||
scripts = Script.get_all_subclasses()
|
||||
script_meta = []
|
||||
for script_class in scripts:
|
||||
script_meta.append(
|
||||
{
|
||||
"name": script_class.__name__,
|
||||
"description": script_class().get_description()
|
||||
})
|
||||
return script_meta
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import requests
|
||||
|
||||
|
||||
class IRBDocAPI:
|
||||
"""Just your basic class that can pull in data from a few api endpoints and do a basic task."""
|
||||
|
||||
def do_task(self, task_data):
|
||||
print('*** IRB_Doc_API > do_task ***')
|
||||
print('task_data', task_data)
|
|
@ -17,11 +17,8 @@ from crc.services.workflow_processor import WorkflowProcessor
|
|||
class CompleteTemplate(Script):
|
||||
|
||||
def get_description(self):
|
||||
return
|
||||
"""Completes a word template, using the data available in the current task. Heavy on the
|
||||
error messages, because there is so much that can go wrong here, and we want to provide
|
||||
as much feedback as possible. Some of this might move up to a higher level object or be
|
||||
passed into all tasks as we complete more work."""
|
||||
return """Takes one argument, which is the name of a MS Word docx file to use as a template.
|
||||
All data currently collected up to this Task will be available for use in the template."""
|
||||
|
||||
def do_task(self, task, study_id, *args, **kwargs):
|
||||
"""Entry point, mostly worried about wiring it all up."""
|
||||
|
|
|
@ -5,7 +5,8 @@ from crc.scripts.script import Script
|
|||
|
||||
class FactService(Script):
|
||||
def get_description(self):
|
||||
return """Just your basic class that can pull in data from a few api endpoints and do a basic task."""
|
||||
return """Just your basic class that can pull in data from a few api endpoints and
|
||||
do a basic task."""
|
||||
|
||||
def get_cat(self):
|
||||
response = requests.get('https://cat-fact.herokuapp.com/facts/random')
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import importlib
|
||||
import os
|
||||
import pkgutil
|
||||
|
||||
from crc.api.common import ApiError
|
||||
|
||||
|
||||
|
@ -13,3 +17,25 @@ class Script:
|
|||
raise ApiError("invalid_script",
|
||||
"This is an internal error. The script you are trying to execute " +
|
||||
"does not properly implement the do_task function.")
|
||||
|
||||
@staticmethod
|
||||
def get_all_subclasses():
|
||||
return Script._get_all_subclasses(Script)
|
||||
|
||||
@staticmethod
|
||||
def _get_all_subclasses(cls):
|
||||
|
||||
# hackish mess to make sure we have all the modules loaded for the scripts
|
||||
pkg_dir = os.path.dirname(__file__)
|
||||
for (module_loader, name, ispkg) in pkgutil.iter_modules([pkg_dir]):
|
||||
importlib.import_module('.' + name, __package__)
|
||||
|
||||
|
||||
"""Returns a list of all classes that extend this class."""
|
||||
all_subclasses = []
|
||||
|
||||
for subclass in cls.__subclasses__():
|
||||
all_subclasses.append(subclass)
|
||||
all_subclasses.extend(Script._get_all_subclasses(subclass))
|
||||
|
||||
return all_subclasses
|
|
@ -13,8 +13,7 @@ class StudyInfo(Script):
|
|||
type_options = ['info', 'investigators', 'required_docs', 'details']
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
StudyInfo [TYPE] is one of 'info', 'investigators','required_docs', 'details'
|
||||
return """StudyInfo [TYPE], where TYPE is one of 'info', 'investigators','required_docs', or 'details'
|
||||
Adds details about the current study to the Task Data. The type of information required should be
|
||||
provided as an argument. Basic returns the basic information such as the title. Investigators provides
|
||||
detailed information about each investigator in th study. Details provides a large number
|
||||
|
|
|
@ -32,3 +32,11 @@ class TestStudyApi(BaseTest):
|
|||
data=file_data, follow_redirects=True,
|
||||
content_type='multipart/form-data')
|
||||
self.assert_success(rv)
|
||||
|
||||
def test_list_scripts(self):
|
||||
rv = self.app.get('/v1.0/list_scripts')
|
||||
self.assert_success(rv)
|
||||
scripts = json.loads(rv.get_data(as_text=True))
|
||||
self.assertTrue(len(scripts) > 1)
|
||||
self.assertIsNotNone(scripts[0]['name'])
|
||||
self.assertIsNotNone(scripts[0]['description'])
|
||||
|
|
Loading…
Reference in New Issue