Skip to content

Commit e593688

Browse files
authored
Merge branch 'develop' into v2_calculate
2 parents ced3bdc + b0f4c4f commit e593688

File tree

3 files changed

+39
-41
lines changed

3 files changed

+39
-41
lines changed

petab/petablint.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import logging
77
import sys
88

9+
import pydantic
910
from colorama import Fore
1011
from colorama import init as init_colorama
1112
from jsonschema.exceptions import ValidationError as SchemaValidationError
@@ -160,10 +161,23 @@ def main():
160161
try:
161162
validate(args.yaml_file_name)
162163
except SchemaValidationError as e:
164+
path = ""
165+
if e.absolute_path:
166+
# construct a path to the error location inside the YAML file
167+
path = list(e.absolute_path)
168+
path = (
169+
f" at {path[0]}"
170+
+ "".join(f"[{str(p)}]" for p in path[1:])
171+
+ ": "
172+
)
163173
logger.error(
164-
f"Provided YAML file does not adhere to PEtab schema: {e}"
174+
"Provided YAML file does not adhere to the PEtab schema"
175+
f"{path}: {e.args[0]}"
165176
)
166177
sys.exit(1)
178+
except ValueError as e:
179+
logger.error(e)
180+
sys.exit(1)
167181

168182
if petab.is_composite_problem(args.yaml_file_name):
169183
# TODO: further checking:
@@ -179,12 +193,24 @@ def main():
179193
case 2:
180194
from petab.v2.lint import lint_problem
181195

182-
validation_issues = lint_problem(args.yaml_file_name)
183-
if validation_issues:
184-
validation_issues.log(logger=logger)
196+
try:
197+
validation_issues = lint_problem(args.yaml_file_name)
198+
if validation_issues:
199+
# Handle petab.v2.lint.ValidationTask issues
200+
validation_issues.log(logger=logger)
201+
sys.exit(1)
202+
logger.info("PEtab format check completed successfully.")
203+
sys.exit(0)
204+
except pydantic.ValidationError as e:
205+
# Handle Pydantic validation errors
206+
for err in e.errors():
207+
loc = ", ".join(str(loc) for loc in err["loc"])
208+
msg = err["msg"]
209+
# TODO: include model info here once available
210+
# https://github.com/pydantic/pydantic/issues/7224
211+
logger.error(f"Error in field(s) `{loc}`: {msg}")
185212
sys.exit(1)
186-
logger.info("PEtab format check completed successfully.")
187-
sys.exit(0)
213+
188214
case _:
189215
logger.error(
190216
"The provided PEtab files are of unsupported version "

petab/v1/yaml.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,14 @@ def validate_yaml_syntax(
7777
# but let's still use the latest PEtab schema for full validation
7878
version = yaml_config.get(FORMAT_VERSION, None)
7979
version = (
80-
parse_version(version)[:2]
81-
if version
82-
else list(SCHEMAS.values())[-1]
80+
parse_version(version)[:2] if version else list(SCHEMAS.keys())[-1]
8381
)
8482

8583
try:
8684
schema = SCHEMAS[version]
8785
except KeyError as e:
8886
raise ValueError(
89-
"Unknown PEtab version given in problem "
87+
"No or unknown PEtab version given in problem "
9088
f"specification: {version}"
9189
) from e
9290
schema = load_yaml(schema)

petab/v2/lint.py

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
"CheckUnusedExperiments",
4040
"CheckObservablesDoNotShadowModelEntities",
4141
"CheckUnusedConditions",
42-
"CheckAllObservablesDefined",
4342
"CheckPriorDistribution",
4443
"lint_problem",
4544
"default_validation_tasks",
@@ -261,8 +260,9 @@ def run(self, problem: Problem) -> ValidationIssue | None:
261260
}
262261
if undefined_observables := (used_observables - defined_observables):
263262
return ValidationError(
264-
f"Observables {undefined_observables} used in "
265-
"measurement table but not defined in observable table."
263+
f"Observable(s) {undefined_observables} are used in the "
264+
"measurement table but are not defined in the observable "
265+
"table."
266266
)
267267

268268
return None
@@ -289,8 +289,8 @@ def run(self, problem: Problem) -> ValidationIssue | None:
289289
expected = observable_parameters_count[m.observable_id]
290290
except KeyError:
291291
messages.append(
292-
f"Observable {m.observable_id} used in measurement "
293-
f"table is not defined."
292+
f"Observable {m.observable_id} is used in the measurement "
293+
f"table but is not defined in the observable table."
294294
)
295295
continue
296296

@@ -443,31 +443,6 @@ def run(self, problem: Problem) -> ValidationIssue | None:
443443
return None
444444

445445

446-
class CheckAllObservablesDefined(ValidationTask):
447-
"""A task to validate that all observables in the measurement table are
448-
defined in the observable table."""
449-
450-
def run(self, problem: Problem) -> ValidationIssue | None:
451-
if problem.measurement_df is None:
452-
return None
453-
454-
measurement_df = problem.measurement_df
455-
observable_df = problem.observable_df
456-
used_observables = set(measurement_df[OBSERVABLE_ID].values)
457-
defined_observables = (
458-
set(observable_df.index.values)
459-
if observable_df is not None
460-
else set()
461-
)
462-
if undefined_observables := (used_observables - defined_observables):
463-
return ValidationError(
464-
f"Observables {undefined_observables} are used in the"
465-
"measurements table but are not defined in observables table."
466-
)
467-
468-
return None
469-
470-
471446
class CheckUniquePrimaryKeys(ValidationTask):
472447
"""Check that all primary keys are unique."""
473448

@@ -1092,7 +1067,6 @@ def get_placeholders(
10921067
# CheckVisualizationTable(),
10931068
# TODO validate mapping table
10941069
CheckValidParameterInConditionOrParameterTable(),
1095-
CheckAllObservablesDefined(),
10961070
CheckAllParametersPresentInParameterTable(),
10971071
CheckValidConditionTargets(),
10981072
CheckPriorDistribution(),

0 commit comments

Comments
 (0)