Skip to content

Commit c8a6a3f

Browse files
committed
feat: add strict option
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
1 parent cebfaed commit c8a6a3f

28 files changed

Lines changed: 115 additions & 74 deletions

docs/cli/t4sanity.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ $ t4sanity -h
1010
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
1111
╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
1212
│ --version -v Show the application version and exit. │
13-
│ --output -o TEXT Path to output JSON file.
14-
│ --revision -rv TEXT Specify if you want to check the specific version.
15-
│ --exclude -e TEXT Exclude specific rules or rule groups.
13+
│ --output -o TEXT Path to output JSON file. [default: None]
14+
│ --revision -rv TEXT Specify if you want to check the specific version. [default: None]
15+
│ --exclude -e TEXT Exclude specific rules or rule groups. [default: None]
1616
│ --include-warning -iw Indicates whether to report any warnings. │
17+
│ --strict -s Indicates whether warnings are treated as failures. │
1718
│ --install-completion Install completion for the current shell. │
1819
│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
1920
│ --help -h Show this message and exit. │
@@ -100,3 +101,14 @@ With `-e; --excludes` option enables us to exclude specific checks by specifying
100101
# Exclude STR001 and all FMT-relevant rules
101102
t4sanity <DATA_ROOT> -e STR001 -e FMT
102103
```
104+
105+
### Strict Mode
106+
107+
Basically, rules whose **severity is WARNING** will be treated as success.
108+
109+
With `-s; --strict` option enables us to treat warnings as failures:
110+
111+
```shell
112+
# Run strict mode
113+
t4sanity <DATA_ROOT> -s
114+
```

t4_devkit/cli/sanity.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,16 @@ def main(
3737
include_warning: bool = typer.Option(
3838
False, "-iw", "--include-warning", help="Indicates whether to report any warnings."
3939
),
40+
strict: bool = typer.Option(
41+
False, "-s", "--strict", help="Indicates whether warnings are treated as failures."
42+
),
4043
) -> None:
4144
result = sanity_check(
4245
data_root=data_root,
4346
revision=revision,
4447
excludes=excludes,
4548
include_warning=include_warning,
49+
strict=strict,
4650
)
4751

4852
print_sanity_result(result)

t4_devkit/sanity/checker.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from returns.maybe import Maybe, Nothing, Some
88

9-
from .result import make_failure, make_skipped, make_success
9+
from .result import make_report, make_skipped
1010

1111
if TYPE_CHECKING:
1212
from .context import SanityContext
@@ -48,15 +48,22 @@ def __call__(self, context: SanityContext) -> Report:
4848
return make_skipped(self.id, self.name, self.severity, self.description, skip)
4949

5050
reasons = self.check(context)
51-
if reasons:
52-
return make_failure(self.id, self.name, self.severity, self.description, reasons)
53-
else:
54-
return make_success(self.id, self.name, self.severity, self.description)
51+
return make_report(
52+
self.id, self.name, self.severity, self.description, reasons, strict=context.strict
53+
)
5554

5655
def can_skip(self, _: SanityContext) -> Maybe[Reason]:
5756
"""Return a skip reason if the checker should be skipped."""
5857
return Nothing
5958

6059
@abstractmethod
61-
def check(self, context: SanityContext) -> list[Reason]:
60+
def check(self, context: SanityContext) -> list[Reason] | None:
61+
"""Return a list of reasons if the checker fails, or None if it passes.
62+
63+
Args:
64+
context (SanityContext): The sanity context.
65+
66+
Returns:
67+
A list of reasons if the checker fails, or None if it passes.
68+
"""
6269
pass

t4_devkit/sanity/context.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
@define
1616
class SanityContext:
1717
metadata: Maybe[DBMetadata]
18+
strict: bool
1819

1920
@classmethod
20-
def from_path(cls, data_root: str, revision: str | None = None) -> Self:
21+
def from_path(cls, data_root: str, revision: str | None = None, strict: bool = False) -> Self:
2122
metadata_result = _load_metadata_safe(data_root, revision=revision)
2223
metadata = metadata_result.unwrap() if is_successful(metadata_result) else None
23-
return cls(Maybe.from_optional(metadata))
24+
return cls(Maybe.from_optional(metadata), strict)
2425

2526
@property
2627
def data_root(self) -> Maybe[Path]:

t4_devkit/sanity/format/base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,24 @@ def can_skip(self, context: SanityContext) -> Maybe[Reason]:
3737
case _:
3838
return Nothing
3939

40-
def check(self, context: SanityContext) -> list[Reason]:
40+
def check(self, context: SanityContext) -> list[Reason] | None:
4141
filepath = context.to_schema_file(self.schema).unwrap()
4242

4343
if self.schema.is_optional() and not filepath.exists():
44-
return []
44+
return None
4545

4646
records = load_json_safe(filepath)
4747
return _build_records(self.schema, records.unwrap())
4848

4949

50-
def _build_records(schema: SchemaName, records: list[dict]) -> list[Reason]:
50+
def _build_records(schema: SchemaName, records: list[dict]) -> list[Reason] | None:
5151
module = SCHEMAS.get(schema)
5252
failures = []
5353
for record in records:
5454
conversion = _safe_from_dict(module, record)
5555
if not is_successful(conversion):
5656
failures.append(Reason(f"[{schema.name}] {record['token']}: {conversion.failure()}"))
57-
return failures
57+
return failures if failures else None
5858

5959

6060
@safe

t4_devkit/sanity/record/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,19 @@ def can_skip(self, context: SanityContext) -> Maybe[Reason]:
3737
case _:
3838
return Maybe.from_value(Reason("Missing 'annotation' directory path"))
3939

40-
def check(self, context: SanityContext) -> list[Reason]:
40+
def check(self, context: SanityContext) -> list[Reason] | None:
4141
filepath = context.to_schema_file(self.schema).unwrap()
4242
records = load_json_safe(filepath).unwrap()
4343
return self.check_count(records)
4444

4545
@abstractmethod
46-
def check_count(self, records: list[dict]) -> list[Reason]:
46+
def check_count(self, records: list[dict]) -> list[Reason] | None:
4747
"""Check the count of records.
4848
4949
Args:
5050
records (list[dict]): The list of records to check.
5151
5252
Returns:
53-
A list of reasons for any issues found, otherwise an empty list.
53+
A list of reasons for any issues found, otherwise None.
5454
"""
5555
pass

t4_devkit/sanity/record/rec001.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ class REC001(RecordCountChecker):
1919
description = "'Scene' record is a single."
2020
schema = SchemaName.SCENE
2121

22-
def check_count(self, records: list[dict]) -> list[Reason]:
22+
def check_count(self, records: list[dict]) -> list[Reason] | None:
2323
num_scene = len(records)
2424
return (
25-
[]
25+
None
2626
if num_scene == 1
2727
else [Reason(f"'Scene' must contain exactly one element: {num_scene}")]
2828
)

t4_devkit/sanity/record/rec002.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ class REC002(RecordCountChecker):
1919
description = "'Sample' record is not empty."
2020
schema = SchemaName.SAMPLE
2121

22-
def check_count(self, records: list[dict]) -> list[Reason]:
22+
def check_count(self, records: list[dict]) -> list[Reason] | None:
2323
num_sample = len(records)
24-
return [Reason("'Sample' record must not be empty")] if num_sample == 0 else []
24+
return [Reason("'Sample' record must not be empty")] if num_sample == 0 else None

t4_devkit/sanity/record/rec003.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ class REC003(RecordCountChecker):
1919
description = "'SampleData' record is not empty."
2020
schema = SchemaName.SAMPLE_DATA
2121

22-
def check_count(self, records: list[dict]) -> list[Reason]:
22+
def check_count(self, records: list[dict]) -> list[Reason] | None:
2323
num_sample_data = len(records)
24-
return [Reason("'SampleData' record must not be empty")] if num_sample_data == 0 else []
24+
return [Reason("'SampleData' record must not be empty")] if num_sample_data == 0 else None

t4_devkit/sanity/record/rec004.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ class REC004(RecordCountChecker):
1919
description = "'EgoPose' record is not empty."
2020
schema = SchemaName.EGO_POSE
2121

22-
def check_count(self, records: list[dict]) -> list[Reason]:
22+
def check_count(self, records: list[dict]) -> list[Reason] | None:
2323
num_ego_pose = len(records)
24-
return [Reason("'EgoPose' record must not be empty")] if num_ego_pose == 0 else []
24+
return [Reason("'EgoPose' record must not be empty")] if num_ego_pose == 0 else None

0 commit comments

Comments
 (0)