LibreOffice Calc extension for Silo PLM integration. Uses shared silo-client package (submodule) for API communication. Changes from monorepo version: - SiloClient class removed from client.py, replaced with CalcSiloSettings adapter + factory function wrapping silo_client.SiloClient - silo_calc_component.py adds silo-client to sys.path - Makefile build-oxt copies silo_client into .oxt for self-contained packaging - All other modules unchanged
77 lines
2.2 KiB
Python
77 lines
2.2 KiB
Python
"""Local project file management for ODS workbooks.
|
|
|
|
Mirrors the FreeCAD file path pattern from ``pkg/freecad/silo_commands.py``.
|
|
Project ODS files live at::
|
|
|
|
~/projects/sheets/{PROJECT_CODE}/{PROJECT_CODE}.ods
|
|
|
|
The ``SILO_PROJECTS_DIR`` env var (shared with the FreeCAD workbench)
|
|
controls the base directory.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from . import settings as _settings
|
|
|
|
|
|
def get_sheets_dir() -> Path:
|
|
"""Return the base directory for ODS project sheets."""
|
|
return _settings.get_projects_dir() / "sheets"
|
|
|
|
|
|
def get_project_sheet_path(project_code: str) -> Path:
|
|
"""Canonical path for a project workbook.
|
|
|
|
Example: ``~/projects/sheets/3DX10/3DX10.ods``
|
|
"""
|
|
return get_sheets_dir() / project_code / f"{project_code}.ods"
|
|
|
|
|
|
def ensure_project_dir(project_code: str) -> Path:
|
|
"""Create the project sheet directory if needed and return its path."""
|
|
d = get_sheets_dir() / project_code
|
|
d.mkdir(parents=True, exist_ok=True)
|
|
return d
|
|
|
|
|
|
def project_sheet_exists(project_code: str) -> bool:
|
|
"""Check whether a project workbook already exists locally."""
|
|
return get_project_sheet_path(project_code).is_file()
|
|
|
|
|
|
def save_project_sheet(project_code: str, ods_bytes: bytes) -> Path:
|
|
"""Write ODS bytes to the canonical project path.
|
|
|
|
Returns the Path written to.
|
|
"""
|
|
ensure_project_dir(project_code)
|
|
path = get_project_sheet_path(project_code)
|
|
with open(path, "wb") as f:
|
|
f.write(ods_bytes)
|
|
return path
|
|
|
|
|
|
def read_project_sheet(project_code: str) -> Optional[bytes]:
|
|
"""Read ODS bytes from the canonical project path, or None."""
|
|
path = get_project_sheet_path(project_code)
|
|
if not path.is_file():
|
|
return None
|
|
with open(path, "rb") as f:
|
|
return f.read()
|
|
|
|
|
|
def list_project_sheets() -> list:
|
|
"""Return a list of (project_code, path) tuples for all local sheets."""
|
|
sheets_dir = get_sheets_dir()
|
|
results = []
|
|
if not sheets_dir.is_dir():
|
|
return results
|
|
for entry in sorted(sheets_dir.iterdir()):
|
|
if entry.is_dir():
|
|
ods = entry / f"{entry.name}.ods"
|
|
if ods.is_file():
|
|
results.append((entry.name, ods))
|
|
return results
|