got library side working - still need to have parent working
This commit is contained in:
parent
79c69037dd
commit
2455495457
17
Pipfile
17
Pipfile
|
@ -10,7 +10,6 @@ coverage = "*"
|
|||
|
||||
[packages]
|
||||
alembic = "*"
|
||||
connexion = {extras = ["swagger-ui"],version = "*"}
|
||||
coverage = "*"
|
||||
docxtpl = "*"
|
||||
flask = "*"
|
||||
|
@ -36,11 +35,8 @@ pyjwt = "*"
|
|||
python-dateutil = "*"
|
||||
recommonmark = "*"
|
||||
requests = "*"
|
||||
sentry-sdk = {extras = ["flask"],version = "==0.14.4"}
|
||||
sphinx = "*"
|
||||
swagger-ui-bundle = "*"
|
||||
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git"}
|
||||
# spiffworkflow = {editable = true, path = "./../SpiffWorkflow"}
|
||||
webtest = "*"
|
||||
werkzeug = "*"
|
||||
xlrd = "*"
|
||||
|
@ -50,4 +46,15 @@ python-levenshtein = "*"
|
|||
apscheduler = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.8"
|
||||
python_version = "3.9"
|
||||
|
||||
[packages.connexion]
|
||||
extras = [ "swagger-ui",]
|
||||
version = "*"
|
||||
|
||||
[packages.sentry-sdk]
|
||||
extras = [ "flask",]
|
||||
version = "==0.14.4"
|
||||
|
||||
[packages.spiffworkflow]
|
||||
git = "https://github.com/sartography/SpiffWorkflow.git"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
79
crc/api.yml
79
crc/api.yml
|
@ -426,6 +426,70 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/WorkflowSpec"
|
||||
|
||||
/workflow-specification/{spec_id}/libraries:
|
||||
parameters:
|
||||
- name: spec_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing workflow specification.
|
||||
schema:
|
||||
type: string
|
||||
get:
|
||||
operationId: crc.api.workflow.get_workflow_specification_libraries
|
||||
summary: Returns all libraries that are enabled for a workflow spec
|
||||
tags:
|
||||
- Workflow Specifications
|
||||
responses:
|
||||
'200':
|
||||
description: Workflow specification.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/WorkflowSpec"
|
||||
|
||||
/workflow-specification/{spec_id}/library/{library_id}:
|
||||
parameters:
|
||||
- name: spec_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing workflow specification.
|
||||
schema:
|
||||
type: string
|
||||
- name: library_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing library specification.
|
||||
schema:
|
||||
type: string
|
||||
|
||||
|
||||
post:
|
||||
operationId: crc.api.workflow.add_workflow_spec_library
|
||||
summary: Adds a library to a workflow spec
|
||||
tags:
|
||||
- Workflow Specifications
|
||||
responses:
|
||||
'200':
|
||||
description: Workflow specification.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/WorkflowSpec"
|
||||
delete:
|
||||
operationId: crc.api.workflow.drop_workflow_spec_library
|
||||
summary: Delete a library from a workflow
|
||||
tags:
|
||||
- Workflow Specifications
|
||||
responses:
|
||||
'200':
|
||||
description: Workflow specification.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/WorkflowSpec"
|
||||
|
||||
|
||||
/workflow-specification/{spec_id}:
|
||||
parameters:
|
||||
- name: spec_id
|
||||
|
@ -502,6 +566,21 @@ paths:
|
|||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/WorkflowSpec"
|
||||
/workflow-specification/libraries:
|
||||
get:
|
||||
operationId: crc.api.workflow.library_workflow_specs
|
||||
summary: Provides a list of workflow specifications that are considered libraries.
|
||||
tags:
|
||||
- Workflow Specifications
|
||||
responses:
|
||||
'200':
|
||||
description: A list of workflow specifications
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/WorkflowSpec"
|
||||
/workflow-specification/{spec_id}/validate:
|
||||
parameters:
|
||||
- name: spec_id
|
||||
|
|
|
@ -10,7 +10,7 @@ from crc.models.study import StudyModel, WorkflowMetadata, StudyStatus
|
|||
from crc.models.task_event import TaskEventModel, TaskEvent, TaskEventSchema
|
||||
from crc.models.user import UserModelSchema
|
||||
from crc.models.workflow import WorkflowModel, WorkflowSpecModelSchema, WorkflowSpecModel, WorkflowSpecCategoryModel, \
|
||||
WorkflowSpecCategoryModelSchema
|
||||
WorkflowSpecCategoryModelSchema, WorkflowLibraryModel, WorkflowLibraryModelSchema
|
||||
from crc.services.error_service import ValidationErrorService
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.lookup_service import LookupService
|
||||
|
@ -22,7 +22,8 @@ from crc.services.workflow_service import WorkflowService
|
|||
|
||||
def all_specifications():
|
||||
schema = WorkflowSpecModelSchema(many=True)
|
||||
return schema.dump(session.query(WorkflowSpecModel).all())
|
||||
return schema.dump(session.query(WorkflowSpecModel).filter((WorkflowSpecModel.library==False)|(
|
||||
WorkflowSpecModel.library==None)).all())
|
||||
|
||||
|
||||
def add_workflow_specification(body):
|
||||
|
@ -45,6 +46,50 @@ def get_workflow_specification(spec_id):
|
|||
|
||||
return WorkflowSpecModelSchema().dump(spec)
|
||||
|
||||
def get_workflow_specification_libraries(spec_id):
|
||||
if spec_id is None:
|
||||
raise ApiError('unknown_spec', 'Please provide a valid Workflow Specification ID.')
|
||||
spec: WorkflowSpecModel = session.query(WorkflowSpecModel).filter_by(id=spec_id).first()
|
||||
libraries: WorkflowLibraryModel = session.query(WorkflowLibraryModel).filter_by(workflow_spec_id=spec_id).all()
|
||||
if spec is None:
|
||||
raise ApiError('unknown_spec', 'The Workflow Specification "' + spec_id + '" is not recognized.')
|
||||
return WorkflowLibraryModelSchema(many=True).dump(libraries)
|
||||
|
||||
def validate_spec_and_library(spec_id,library_id):
|
||||
if spec_id is None:
|
||||
raise ApiError('unknown_spec', 'Please provide a valid Workflow Specification ID.')
|
||||
if library_id is None:
|
||||
raise ApiError('unknown_spec', 'Please provide a valid Library Specification ID.')
|
||||
spec: WorkflowSpecModel = session.query(WorkflowSpecModel).filter_by(id=spec_id).first()
|
||||
library: WorkflowSpecModel = session.query(WorkflowSpecModel).filter_by(id=library_id).first()
|
||||
if spec is None:
|
||||
raise ApiError('unknown_spec', 'The Workflow Specification "' + spec_id + '" is not recognized.')
|
||||
if library is None:
|
||||
raise ApiError('unknown_spec', 'The Library Specification "' + library_id + '" is not recognized.')
|
||||
if not library.library:
|
||||
raise ApiError('unknown_spec', 'Linked workflow spec is not a library.')
|
||||
|
||||
|
||||
def add_workflow_spec_library(spec_id,library_id):
|
||||
validate_spec_and_library(spec_id, library_id)
|
||||
libraries: WorkflowLibraryModel = session.query(WorkflowLibraryModel).filter_by(workflow_spec_id=spec_id).all()
|
||||
libraryids = [x.library_spec_id for x in libraries]
|
||||
if library_id in libraryids:
|
||||
raise ApiError('unknown_spec', 'The Library Specification "' + spec_id + '" is already attached.')
|
||||
newlib = WorkflowLibraryModel()
|
||||
newlib.workflow_spec_id = spec_id
|
||||
newlib.library_spec_id = library_id
|
||||
session.add(newlib)
|
||||
session.commit()
|
||||
libraries: WorkflowLibraryModel = session.query(WorkflowLibraryModel).filter_by(workflow_spec_id=spec_id).all()
|
||||
return WorkflowLibraryModelSchema(many=True).dump(libraries)
|
||||
|
||||
def drop_workflow_spec_library(spec_id,library_id):
|
||||
validate_spec_and_library(spec_id, library_id)
|
||||
session.query(WorkflowLibraryModel).filter_by(workflow_spec_id=spec_id,library_spec_id=library_id).delete()
|
||||
session.commit()
|
||||
libraries: WorkflowLibraryModel = session.query(WorkflowLibraryModel).filter_by(workflow_spec_id=spec_id).all()
|
||||
return WorkflowLibraryModelSchema(many=True).dump(libraries)
|
||||
|
||||
def validate_workflow_specification(spec_id, validate_study_id=None, test_until=None):
|
||||
errors = {}
|
||||
|
@ -118,6 +163,10 @@ def standalone_workflow_specs():
|
|||
specs = WorkflowService.get_standalone_workflow_specs()
|
||||
return schema.dump(specs)
|
||||
|
||||
def library_workflow_specs():
|
||||
schema = WorkflowSpecModelSchema(many=True)
|
||||
specs = WorkflowService.get_library_workflow_specs()
|
||||
return schema.dump(specs)
|
||||
|
||||
def get_workflow(workflow_id, do_engine_steps=True):
|
||||
"""Retrieve workflow based on workflow_id, and return it in the last saved State.
|
||||
|
|
|
@ -159,7 +159,6 @@ def create_or_update_local_spec(remote,workflow_spec_id):
|
|||
localcategory.name = specdict['category']['name']
|
||||
localcategory.display_name = specdict['category']['display_name']
|
||||
localcategory.display_order = specdict['category']['display_order']
|
||||
localcategory.library = False
|
||||
session.add(localcategory)
|
||||
localspec.category = localcategory
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import enum
|
||||
|
||||
import marshmallow
|
||||
from marshmallow import EXCLUDE
|
||||
from marshmallow import EXCLUDE,fields
|
||||
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
|
||||
from sqlalchemy import func
|
||||
|
||||
|
@ -15,7 +15,6 @@ class WorkflowSpecCategoryModel(db.Model):
|
|||
name = db.Column(db.String)
|
||||
display_name = db.Column(db.String)
|
||||
display_order = db.Column(db.Integer)
|
||||
library = db.Column(db.Boolean)
|
||||
|
||||
|
||||
class WorkflowSpecCategoryModelSchema(SQLAlchemyAutoSchema):
|
||||
|
@ -25,6 +24,7 @@ class WorkflowSpecCategoryModelSchema(SQLAlchemyAutoSchema):
|
|||
include_relationships = True
|
||||
|
||||
|
||||
|
||||
class WorkflowSpecModel(db.Model):
|
||||
__tablename__ = 'workflow_spec'
|
||||
id = db.Column(db.String, primary_key=True)
|
||||
|
@ -36,6 +36,19 @@ class WorkflowSpecModel(db.Model):
|
|||
category = db.relationship("WorkflowSpecCategoryModel")
|
||||
is_master_spec = db.Column(db.Boolean, default=False)
|
||||
standalone = db.Column(db.Boolean, default=False)
|
||||
library = db.Column(db.Boolean, default=False)
|
||||
|
||||
|
||||
class WorkflowLibraryModel(db.Model):
|
||||
__tablename__ = 'workflow_library'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
workflow_spec_id = db.Column(db.String, db.ForeignKey('workflow_spec.id'), nullable=True)
|
||||
library_spec_id = db.Column(db.String, db.ForeignKey('workflow_spec.id'), nullable=True)
|
||||
workflow_side = db.relationship(WorkflowSpecModel,
|
||||
primaryjoin=workflow_spec_id==WorkflowSpecModel.id,
|
||||
backref='libraries')
|
||||
library = db.relationship(WorkflowSpecModel,primaryjoin=library_spec_id==WorkflowSpecModel.id,
|
||||
backref='referred_by')
|
||||
|
||||
|
||||
class WorkflowSpecModelSchema(SQLAlchemyAutoSchema):
|
||||
|
@ -47,7 +60,10 @@ class WorkflowSpecModelSchema(SQLAlchemyAutoSchema):
|
|||
unknown = EXCLUDE
|
||||
|
||||
category = marshmallow.fields.Nested(WorkflowSpecCategoryModelSchema, dump_only=True)
|
||||
|
||||
libraries = marshmallow.fields.Function(lambda obj: [{'id':x.library.id,
|
||||
'name':x.library.name,
|
||||
'display_name':x.library.display_name} for x in
|
||||
obj.libraries] )
|
||||
|
||||
class WorkflowState(enum.Enum):
|
||||
hidden = "hidden"
|
||||
|
@ -79,6 +95,15 @@ class WorkflowSpecDependencyFile(db.Model):
|
|||
file_data = db.relationship(FileDataModel)
|
||||
|
||||
|
||||
|
||||
class WorkflowLibraryModelSchema(SQLAlchemyAutoSchema):
|
||||
class Meta:
|
||||
model = WorkflowLibraryModel
|
||||
load_instance = True
|
||||
include_relationships = True
|
||||
|
||||
library = marshmallow.fields.Nested('WorkflowSpecModelSchema')
|
||||
|
||||
class WorkflowModel(db.Model):
|
||||
__tablename__ = 'workflow'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
|
|
@ -242,8 +242,7 @@ class StudyService(object):
|
|||
def get_categories():
|
||||
"""Returns a list of category objects, in the correct order."""
|
||||
cat_models = db.session.query(WorkflowSpecCategoryModel) \
|
||||
.order_by(WorkflowSpecCategoryModel.display_order) \
|
||||
.filter((WorkflowSpecCategoryModel.library == None)|(WorkflowSpecCategoryModel.library ==False)).all()
|
||||
.order_by(WorkflowSpecCategoryModel.display_order).all()
|
||||
categories = []
|
||||
for cat_model in cat_models:
|
||||
categories.append(Category(cat_model))
|
||||
|
|
|
@ -886,6 +886,11 @@ class WorkflowService(object):
|
|||
specs = db.session.query(WorkflowSpecModel).filter_by(standalone=True).all()
|
||||
return specs
|
||||
|
||||
@staticmethod
|
||||
def get_library_workflow_specs():
|
||||
specs = db.session.query(WorkflowSpecModel).filter_by(library=True).all()
|
||||
return specs
|
||||
|
||||
@staticmethod
|
||||
def get_primary_workflow(workflow_spec_id):
|
||||
# Returns the FileModel of the primary workflow for a workflow_spec
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: a931e2b7b070
|
||||
Revises: 47b10b171d7c
|
||||
Create Date: 2021-07-12 08:46:08.814577
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'a931e2b7b070'
|
||||
down_revision = 'bbf064082623'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('workflow_library',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('workflow_spec_id', sa.String(), nullable=True),
|
||||
sa.Column('library_spec_id', sa.String(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['library_spec_id'], ['workflow_spec.id'], ),
|
||||
sa.ForeignKeyConstraint(['workflow_spec_id'], ['workflow_spec.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('workflow_library')
|
||||
# ### end Alembic commands ###
|
|
@ -0,0 +1,28 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: b0f38c78db40
|
||||
Revises: a931e2b7b070
|
||||
Create Date: 2021-07-14 09:30:42.562825
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'b0f38c78db40'
|
||||
down_revision = 'a931e2b7b070'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('workflow_spec', sa.Column('library', sa.Boolean(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('workflow_spec', 'library')
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in New Issue