mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-27 02:28:22 +03:00
fix logger and env vars config section saving
use escaped periods in keys to retain them in the config file (eg "frigate.embeddings")
This commit is contained in:
parent
cb231ffa66
commit
2ae972c068
@ -195,7 +195,8 @@ def flatten_config_data(
|
|||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
items = []
|
items = []
|
||||||
for key, value in config_data.items():
|
for key, value in config_data.items():
|
||||||
new_key = f"{parent_key}.{key}" if parent_key else key
|
escaped_key = escape_config_key_segment(str(key))
|
||||||
|
new_key = f"{parent_key}.{escaped_key}" if parent_key else escaped_key
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
items.extend(flatten_config_data(value, new_key).items())
|
items.extend(flatten_config_data(value, new_key).items())
|
||||||
else:
|
else:
|
||||||
@ -203,6 +204,41 @@ def flatten_config_data(
|
|||||||
return dict(items)
|
return dict(items)
|
||||||
|
|
||||||
|
|
||||||
|
def escape_config_key_segment(segment: str) -> str:
|
||||||
|
"""Escape dots and backslashes so they can be treated as literal key chars."""
|
||||||
|
return segment.replace("\\", "\\\\").replace(".", "\\.")
|
||||||
|
|
||||||
|
|
||||||
|
def split_config_key_path(key_path_str: str) -> list[str]:
|
||||||
|
"""Split a dotted config path, honoring \\. as a literal dot in a key."""
|
||||||
|
parts: list[str] = []
|
||||||
|
current: list[str] = []
|
||||||
|
escaped = False
|
||||||
|
|
||||||
|
for char in key_path_str:
|
||||||
|
if escaped:
|
||||||
|
current.append(char)
|
||||||
|
escaped = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
if char == "\\":
|
||||||
|
escaped = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
if char == ".":
|
||||||
|
parts.append("".join(current))
|
||||||
|
current = []
|
||||||
|
continue
|
||||||
|
|
||||||
|
current.append(char)
|
||||||
|
|
||||||
|
if escaped:
|
||||||
|
current.append("\\")
|
||||||
|
|
||||||
|
parts.append("".join(current))
|
||||||
|
return parts
|
||||||
|
|
||||||
|
|
||||||
def update_yaml_file_bulk(file_path: str, updates: Dict[str, Any]):
|
def update_yaml_file_bulk(file_path: str, updates: Dict[str, Any]):
|
||||||
yaml = YAML()
|
yaml = YAML()
|
||||||
yaml.indent(mapping=2, sequence=4, offset=2)
|
yaml.indent(mapping=2, sequence=4, offset=2)
|
||||||
@ -218,7 +254,7 @@ def update_yaml_file_bulk(file_path: str, updates: Dict[str, Any]):
|
|||||||
|
|
||||||
# Apply all updates
|
# Apply all updates
|
||||||
for key_path_str, new_value in updates.items():
|
for key_path_str, new_value in updates.items():
|
||||||
key_path = key_path_str.split(".")
|
key_path = split_config_key_path(key_path_str)
|
||||||
for i in range(len(key_path)):
|
for i in range(len(key_path)):
|
||||||
try:
|
try:
|
||||||
index = int(key_path[i])
|
index = int(key_path[i])
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
import { RJSFSchema } from "@rjsf/utils";
|
import { RJSFSchema } from "@rjsf/utils";
|
||||||
import { applySchemaDefaults } from "@/lib/config-schema";
|
import { applySchemaDefaults } from "@/lib/config-schema";
|
||||||
import { isJsonObject } from "@/lib/utils";
|
import { isJsonObject } from "@/lib/utils";
|
||||||
import { JsonObject } from "@/types/configForm";
|
import { JsonObject, JsonValue } from "@/types/configForm";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sections that require special handling at the global level.
|
* Sections that require special handling at the global level.
|
||||||
@ -146,6 +146,22 @@ export function sanitizeOverridesForSection(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const flattenRecordWithDots = (
|
||||||
|
value: JsonObject,
|
||||||
|
prefix: string = "",
|
||||||
|
): JsonObject => {
|
||||||
|
const flattened: JsonObject = {};
|
||||||
|
Object.entries(value).forEach(([key, entry]) => {
|
||||||
|
const nextKey = prefix ? `${prefix}.${key}` : key;
|
||||||
|
if (isJsonObject(entry)) {
|
||||||
|
Object.assign(flattened, flattenRecordWithDots(entry, nextKey));
|
||||||
|
} else {
|
||||||
|
flattened[nextKey] = entry as JsonValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return flattened;
|
||||||
|
};
|
||||||
|
|
||||||
// detectors: Strip readonly model fields that are generated on startup
|
// detectors: Strip readonly model fields that are generated on startup
|
||||||
// and should never be persisted back to the config file.
|
// and should never be persisted back to the config file.
|
||||||
if (sectionPath === "detectors") {
|
if (sectionPath === "detectors") {
|
||||||
@ -167,5 +183,21 @@ export function sanitizeOverridesForSection(
|
|||||||
return cleaned;
|
return cleaned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sectionPath === "logger") {
|
||||||
|
const overridesObj = overrides as JsonObject;
|
||||||
|
const logs = overridesObj.logs;
|
||||||
|
if (isJsonObject(logs)) {
|
||||||
|
return {
|
||||||
|
...overridesObj,
|
||||||
|
logs: flattenRecordWithDots(logs),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectionPath === "environment_vars") {
|
||||||
|
const overridesObj = overrides as JsonObject;
|
||||||
|
return flattenRecordWithDots(overridesObj);
|
||||||
|
}
|
||||||
|
|
||||||
return overrides;
|
return overrides;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user