webstation-broker
DeveloperPython reference

saves

Save data in and out of the emulator's save directories.

Save data in and out of the emulator's save directories.

Activate restores a zip archive into the emulator's save directories; exit zips every save file modified since launch.

attributelog
= logging.getLogger(__name__)
attributeSAVE_FILE_MAX_BYTES
= int(os.environ.get('SAVE_FILE_MAX_BYTES', str(256 * 1024 * 1024)))

Env-tunable guard against runaway dumps, from SAVE_FILE_MAX_BYTES (default 256 MiB).

func_iter_save_files(root, subtrees) -> list[Path]

List every regular file under the allowed subtrees.

Sorted so identical content zips to identical bytes. Dot-prefixed components are staging or tmp entries and never ship, and symlinks are skipped.

paramrootPath

The emulator's save data root.

paramsubtreestuple[str, ...]

Subdirectory names under root that hold save data.

Returns

list

The files found, in sorted order.

func_read_file_stable(p, retries=4, settle=0.5) -> Optional[tuple[bytes, float]]

Read p only when size and mtime match before and after the read.

This is what keeps a file the emulator is mid-writing from ever being shipped torn.

parampPath

The file to read.

paramretriesint
= 4

How many reads to attempt before giving up.

paramsettlefloat
= 0.5

Seconds to wait between attempts.

Returns

typing.Optional

The file contents and its mtime, or None when the file could not be

funcbuild_save_archive(root, subtrees, baseline) -> dict[str, Any]

Zip every save file modified since baseline (the launch timestamp).

Member paths are relative to root and mtimes are stored in UTC on both sides, so a timezone difference between the dump and a later restore never shifts them past the newer-file guard.

paramrootPath

The emulator's save data root.

paramsubtreestuple[str, ...]

Subdirectory names under root that hold save data.

parambaselinefloat

Unix timestamp; files with an mtime at or after it are included.

Returns

dict

A report dict of the shape

func_under(member, subtrees) -> bool

Whether an archive member path lies inside one of the given subtrees.

parammemberPurePosixPath

The member path, relative to the save data root.

paramsubtreestuple[str, ...]

Subdirectory names to test against.

Returns

bool

True when member starts with one of the subtrees followed by a slash.

funcextract_save_archive(content, root, subtrees, excluded=()) -> dict[str, Any]

Restore an archive into the emulator's data dir.

excluded names subtrees the emulator owns but this session syncs some other way. Those members are dropped rather than refused: archives taken before that sync was turned on still carry them, and restoring one would undo what the other route just wrote. A member under neither is still a hard error, since that is the guard against an archive writing outside the save area.

Existing files newer than their archive member are skipped so a restore can never roll back saves made since the archive was taken. Each file is written through a temp file and renamed into place.

paramcontentbytes

The zip archive body.

paramrootPath

The emulator's save data root.

paramsubtreestuple[str, ...]

Subdirectory names under root that members may be restored into.

paramexcludedtuple[str, ...]
= ()

Subdirectory names whose members are counted and dropped.

Returns

dict

A dict of the shape {"written", "skipped", "excluded", "failed", "error"}

funcwrite_export(zip_bytes, name) -> str

Persist a dump archive under settings.EXPORT_DIR for inspection.

paramzip_bytesbytes

The archive body.

paramnamestr

The filename to write it as.

Returns

str

The path written, as a string.

funcwrite_import(zip_bytes, name) -> str

Persist an archive the parent uploaded for restore under settings.IMPORT_DIR.

Written through a temp file and renamed so a half-received upload can never be handed to activate as a restore source.

paramzip_bytesbytes

The archive body.

paramnamestr

The filename to write it as.

Returns

str

The path written, as a string.