Skip to content

Commit 1c5bca2

Browse files
author
Alan Christie
committed
feat: Basic files for validator
1 parent a7c13a9 commit 1c5bca2

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ build-backend = "poetry.core.masonry.api"
2929
omit = [
3030
"tests/*",
3131
]
32+
33+
[tool.pylint]
34+
disable = [
35+
"too-few-public-methods",
36+
]

workflow/workflow_abc.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""Workflow abstract base classes.
2+
Interface definitions of class instances that must be provided to the Engine.
3+
"""
4+
5+
from abc import ABC, abstractmethod
6+
from dataclasses import dataclass
7+
from typing import Any, Dict, Optional
8+
9+
10+
@dataclass
11+
class LaunchResult:
12+
"""Results returned from methods in the InstanceLauncher."""
13+
14+
error: int
15+
error_msg: Optional[str]
16+
instance_id: Optional[str]
17+
task_id: Optional[str]
18+
19+
20+
class DatabaseAdapter(ABC):
21+
"""The DatabaseAdapter will not need to provide a save/commit service.
22+
Instead it should be assumed that new database records are the
23+
responsibility of the governing application code. The WE simply has
24+
to implement engine logic and launch instance. The InstanceLauncher
25+
is responsible for creating RunningWorkflow and RunningWorkflowStep
26+
records for example."""
27+
28+
@abstractmethod
29+
def get_workflow(
30+
self,
31+
*,
32+
workflow_definition_id: str,
33+
) -> Optional[Dict[str, Any]]:
34+
"""Get a Workflow by ID"""
35+
36+
@abstractmethod
37+
def get_workflow_by_name(
38+
self,
39+
*,
40+
name: str,
41+
version: str,
42+
) -> Optional[Dict[str, Any]]:
43+
"""Get a Workflow by name"""
44+
45+
@abstractmethod
46+
def get_job(
47+
self,
48+
*,
49+
collection: str,
50+
job: str,
51+
version: str,
52+
) -> Optional[Dict[str, Any]]:
53+
"""Get a Job"""

workflow/worklfow_validator.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""The WorkflowEngine validation logic.
2+
"""
3+
4+
from dataclasses import dataclass
5+
from enum import Enum
6+
from typing import Any, Dict, List, Optional
7+
8+
from .decoder import validate_schema
9+
from .workflow_abc import DatabaseAdapter
10+
11+
12+
class ValidationLevel(Enum):
13+
"""Workflow validation levels."""
14+
15+
CREATE = 1
16+
RUN = 2
17+
TAG = 3
18+
19+
20+
@dataclass
21+
class ValidationResult:
22+
"""Workflow validation results."""
23+
24+
error: int
25+
error_msg: Optional[List[str]]
26+
27+
28+
# A successful validation result.
29+
_VALIDATION_SUCCESS = ValidationResult(error=0, error_msg=None)
30+
31+
32+
class WorkflowValidator:
33+
"""The workflow validator. Typically used from teh context of the API
34+
to check workflow content prior to creation and execution.
35+
"""
36+
37+
def __init__(
38+
self,
39+
*,
40+
db_adapter: DatabaseAdapter,
41+
):
42+
assert db_adapter
43+
44+
self.db_adapter = db_adapter
45+
46+
def validate(
47+
self,
48+
*,
49+
level: ValidationLevel,
50+
workflow_definition: Dict[str, Any],
51+
workflow_inputs: Optional[Dict[str, Any]],
52+
) -> ValidationResult:
53+
"""Validates the workflow definition (and inputs) based
54+
on the provided 'level'."""
55+
assert level in ValidationLevel
56+
assert isinstance(workflow_definition, dict)
57+
if workflow_inputs:
58+
assert isinstance(workflow_inputs, dict)
59+
60+
if error := validate_schema(workflow_definition):
61+
return ValidationResult(error=1, error_msg=[error])
62+
63+
return _VALIDATION_SUCCESS

0 commit comments

Comments
 (0)