fix(codex): sync codex_patcher.py with TOML inline-table fix
Mirrors claude_code_patcher@661eced — fixes Windows ucodex_install.ps1 crash 'Error loading config.toml: missing assignment' caused by toml_value(dict) emitting Python str(dict) instead of TOML syntax. Existing broken installs: re-run installer or manually delete the bad section from ~/.codex/config.toml then re-run ucodex_install. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -221,25 +221,56 @@ def read_toml_raw(path):
|
|||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def _toml_str(s):
|
||||||
|
"""Escape a Python string as a TOML basic-string literal.
|
||||||
|
|
||||||
|
Backslashes (Windows paths!) and double-quotes must be escaped per
|
||||||
|
TOML spec — otherwise the parser sees `C:\\Windows` as `C:Windows`
|
||||||
|
or fails with `Unescaped '\\' in a string`.
|
||||||
|
"""
|
||||||
|
escaped = s.replace("\\", "\\\\").replace('"', '\\"')
|
||||||
|
return f'"{escaped}"'
|
||||||
|
|
||||||
|
|
||||||
def toml_value(v):
|
def toml_value(v):
|
||||||
"""Format a Python value as TOML."""
|
"""Format a Python value as TOML.
|
||||||
|
|
||||||
|
Dicts → inline table `{ key = "val", k2 = "v2" }` (NOT Python str(dict)
|
||||||
|
which uses single quotes + colons and breaks `tomllib.load`).
|
||||||
|
Strings → basic-string with backslash/quote escapes (Windows paths).
|
||||||
|
"""
|
||||||
if isinstance(v, bool):
|
if isinstance(v, bool):
|
||||||
return "true" if v else "false"
|
return "true" if v else "false"
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
return f'"{v}"'
|
return _toml_str(v)
|
||||||
if isinstance(v, (int, float)):
|
if isinstance(v, (int, float)):
|
||||||
return str(v)
|
return str(v)
|
||||||
if isinstance(v, list):
|
if isinstance(v, list):
|
||||||
items = ", ".join(toml_value(i) for i in v)
|
items = ", ".join(toml_value(i) for i in v)
|
||||||
return f"[{items}]"
|
return f"[{items}]"
|
||||||
return str(v)
|
if isinstance(v, dict):
|
||||||
|
# TOML inline table: keys may need quoting (special chars / dots),
|
||||||
|
# values recurse through toml_value.
|
||||||
|
items = ", ".join(
|
||||||
|
f"{toml_key(k)} = {toml_value(val)}" for k, val in v.items()
|
||||||
|
)
|
||||||
|
return f"{{ {items} }}" if items else "{}"
|
||||||
|
return _toml_str(str(v))
|
||||||
|
|
||||||
|
|
||||||
def toml_key(k):
|
def toml_key(k):
|
||||||
"""Format a TOML key, quoting if it contains dots or special chars."""
|
"""Format a TOML key, quoting if it contains anything other than the
|
||||||
if "." in k or " " in k:
|
bare-key charset (A-Z a-z 0-9 _ -). Examples that MUST be quoted:
|
||||||
return f'"{k}"'
|
"PROGRAMFILES(X86)" — parens
|
||||||
|
"key.with.dots" — would parse as nested
|
||||||
|
"key with spaces"
|
||||||
|
"""
|
||||||
|
import re as _re
|
||||||
|
if _re.fullmatch(r"[A-Za-z0-9_-]+", k):
|
||||||
return k
|
return k
|
||||||
|
# Quote, escape backslashes and quotes
|
||||||
|
escaped = k.replace("\\", "\\\\").replace('"', '\\"')
|
||||||
|
return f'"{escaped}"'
|
||||||
|
|
||||||
|
|
||||||
def generate_config_toml(existing, config, home_dir=None):
|
def generate_config_toml(existing, config, home_dir=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user