Skip to content

Commit 4ed54e1

Browse files
committed
[app][cli] Ensure saved config file can be loaded
Introduce new explicit config option for scan-only. Fixes #240.
1 parent 37a647d commit 4ed54e1

File tree

9 files changed

+28
-22
lines changed

9 files changed

+28
-22
lines changed

docs/changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ Fixes issue with application not loading config files saved with v1.8.
1414
#### Changelog
1515

1616
* [general] Add `--ignore-user-config` flag to both `dvr-scan` and `dvr-scan-app` commands to allow the application to run even if the user config file is corrupted
17+
* [general] Add new `scan-only` config option to match the UI checkbox and the `--scan-only` CLI flag
18+
* [bugfix] Fix crash on startup when trying to load user config saved with v1.8 [#240](https://github.com/Breakthrough/DVR-Scan/issues/240)
19+
* This was caused by the `scan-only` UI option being emitted but the config file did not support it in v1.8
20+
* Users who are running into this issue should be able to run DVR-Scan after updating to v1.8.1
21+
* As a workaround for previous versions, you can manually remove the `scan-only` line in the saved config file
1722

1823

1924
### 1.8 (August 23, 2025)

dvr_scan/app/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def main():
139139
args = get_cli_parser().parse_args()
140140
if args.ignore_user_config:
141141
config_load_error = None
142-
user_config = ConfigRegistry()
142+
config = ConfigRegistry()
143143
init_logging(args, config)
144144
init_log += [(logging.INFO, "DVR-Scan Application %s" % dvr_scan.__version__)]
145145
if config_load_error and not hasattr(args, "config"):

dvr_scan/app/application.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,8 @@ def save(self, settings: ScanSettings) -> ScanSettings:
13641364
return settings
13651365

13661366
def load(self, settings: ScanSettings):
1367-
if OutputMode[settings.get("output-mode").upper()] == OutputMode.SCAN_ONLY:
1367+
output_mode = OutputMode[settings.get("output-mode").upper()]
1368+
if settings.get("scan-only") or output_mode == OutputMode.SCAN_ONLY:
13681369
self.scan_only = True
13691370
self.open_on_completion = settings.get("open-output-dir")
13701371

@@ -1669,13 +1670,13 @@ def _get_settings(self) -> ty.Optional[ScanSettings]:
16691670
settings = self._output_area.save(settings)
16701671
settings = self._scan_area.save(settings)
16711672

1672-
# Check if we are going to create any output files.
1673-
# *NOTE*: Depending on the user's settings, we may generate output files even in scan-only
1674-
# mode (e.g. if the user is generating a mask file).
1673+
output_mode = (
1674+
OutputMode.SCAN_ONLY if settings.get("scan-only") else settings.get("output-mode")
1675+
)
1676+
# Check if we are going to create any output files. We will create files as long as we're
1677+
# not in scan-only mode, or if we
16751678
if not settings.get("output-dir") and (
1676-
not settings.get("scan-only")
1677-
or settings.get("mask-output")
1678-
or self._output_area.combine
1679+
output_mode != OutputMode.SCAN_ONLY or settings.get("mask-output")
16791680
):
16801681
# We will create files but an output directory wasn't set ahead of time - prompt the
16811682
# user to select one.

dvr_scan/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ def from_config(config_value: str, default: "RGBValue") -> "RGBValue":
329329
"open-output-dir": True,
330330
"output-mode": "opencv",
331331
"region-editor": False,
332+
"scan-only": False,
332333
# Motion Events
333334
"min-event-length": TimecodeValue("0.1s"),
334335
"time-before-event": TimecodeValue("1.5s"),

dvr_scan/controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def parse_settings() -> ty.Optional[ScanSettings]:
8888
args = get_cli_parser(config).parse_args()
8989
if args.ignore_user_config:
9090
config_load_error = None
91-
user_config = ConfigRegistry()
91+
config = ConfigRegistry()
9292
debug_mode = args.debug
9393
init_logging(args=args, config=config)
9494
init_log += [(logging.INFO, "DVR-Scan %s" % dvr_scan.__version__)]

dvr_scan/scanner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ def set_output(
349349
KeyError:
350350
- output_mode does not exist in OutputMode
351351
"""
352+
print(output_mode)
352353
if output_dir:
353354
if comp_file and comp_file.is_absolute():
354355
raise ValueError("output file cannot be absolute path if output directory is set!")

dvr_scan/shared/__init__.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,16 @@ def init_scanner(
125125
)
126126

127127
output_dir = settings.get("output-dir")
128+
comp_file = settings.get_arg(
129+
"output",
130+
)
131+
mask_file = settings.get_arg("mask-output")
132+
output_mode = OutputMode.SCAN_ONLY if settings.get("scan-only") else settings.get("output-mode")
133+
128134
scanner.set_output(
129-
comp_file=Path(settings.get("output", ignore_config=True))
130-
if settings.get("output", ignore_config=True)
131-
else None,
132-
mask_file=Path(settings.get_arg("mask-output"))
133-
if settings.get_arg("mask-output")
134-
else None,
135-
output_mode=OutputMode.SCAN_ONLY
136-
if settings.get_arg("scan-only")
137-
else settings.get("output-mode"),
135+
comp_file=Path(comp_file) if comp_file else None,
136+
mask_file=Path(mask_file) if mask_file else None,
137+
output_mode=output_mode,
138138
opencv_fourcc=settings.get("opencv-codec"),
139139
ffmpeg_input_args=settings.get("ffmpeg-input-args"),
140140
ffmpeg_output_args=settings.get("ffmpeg-output-args"),

dvr_scan/shared/settings.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,14 @@ def get_arg(self, option: str) -> ty.Optional[ty.Any]:
4040
arg_name = option.replace("-", "_")
4141
return getattr(self._args, arg_name) if hasattr(self._args, arg_name) else None
4242

43-
def get(self, option: str, ignore_config: bool = False) -> ty.Union[str, int, float, bool]:
43+
def get(self, option: str) -> ty.Union[str, int, float, bool]:
4444
"""Get the current value for `option`, preferring the current UI or CLI setting, falling
4545
back to either the config file option, or the default value."""
4646
if option in self._app_settings:
4747
return self._app_settings[option]
4848
arg_val = self.get_arg(option)
4949
if arg_val is not None:
5050
return arg_val
51-
if ignore_config:
52-
return None
5351
return self._config.get(option)
5452

5553
def set(self, option: str, value: ty.Union[str, int, float, bool]):

tests/test_cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"0",
4343
"--threshold",
4444
"0.2",
45-
"--ignore-user-config"
45+
"--ignore-user-config",
4646
]
4747
BASE_COMMAND_NUM_EVENTS = 3
4848

0 commit comments

Comments
 (0)