Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/simdb/cli/commands/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def simulation_push(
schemas = api.get_validation_schemas()
try:
for schema in schemas:
Validator(schema).validate(simulation)
Validator(schema, config).validate(simulation)
except ValidationError as err:
raise click.ClickException(f"Simulation does not validate: {err}") from err

Expand Down Expand Up @@ -471,7 +471,7 @@ def simulation_validate(

click.echo("validating metadata ... ", nl=False)
for schema in schemas:
Validator(schema).validate(simulation)
Validator(schema, config).validate(simulation)

ids_list = []
for file in chain(simulation.inputs, simulation.outputs):
Expand Down
2 changes: 1 addition & 1 deletion src/simdb/cli/remote_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
from .manifest import DataType

if TYPE_CHECKING:
from simdb.database.models import File, Simulation, Watcher
from simdb.database.models import File, Watcher

if TYPE_CHECKING or "sphinx" in sys.modules:
# Only importing these for type checking and documentation generation in order to
Expand Down
2 changes: 1 addition & 1 deletion src/simdb/database/models/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def meta(self) -> List[MetaDataWrapper]:
Returns a list of MetaDataWrapper objects from the JSON metadata.
"""
meta_dict = self._get_metadata_dict()
return [MetaDataWrapper(k, v) for k, v in meta_dict.items()]
return list(itertools.starmap(MetaDataWrapper, meta_dict.items()))

def _get_metadata_dict(self) -> Dict[str, Any]:
if self._metadata is None:
Expand Down
2 changes: 1 addition & 1 deletion src/simdb/remote/apis/v1/simulations.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _update_simulation_status(
def _validate(simulation, user) -> Dict:
schema = Validator.validation_schema()
try:
Validator(schema).validate(simulation)
Validator(schema, current_app.simdb_config).validate(simulation)
_update_simulation_status(simulation, models_sim.Simulation.Status.PASSED, user)
return {
"passed": True,
Expand Down
2 changes: 1 addition & 1 deletion src/simdb/remote/apis/v1_1/simulations.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def _validate(simulation, user) -> Dict:
schemas = Validator.validation_schemas(current_app.simdb_config, simulation)
try:
for schema in schemas:
Validator(schema).validate(simulation)
Validator(schema, current_app.simdb_config).validate(simulation)
_update_simulation_status(
simulation, models_sim.Simulation.Status.PASSED, user
)
Expand Down
2 changes: 1 addition & 1 deletion src/simdb/remote/apis/v1_2/simulations.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def _validate(simulation, user) -> ValidationResult:
schemas = Validator.validation_schemas(current_app.simdb_config, simulation)
try:
for schema in schemas:
Validator(schema).validate(simulation)
Validator(schema, current_app.simdb_config).validate(simulation)
_update_simulation_status(
simulation, models_sim.Simulation.Status.PASSED, user
)
Expand Down
2 changes: 1 addition & 1 deletion src/simdb/validation/file/ids_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def configure(self, arguments: dict):
.split(",")
]

### Define logic for rule_filter
# Define logic for rule_filter
list_of_filter_names = (
arguments.get("rule_filter_name", "").strip('"').split(",")
)
Expand Down
41 changes: 39 additions & 2 deletions src/simdb/validation/validator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import re
import warnings
from importlib import import_module
from pathlib import Path
from typing import Any, Dict, List, Optional, Union, cast

Expand Down Expand Up @@ -200,9 +201,45 @@ def validation_schemas(

return schemas

def __init__(self, schema: Dict):
def _custom_validation_ext(self, config: Config):

module_path = config.get_option("validation.custom_validator", default=None)
if module_path is None:
return CustomValidator

if not isinstance(module_path, str):
raise TypeError(
"Expected 'custom_validator config value' to be a string, "
f"got {type(module_path).__name__}"
)

if "." not in module_path:
raise ValueError(
f"Invalid validator path '{module_path}'."
"Expected format: 'package.module.ClassName'"
)

module_name, class_name = module_path.rsplit(".", 1)

try:
module = import_module(module_name)
except ModuleNotFoundError as err:
raise ImportError(
f"Unable to import module '{module_name}': {err}. "
"Please ensure the necessary validation package is installed"
) from err
try:
validation_cls = getattr(module, class_name)
except AttributeError as err:
raise AttributeError(
f"Module '{module_name}' does not have classor attribute '{class_name}'"
) from err
return validation_cls

def __init__(self, schema: Dict, config: Config):
try:
self._validator = CustomValidator(schema)
validation_cls = self._custom_validation_ext(config)
self._validator = validation_cls(schema)
self._validator.allow_unknown = True
except cerberus.SchemaError as err:
raise LoadError("Failed to parse validation schema") from err
Expand Down
1 change: 0 additions & 1 deletion tests/remote/api/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import base64
import importlib
import importlib.util
import os
import shutil
Expand Down
1 change: 0 additions & 1 deletion tests/remote/test_authentication.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import importlib
import importlib.util
from typing import TYPE_CHECKING, ClassVar, cast
from unittest import mock
Expand Down
Loading