Files
silo-calc/pythonpath/silo_calc/project_files.py
Zoe Forbes 13b56fd1b0 initial: LibreOffice Calc Silo extension (extracted from silo monorepo)
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
2026-02-06 11:24:13 -06:00

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