72 lines
2.8 KiB
Python
72 lines
2.8 KiB
Python
"""
|
|
FileRecord: one row per file under review. Both the GUI and the batch/
|
|
spreadsheet front end read and write the same fields, so nothing about
|
|
a file's state is front-end-specific.
|
|
|
|
Every editable field defaults to "no change" (current filename, current
|
|
folder) when a record is first created — so a file you never touch in
|
|
review simply stays exactly as it is. Nothing is lost by omission.
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
from typing import List
|
|
|
|
|
|
@dataclass
|
|
class FileRecord:
|
|
path: Path # current absolute path on disk
|
|
root: Path # vault root this file was scanned under
|
|
filename: str = "" # current filename, including extension
|
|
ext: str = ""
|
|
fs_date: str = "" # best-guess filesystem date — a starting
|
|
# point only, never treated as authoritative
|
|
name_matches_convention: bool = False
|
|
near_miss: bool = False # matched a "close but not quite" date format
|
|
|
|
# --- Editable fields ---
|
|
date_override: str = "" # what actually goes in the filename
|
|
topic: str = ""
|
|
subtopic: str = ""
|
|
extra: str = ""
|
|
more: str = ""
|
|
version: str = ""
|
|
dest_folder: str = "" # relative to root
|
|
keep_filename: bool = False # if True, move only — never rebuild the name.
|
|
# Defaults to True for files that already match
|
|
# the convention, so opening one to move it
|
|
# doesn't blank out a name that was already fine.
|
|
|
|
suggested_folders: List[str] = field(default_factory=list)
|
|
|
|
# pending -> not yet reviewed | confirmed -> ready for apply_batch
|
|
# skip -> deliberately left alone | done -> already applied
|
|
status: str = "pending"
|
|
|
|
@property
|
|
def identity(self) -> str:
|
|
"""Stable across rename/move — see core.identity. Use this, not
|
|
rel_path, as the key for anything that needs to survive a file
|
|
actually being moved (e.g. resuming progress across sessions)."""
|
|
from .identity import file_identity
|
|
return file_identity(self.path)
|
|
|
|
@property
|
|
def rel_path(self) -> str:
|
|
return str(self.path.relative_to(self.root))
|
|
|
|
@property
|
|
def current_folder(self) -> str:
|
|
return str(self.path.parent.relative_to(self.root))
|
|
|
|
@property
|
|
def new_filename_preview(self) -> str:
|
|
if self.keep_filename:
|
|
return self.filename
|
|
from .sanitiser import build_filename
|
|
return build_filename(
|
|
date=self.date_override or self.fs_date,
|
|
topic=self.topic, subtopic=self.subtopic,
|
|
extra=self.extra, more=self.more, version=self.version,
|
|
ext=self.ext,
|
|
)
|