git fixec null symbol
This commit is contained in:
@@ -8,11 +8,22 @@ from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def sanitize_text(value: str | None) -> str:
|
||||
"""Remove NUL bytes — PostgreSQL text fields reject them; SchDoc may contain them."""
|
||||
if not value:
|
||||
return ""
|
||||
return value.replace("\x00", "")
|
||||
|
||||
|
||||
@dataclass
|
||||
class ComponentProperty:
|
||||
name: str
|
||||
text: str
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.name = sanitize_text(self.name)
|
||||
self.text = sanitize_text(self.text)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DielProperty:
|
||||
@@ -22,6 +33,10 @@ class DielProperty:
|
||||
diel_type: int
|
||||
layer_number: int
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.name = sanitize_text(self.name)
|
||||
self.value = sanitize_text(self.value)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ProjectData:
|
||||
@@ -342,6 +357,7 @@ class AltiumParser:
|
||||
|
||||
|
||||
def make_complex_string(text: str, props: list[ComponentProperty]) -> str:
|
||||
text = sanitize_text(text)
|
||||
if not text.startswith("="):
|
||||
return text
|
||||
expr = text[1:]
|
||||
@@ -351,7 +367,7 @@ def make_complex_string(text: str, props: list[ComponentProperty]) -> str:
|
||||
key = m.group(1)
|
||||
return mapping.get(key, "")
|
||||
|
||||
return re.sub(r"['\"]([^'\"]+)['\"]", repl, expr)
|
||||
return sanitize_text(re.sub(r"['\"]([^'\"]+)['\"]", repl, expr))
|
||||
|
||||
|
||||
def find_prjpcb(extract_dir: Path) -> Optional[Path]:
|
||||
|
||||
@@ -20,7 +20,7 @@ from app.models import (
|
||||
Variant,
|
||||
VariantProperty,
|
||||
)
|
||||
from app.services.altium_parser import AltiumParser, ProjectData, find_prjpcb, make_complex_string
|
||||
from app.services.altium_parser import AltiumParser, ProjectData, find_prjpcb, make_complex_string, sanitize_text
|
||||
from app.services.designators import DEFAULT_MAPPINGS
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ def ensure_default_mappings(db: Session, project: Project) -> None:
|
||||
def save_project_data(db: Session, project: Project, data: ProjectData) -> None:
|
||||
variant_objs: list[Variant] = []
|
||||
for name in data.variant_names:
|
||||
v = Variant(project_id=project.id, name=name)
|
||||
v = Variant(project_id=project.id, name=sanitize_text(name))
|
||||
db.add(v)
|
||||
variant_objs.append(v)
|
||||
db.flush()
|
||||
@@ -95,7 +95,7 @@ def save_project_data(db: Session, project: Project, data: ProjectData) -> None:
|
||||
designator = ""
|
||||
for p in comp_props:
|
||||
if p.name.lower() == "designator":
|
||||
designator = p.text
|
||||
designator = sanitize_text(p.text)
|
||||
break
|
||||
if not designator:
|
||||
continue
|
||||
@@ -105,7 +105,13 @@ def save_project_data(db: Session, project: Project, data: ProjectData) -> None:
|
||||
db.add(comp)
|
||||
db.flush()
|
||||
for p in comp_props:
|
||||
db.add(ComponentProperty(component_id=comp.id, key=p.name, value=p.text))
|
||||
db.add(
|
||||
ComponentProperty(
|
||||
component_id=comp.id,
|
||||
key=sanitize_text(p.name),
|
||||
value=sanitize_text(p.text),
|
||||
)
|
||||
)
|
||||
designator_to_component[designator] = comp
|
||||
# link to all variants as fitted by default
|
||||
for v in variant_objs:
|
||||
@@ -126,7 +132,7 @@ def save_project_data(db: Session, project: Project, data: ProjectData) -> None:
|
||||
designator = ""
|
||||
for p in comp_props:
|
||||
if p.name == "Designator":
|
||||
designator = p.text
|
||||
designator = sanitize_text(p.text)
|
||||
break
|
||||
if not designator:
|
||||
continue
|
||||
@@ -149,8 +155,8 @@ def save_project_data(db: Session, project: Project, data: ProjectData) -> None:
|
||||
VariantProperty(
|
||||
component_id=comp.id,
|
||||
variant_id=variant.id,
|
||||
key=p.name,
|
||||
value=p.text,
|
||||
key=sanitize_text(p.name),
|
||||
value=sanitize_text(p.text),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -159,16 +165,18 @@ def save_project_data(db: Session, project: Project, data: ProjectData) -> None:
|
||||
for item in params:
|
||||
if len(item) < 2:
|
||||
continue
|
||||
name, value = item[0], item[1]
|
||||
value = make_complex_string(value, flat_props)
|
||||
name, value = sanitize_text(item[0]), sanitize_text(item[1])
|
||||
value = sanitize_text(make_complex_string(value, flat_props))
|
||||
db.add(
|
||||
ProjectParam(
|
||||
project_id=project.id,
|
||||
name=name,
|
||||
value=value,
|
||||
variant_name=data.variant_names[variant_idx]
|
||||
variant_name=sanitize_text(
|
||||
data.variant_names[variant_idx]
|
||||
if variant_idx < len(data.variant_names)
|
||||
else "",
|
||||
else ""
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -181,15 +189,16 @@ def save_project_data(db: Session, project: Project, data: ProjectData) -> None:
|
||||
db.add(
|
||||
DielMaterial(
|
||||
pcb_data_id=pcb.id,
|
||||
name=m.name,
|
||||
value=m.value,
|
||||
name=sanitize_text(m.name),
|
||||
value=sanitize_text(m.value),
|
||||
height=m.height,
|
||||
diel_type=m.diel_type,
|
||||
layer_number=m.layer_number,
|
||||
)
|
||||
)
|
||||
|
||||
project.pcb_doc_name = Path(data.pcb_doc_file_name).name if data.pcb_doc_file_name else None
|
||||
pcb_name = sanitize_text(Path(data.pcb_doc_file_name).name if data.pcb_doc_file_name else "")
|
||||
project.pcb_doc_name = pcb_name or None
|
||||
if "No Variations" in data.variant_names:
|
||||
project.current_variant = "No Variations"
|
||||
elif data.variant_names:
|
||||
@@ -247,10 +256,13 @@ def ingest_zip(
|
||||
db.refresh(project)
|
||||
return project
|
||||
except Exception as e:
|
||||
project.status = "error"
|
||||
project.error_message = str(e)
|
||||
db.rollback()
|
||||
proj = db.get(Project, project.id)
|
||||
if proj:
|
||||
proj.status = "error"
|
||||
proj.error_message = str(e)[:2000]
|
||||
db.commit()
|
||||
raise
|
||||
raise ValueError(str(e)) from e
|
||||
|
||||
|
||||
def get_project_full(db: Session, project_id: int) -> Project | None:
|
||||
|
||||
Reference in New Issue
Block a user