Skip to content

capturegraph.data.load.manifest #

Procedure Manifest Data Classes#

Data structures for parsing and representing the capture_target_manifest.json file that defines the structure and types of data captured by a CaptureGraph procedure.

The manifest is a recursive structure where: - files: Named single files with a type and extensions - file_sequences: Named arrays of numbered files (e.g., sequence_0.dng, sequence_1.dng) - directories: Nested subdirectories with their own manifest - sessions: Timestamped subdirectories (e.g., hex timestamps) with shared manifest

JSONDataClassMixin dataclass #

Mixin providing JSON serialization for dataclasses.

Source code in capturegraph-lib/capturegraph/data/load/manifest.py
@dataclass
class JSONDataClassMixin:
    """Mixin providing JSON serialization for dataclasses."""

    def to_json(self) -> str:
        """Serialize to JSON string."""
        return json.dumps(asdict(self), indent=4)

    @classmethod
    def from_json(cls, json_str: str):
        """Deserialize from JSON string."""
        data = json.loads(json_str)
        return from_dict(data_class=cls, data=data, config=Config(check_types=False))

    @classmethod
    def from_file(cls, path: Union[str, Path]):
        """Load from a JSON file."""
        path = Path(path)
        with open(path, "r") as f:
            return cls.from_json(f.read())

to_json() #

Serialize to JSON string.

Source code in capturegraph-lib/capturegraph/data/load/manifest.py
def to_json(self) -> str:
    """Serialize to JSON string."""
    return json.dumps(asdict(self), indent=4)

from_json(json_str) classmethod #

Deserialize from JSON string.

Source code in capturegraph-lib/capturegraph/data/load/manifest.py
@classmethod
def from_json(cls, json_str: str):
    """Deserialize from JSON string."""
    data = json.loads(json_str)
    return from_dict(data_class=cls, data=data, config=Config(check_types=False))

from_file(path) classmethod #

Load from a JSON file.

Source code in capturegraph-lib/capturegraph/data/load/manifest.py
@classmethod
def from_file(cls, path: Union[str, Path]):
    """Load from a JSON file."""
    path = Path(path)
    with open(path, "r") as f:
        return cls.from_json(f.read())

FileManifest dataclass #

Bases: JSONDataClassMixin

Manifest entry for a single file or file sequence.

Attributes:

Name Type Description
type_name str

The PType name (e.g., 'PBool', 'PImage', 'PUserID')

file_extensions list[str]

List of possible file extensions (e.g., ['heic', 'dng', 'jpeg'])

Source code in capturegraph-lib/capturegraph/data/load/manifest.py
@dataclass
class FileManifest(JSONDataClassMixin):
    """Manifest entry for a single file or file sequence.

    Attributes:
        type_name: The PType name (e.g., 'PBool', 'PImage', 'PUserID')
        file_extensions: List of possible file extensions (e.g., ['heic', 'dng', 'jpeg'])
    """

    type_name: str
    file_extensions: list[str]

ProcedureManifest dataclass #

Bases: JSONDataClassMixin

Complete manifest defining the structure of a capture target directory.

This is a recursive structure that can describe arbitrarily nested directories.

Attributes:

Name Type Description
files dict[str, FileManifest]

Map of filename -> FileManifest for single files

file_sequences dict[str, FileManifest]

Map of sequence name -> FileManifest for numbered file sequences

directories dict[str, ProcedureManifest]

Map of directory name -> ProcedureManifest for nested directories

sessions dict[str, ProcedureManifest]

Map of session container name -> ProcedureManifest for timestamped sessions

Example manifest structure

{ "files": {"reference": {"type_name": "PImage", "file_extensions": ["heic"]}}, "sessions": { "captures": { "files": {"photo": {"type_name": "PImage", "file_extensions": ["heic"]}} } } }

Source code in capturegraph-lib/capturegraph/data/load/manifest.py
@dataclass
class ProcedureManifest(JSONDataClassMixin):
    """Complete manifest defining the structure of a capture target directory.

    This is a recursive structure that can describe arbitrarily nested directories.

    Attributes:
        files: Map of filename -> FileManifest for single files
        file_sequences: Map of sequence name -> FileManifest for numbered file sequences
        directories: Map of directory name -> ProcedureManifest for nested directories
        sessions: Map of session container name -> ProcedureManifest for timestamped sessions

    Example manifest structure:
        {
            "files": {"reference": {"type_name": "PImage", "file_extensions": ["heic"]}},
            "sessions": {
                "captures": {
                    "files": {"photo": {"type_name": "PImage", "file_extensions": ["heic"]}}
                }
            }
        }
    """

    files: dict[str, FileManifest] = field(default_factory=lambda: {})

    file_sequences: dict[str, FileManifest] = field(default_factory=lambda: {})

    directories: dict[str, "ProcedureManifest"] = field(
        default_factory=lambda: defaultdict(lambda: ProcedureManifest())
    )

    sessions: dict[str, "ProcedureManifest"] = field(
        default_factory=lambda: defaultdict(lambda: ProcedureManifest())
    )

    def __post_init__(self):
        """Convert deserialized dicts to defaultdicts for auto-creating behavior."""
        self.directories = defaultdict(
            lambda: ProcedureManifest(),
            dict(self.directories),
        )

        self.sessions = defaultdict(
            lambda: ProcedureManifest(),
            dict(self.sessions),
        )

__post_init__() #

Convert deserialized dicts to defaultdicts for auto-creating behavior.

Source code in capturegraph-lib/capturegraph/data/load/manifest.py
def __post_init__(self):
    """Convert deserialized dicts to defaultdicts for auto-creating behavior."""
    self.directories = defaultdict(
        lambda: ProcedureManifest(),
        dict(self.directories),
    )

    self.sessions = defaultdict(
        lambda: ProcedureManifest(),
        dict(self.sessions),
    )