archivebox.core.models

Module Contents

Classes

UngroupedSubquery

Scalar subquery that should not be copied into the outer GROUP BY.

Tag

SnapshotTag

SnapshotQuerySet

Custom QuerySet for Snapshot model with export methods that persist through .filter() etc.

SnapshotManager

Manager for Snapshot model - uses SnapshotQuerySet for chainable methods

Snapshot

ArchiveResult

API

exception archivebox.core.models.SnapshotMigrationError[source]

Bases: RuntimeError

Raised when a snapshot filesystem migration fails validation.

Initialization

Initialize self. See help(type(self)) for accurate signature.

class archivebox.core.models.UngroupedSubquery[source]

Bases: django.db.models.Subquery

Scalar subquery that should not be copied into the outer GROUP BY.

get_group_by_cols()[source]
class archivebox.core.models.Tag[source]

Bases: archivebox.base_models.models.ModelWithUUID

id[source]

‘AutoField(…)’

created_by[source]

‘ForeignKey(…)’

created_at[source]

‘DateTimeField(…)’

modified_at[source]

‘DateTimeField(…)’

name[source]

‘CharField(…)’

classmethod get_or_create_by_name(name: str, *, defaults: collections.abc.Mapping[str, Any] | None = None) tuple[archivebox.core.models.Tag, bool][source]
snapshot_set: django.db.models.Manager[Snapshot][source]

None

class Meta[source]

Bases: archivebox.base_models.models.ModelWithUUID.Meta

app_label[source]

‘core’

verbose_name[source]

‘Tag’

verbose_name_plural[source]

‘Tags’

__str__()[source]
save(*args, **kwargs)[source]
property slug: str[source]

ASCII-safe slugified form of the tag name (derived, not stored).

property api_url: str[source]
to_json() dict[source]

Convert Tag model instance to a JSON-serializable dict.

static from_json(record: dict[str, Any], overrides: dict[str, Any] | None = None)[source]

Create/update Tag from JSON dict.

Args: record: JSON dict with ‘name’ field overrides: Optional dict with ‘snapshot’ to auto-attach tag

Returns: Tag instance or None

class archivebox.core.models.SnapshotTag[source]

Bases: django.db.models.Model

id[source]

‘AutoField(…)’

snapshot[source]

‘ForeignKey(…)’

tag[source]

‘ForeignKey(…)’

class Meta[source]
app_label[source]

‘core’

db_table[source]

‘core_snapshot_tags’

unique_together: ClassVar[list[tuple[str, str]]][source]

[(‘snapshot’, ‘tag’)]

class archivebox.core.models.SnapshotQuerySet[source]

Bases: django.db.models.QuerySet

Custom QuerySet for Snapshot model with export methods that persist through .filter() etc.

bulk_create(objs, *args, **kwargs)[source]
paged_iterator(chunk_size: int = 500)[source]

Iterate snapshots using bounded keyset pages instead of one streaming cursor.

Django’s iterator(chunk_size=…) still keeps a single SQLite SELECT cursor open until the full queryset is exhausted. That is fine for read-only exports, but update/migration code does filesystem work and writes while iterating; a long-lived read cursor there can stretch lock waits across thousands of rows. This respects the queryset’s existing filters, order_by(), select_related(), and prefetch_related() state; if no ordering is defined, it falls back to primary-key order.

FILTER_TYPES: ClassVar[dict[str, Any]][source]

None

FILTER_TYPE_CHOICES[source]

‘tuple(…)’

FILTER_ARG_KEYS[source]

(‘after’, ‘before’, ‘filter_type’, ‘filter_patterns’, ‘status’, ‘url__icontains’, ‘url__istartswith’…

SPECIAL_FILTER_ARG_KEYS[source]

‘frozenset(…)’

filter_by_patterns(patterns: list[str], filter_type: str = 'exact') archivebox.core.models.SnapshotQuerySet[source]

Filter snapshots by URL patterns using specified filter type

search(**kwargs) archivebox.core.models.SnapshotQuerySet[source]
to_json(with_headers: bool = False) str[source]

Generate JSON index from snapshots

to_csv(cols: list[str] | None = None, header: bool = True, separator: str = ',', ljust: int = 0) str[source]

Generate CSV output from snapshots

to_html(with_headers: bool = True) str[source]

Generate main index HTML from snapshots

class archivebox.core.models.SnapshotManager[source]

Bases: models.Manager.from_queryset(SnapshotQuerySet)

Manager for Snapshot model - uses SnapshotQuerySet for chainable methods

filter(*args, **kwargs)[source]
get_queryset()[source]
remove(atomic: bool = False) tuple[source]

Remove snapshots from the database

class archivebox.core.models.Snapshot[source]

Bases: archivebox.base_models.models.ModelWithDeleteAfter, archivebox.base_models.models.ModelWithOutputDir, archivebox.base_models.models.ModelWithConfig, archivebox.base_models.models.ModelWithNotes, archivebox.base_models.models.ModelWithHealthStats, archivebox.workers.models.ModelWithQueue

BROWSER_EXTENSION_UPLOAD_HOOK_NAME[source]

‘on_Snapshot__archivebox_browser_extension_upload’

id[source]

‘CompactUUIDField(…)’

created_at[source]

‘DateTimeField(…)’

modified_at[source]

‘DateTimeField(…)’

url[source]

‘TextField(…)’

timestamp[source]

‘CharField(…)’

bookmarked_at[source]

‘DateTimeField(…)’

crawl: archivebox.crawls.models.Crawl[source]

‘ForeignKey(…)’

parent_snapshot[source]

‘ForeignKey(…)’

title[source]

‘CharField(…)’

downloaded_at[source]

‘DateTimeField(…)’

depth[source]

‘PositiveSmallIntegerField(…)’

fs_version[source]

‘CharField(…)’

retry_at[source]

‘RetryAtField(…)’

status[source]

‘StatusField(…)’

config[source]

‘JSONField(…)’

permissions[source]

‘GeneratedField(…)’

output_size[source]

‘BigIntegerField(…)’

notes[source]

‘TextField(…)’

tags[source]

‘ManyToManyField(…)’

state_field_name[source]

‘status’

retry_at_field_name[source]

‘retry_at’

StatusChoices[source]

None

INITIAL_STATE[source]

None

ACTIVE_STATE[source]

None

FINAL_STATES[source]

()

FINAL_OR_ACTIVE_STATES[source]

()

active_state[source]

None

delete_after_final_statuses[source]

()

RUNNABLE_STATES[source]

()

OPEN_STATES[source]

()

crawl_id: uuid.UUID[source]

None

parent_snapshot_id: uuid.UUID | None[source]

None

_prefetched_objects_cache: dict[str, Any][source]

None

objects[source]

‘SnapshotManager(…)’

archiveresult_set: django.db.models.Manager[ArchiveResult][source]

None

add_tag_ids(tag_ids: collections.abc.Iterable[int | str]) None[source]
remove_tag_ids(tag_ids: collections.abc.Iterable[int | str]) int[source]
class Meta[source]

Bases: archivebox.base_models.models.ModelWithDeleteAfter.Meta, archivebox.base_models.models.ModelWithOutputDir.Meta, archivebox.base_models.models.ModelWithConfig.Meta, archivebox.base_models.models.ModelWithNotes.Meta, archivebox.base_models.models.ModelWithHealthStats.Meta, archivebox.workers.models.ModelWithQueue.Meta

app_label[source]

‘core’

verbose_name[source]

‘Snapshot’

verbose_name_plural[source]

‘Snapshots’

indexes: ClassVar[list[django.db.models.Index]][source]

None

constraints: ClassVar[list[django.db.models.BaseConstraint]][source]

None

__str__()[source]
classmethod crawl_count_subquery(*, status: str | None = None, outer_ref: str = 'pk') django.db.models.QuerySet[source]

Return a scalar subquery counting Snapshots for one outer Crawl.

classmethod crawl_count_expr(*, status: str | None = None, outer_ref: str = 'pk')[source]
classmethod crawl_total_and_status_counts(crawl_ids: collections.abc.Iterable[Any], *, status: str) dict[str, dict[str, int]][source]

Return total and status-filtered Snapshot counts keyed by Crawl ID.

update_and_requeue(**kwargs) bool[source]

Update this Snapshot through the shared retry_at ownership path.

Any non-final Snapshot work means the parent Crawl must also be visible to the runner. Keep that invariant here so CLI/admin callers do not hand-edit the parent Crawl state every time they retry a hook.

queue_for_extraction(*, when=None) bool[source]

Queue this Snapshot for the runner using the normal state path.

schedule_plugin_run(plugins: collections.abc.Iterable[str], *, when=None) bool[source]

Persist one snapshot-scoped plugin request until abx-dl completes it.

pause(*, save: bool = True) bool[source]
resume(*, when: datetime.datetime | None = None, save: bool = True) bool[source]
restore_paused_scheduler_marker() None[source]

Restore the indefinite scheduler marker owned by the PAUSED lifecycle.

reconcile_parent_lifecycle(*, lock_seconds: int = 60) bool | None[source]

Follow parent Crawl pause/seal state before any Snapshot work runs.

Crawl.pause()/cancel() only wake child rows. The runner claims each due Snapshot and lets this method perform the actual child transition, so cancellation stays fast and Snapshot cleanup still runs from the normal lifecycle owner.

finalize_completed_upload_results() int[source]
start_processing() bool[source]

Atomically move a claimed queued Snapshot into its active lease.

seal() bool[source]

Atomically finalize this Snapshot and reconcile its output metadata.

advance_lifecycle() bool[source]

Advance one explicit lifecycle step after the runner claims this row.

cancel() None[source]
get_delete_after_config_value()[source]
classmethod missing_delete_at_candidates()[source]
classmethod is_archivebox_internal_url(url: str, *, config: collections.abc.Mapping[str, Any] | Any | None = None) bool[source]
property created_by[source]

Convenience property to access the user who created this snapshot via its crawl.

property process_set[source]

Get all Process objects related to this snapshot’s ArchiveResults.

property binary_set[source]

Get all Binary objects used by processes related to this snapshot.

ensure_permissions_config(crawl_permissions: str | None = None) bool[source]
validate_url_for_archiving(*, config: collections.abc.Mapping[str, Any] | Any | None = None) None[source]
save(*args, **kwargs)[source]
static _fs_current_version() str[source]

Get current ArchiveBox filesystem layout version.

_FS_VERSION_MIGRATION_PATHS: ClassVar[dict[str, str]][source]

None

property fs_migration_needed: bool[source]

Check if snapshot needs filesystem migration

_fs_next_version(version: str) str[source]

Get the next declared version in the filesystem migration chain.

static is_legacy_archive_dir(path: pathlib.Path) bool[source]

Return True for old-style archive/{timestamp} snapshot directories.

migrate_filesystem_to_current_version(source_dir: pathlib.Path | None = None, config: ArchiveBoxBaseConfig | None = None) None[source]

Copy legacy snapshot output into the current layout and safely remove the old tree.

The ordering is intentionally crash-safe:

  1. Copy from the legacy directory into the new directory idempotently.

  2. Verify the new directory has every old file.

  3. Convert metadata in the new directory.

  4. Remove the verified legacy source.

  5. Persist fs_version last, so an interruption remains selected by the indexed stale-version query and resumes naturally.

Re-running this method also reconciles a legacy timestamp directory left behind when a machine stopped after the database commit but before the on-commit cleanup callback ran.

_fs_migrate_from_0_7_0_to_0_9_0(source_dir: pathlib.Path | None = None, config: ArchiveBoxBaseConfig | None = None)[source]
_fs_migrate_from_0_8_0_to_0_9_0(source_dir: pathlib.Path | None = None, config: ArchiveBoxBaseConfig | None = None)[source]
_fs_migrate_from_0_9_0_to_0_9_4(source_dir: pathlib.Path | None = None, config: ArchiveBoxBaseConfig | None = None)[source]
hydrate_archiveresult_output_metadata(snapshot_dir: pathlib.Path | None = None) int[source]

Populate missing ArchiveResult file metadata from existing outputs.

_fs_migrate_legacy_to_0_9_0(source_dir: pathlib.Path | None = None, target_dir: pathlib.Path | None = None, config: ArchiveBoxBaseConfig | None = None)[source]

Migrate from flat to nested structure.

0.8.x: archive/{timestamp}/ 0.9.x: archive/users/{user}/snapshots/YYYYMMDD/{domain}/{uuid}/

static _migration_trees_match(old_dir: pathlib.Path, new_dir: pathlib.Path) bool[source]

Verify every legacy entry exists unchanged at the destination.

_cleanup_old_migration_dir(old_dir: pathlib.Path, new_dir: pathlib.Path) bool[source]

Delete the old directory after its contents are verified at the new path.

static extract_domain_from_url(url: str) str[source]

Extract domain from URL for 0.9.x path structure. Uses full hostname with sanitized special chars.

Examples: https://example.com:8080 → example.com_8080 https://sub.example.comsub.example.com file:///path → localhost data:text/html → data

get_storage_path_for_version(version: str) pathlib.Path[source]

Calculate storage path for specific filesystem version. Centralizes path logic so it’s reusable.

0.7.x/0.8.x: archive/{timestamp} 0.9.x: archive/users/{username}/snapshots/YYYYMMDD/{domain}/{uuid}/

classmethod load_from_directory(snapshot_dir: pathlib.Path) Optional[archivebox.core.models.Snapshot][source]

Load existing Snapshot from DB by reading index.jsonl or index.json.

Reads index file, extracts url+timestamp, queries DB. Returns existing Snapshot or None if not found/invalid. Does NOT create new snapshots.

ONLY used by: archivebox update (for orphan detection)

classmethod create_from_directory(snapshot_dir: pathlib.Path) Optional[archivebox.core.models.Snapshot][source]

Create new Snapshot from orphaned directory.

Validates timestamp, ensures uniqueness. Returns new UNSAVED Snapshot or None if invalid.

ONLY used by: archivebox update (for orphan import)

static _select_best_timestamp(index_timestamp: object | None, folder_name: str) str | None[source]

Select best timestamp from index.json vs folder name.

Validates range (1995-2035). When a valid legacy folder name is available it is the stable filesystem identity, so preserve it over normalized variants like “1508259732.0” found in old index files.

classmethod _ensure_unique_timestamp(url: str, timestamp: str) str[source]

Ensure timestamp is globally unique. If there is a collision, add a tiny fractional suffix until unique.

static _detect_fs_version_from_index(data: dict) str[source]

Detect fs_version from index.json structure.

  • Has fs_version field: use it

  • Has history dict: 0.7.0

  • Has archive_results list: 0.8.0

  • Default: 0.7.0

reconcile_with_index(output_dir: pathlib.Path | None = None, update_existing_archive_results: bool = True)[source]

Merge index.json/index.jsonl with DB. DB is source of truth.

  • Title: longest non-URL

  • Tags: union

  • ArchiveResults: keep both (by plugin+start_ts)

Converts index.json to index.jsonl if needed, then writes back in JSONL format.

Used by: archivebox update (to sync index with DB)

reconcile_with_index_json(output_dir: pathlib.Path | None = None, update_existing_archive_results: bool = True)[source]

Deprecated: use reconcile_with_index() instead.

_merge_title_from_index(index_data: dict)[source]

Merge title - prefer longest non-URL title.

_merge_tags_from_index(index_data: dict)[source]

Merge tags - union of both sources.

_merge_archive_results_from_index(index_data: dict, update_existing: bool = True)[source]

Merge ArchiveResults one row per hook; retries update the existing row.

_create_archive_result_if_missing(result_data: dict, existing: dict, update_existing: bool = True)[source]

Create ArchiveResult if not already in DB.

write_index_json()[source]

Write index.json in 0.9.x format (deprecated, use write_index_jsonl).

write_index_jsonl(output_dir: pathlib.Path | None = None)[source]

Write index.jsonl in flat JSONL format.

Each line is a JSON record with a ‘type’ field:

  • Snapshot: snapshot metadata (crawl_id, url, tags, etc.)

  • ArchiveResult: extractor results (plugin, status, output, etc.)

  • Binary: binary info used for the extraction

  • Process: process execution details (cmd, exit_code, timing, etc.)

read_index_jsonl(output_dir: pathlib.Path | None = None) dict[source]

Read index.jsonl and return parsed records grouped by type.

Returns dict with keys: ‘snapshot’, ‘archive_results’, ‘binaries’, ‘processes’

convert_index_json_to_jsonl(output_dir: pathlib.Path | None = None) bool[source]

Convert index.json to index.jsonl format.

Reads existing index.json and creates index.jsonl while preserving the original JSON byte-for-byte for unknown legacy metadata. Returns True if conversion was performed, False if no conversion needed.

static move_directory_to_invalid(snapshot_dir: pathlib.Path)[source]

Move invalid directory to data/invalid/YYYYMMDD/.

Used by: archivebox update (when encountering invalid directories)

classmethod find_and_merge_duplicates() int[source]

Find and merge snapshots with same url:timestamp. Returns count of duplicate sets merged.

Used by: archivebox update (Phase 3: deduplication)

classmethod _merge_snapshots(snapshots: collections.abc.Sequence[archivebox.core.models.Snapshot])[source]

Merge exact duplicates. Keep oldest, union files + ArchiveResults.

property output_dir_parent: str[source]
property output_dir_name: str[source]
archive(overwrite=False, methods=None)[source]
tags_str() str | None[source]
icons(path: str | None = None, prefix: str = '/', quote_paths: bool = False) str[source]

Generate HTML icons showing which extractor plugins have succeeded for this snapshot

property api_url: str[source]
get_absolute_url()[source]
domain() str[source]
property title_stripped: str[source]
static _normalize_title_candidate(candidate: str | None, *, snapshot_url: str) str[source]
property resolved_title: str[source]
hashes_index() dict[str, dict[str, Any]][source]
property output_dir: pathlib.Path[source]

The filesystem path to the snapshot’s output directory.

Ensure snapshot is symlinked under its crawl output directory.

Remove a stale archive/ compatibility projection.

Repair filesystem projections after a save or migration.

legacy_archive_path() str[source]
archive_path_from_db() str[source]

Best-effort public URL path derived from DB fields only.

url_path() str[source]

URL path matching the current snapshot output_dir layout.

archive_path()[source]
archive_size()[source]
save_tags(tags: collections.abc.Iterable[str] = (), *, created_by: Any = None) None[source]
finalize_output_metadata() None[source]

Clean up background ArchiveResult hooks and empty results.

Called after entering the sealed state. Reconcile late background outputs and hydrate result metadata.

to_json() dict[source]

Convert Snapshot model instance to a JSON-serializable dict. Includes all fields needed to fully reconstruct/identify this snapshot.

static from_json(record: dict[str, Any], overrides: dict[str, Any] | None = None, queue_for_extraction: bool = True)[source]

Create/update Snapshot from JSON dict.

Unified method that handles:

  • ID-based patching: {“id”: “…”, “title”: “new title”}

  • URL-based create/update: {“url”: “…”, “title”: “…”, “tags”: “…”}

  • Auto-creates Crawl if not provided

  • Optionally queues for extraction

Args: record: Dict with ‘url’ (for create) or ‘id’ (for patch), plus other fields overrides: Dict with ‘crawl’, ‘snapshot’ (parent), ‘created_by_id’ queue_for_extraction: If True, sets status=QUEUED and retry_at (default: True)

Returns: Snapshot instance or None

get_progress_stats() dict[source]

Get progress statistics for this snapshot’s archiving process.

Returns dict with: - total: Total number of archive results - succeeded: Number of succeeded results - failed: Number of failed results - running: Number of currently running results - pending: Number of pending/queued results - percent: Completion percentage (0-100) - output_size: Total output size in bytes - is_sealed: Whether the snapshot is in a final state

retry_failed_archiveresults() int[source]

Queue the parent Snapshot to rerun plugins with failed facts.

url_hash() str[source]
scheme() str[source]
path() str[source]
basename() str[source]
extension() str[source]
base_url() str[source]
is_static() bool[source]
is_archived() bool[source]
bookmarked_date() str | None[source]
downloaded_datestr() str | None[source]
archive_dates() list[datetime.datetime][source]
oldest_archive_date() datetime.datetime | None[source]
newest_archive_date() datetime.datetime | None[source]
num_outputs() int[source]
num_failures() int[source]
latest_outputs(status: str | None = None) dict[str, Any][source]

Get the latest output that each plugin produced

discover_outputs(include_filesystem_fallback: bool = True, archive_results: list[archivebox.core.models.Snapshot.discover_outputs.ArchiveResult] | None = None) list[dict][source]

Discover output files from ArchiveResults and filesystem.

property static_archive_path: str[source]

Snapshot output path relative to the data root, for portable exports.

to_dict(extended: bool = False, static_export: bool = False) dict[str, Any][source]

Convert Snapshot to a dictionary (replacement for Link._asdict())

to_json_str(indent: int = 4) str[source]

Convert to JSON string (legacy method, use to_json() for dict)

to_csv(cols: list[str] | None = None, separator: str = ',', ljust: int = 0) str[source]

Convert to CSV string

write_json_details(out_dir: pathlib.Path | str | None = None) None[source]

Write JSON index file for this snapshot to its output directory

get_html_details_context(request=None, *, static_export_dir: pathlib.Path | None = None) dict[str, Any][source]

Build the one context used by both served and on-disk snapshot pages.

write_html_details(out_dir: pathlib.Path | str | None = None) None[source]

Write the unified snapshot detail page with portable filesystem URLs.

get_detail_page_auxiliary_items(outputs: list[dict] | None = None, hidden_card_plugins: set[str] | None = None, archive_results: list[archivebox.core.models.Snapshot.get_detail_page_auxiliary_items.ArchiveResult] | None = None) tuple[list[dict[str, object]], list[dict[str, object]]][source]
static _ts_to_date_str(dt: datetime.datetime | None) str | None[source]
class archivebox.core.models.ArchiveResult[source]

Bases: archivebox.base_models.models.ModelWithDeleteAfter, archivebox.base_models.models.ModelWithOutputDir, archivebox.base_models.models.ModelWithNotes

class StatusChoices[source]

Bases: django.db.models.TextChoices

QUEUED[source]

(‘queued’, ‘Queued’)

STARTED[source]

(‘started’, ‘Started’)

PAUSED[source]

(‘paused’, ‘Paused’)

BACKOFF[source]

(‘backoff’, ‘Waiting to retry’)

SUCCEEDED[source]

(‘succeeded’, ‘Succeeded’)

FAILED[source]

(‘failed’, ‘Failed’)

SKIPPED[source]

(‘skipped’, ‘Skipped’)

NORESULTS[source]

(‘noresults’, ‘No Results’)

INITIAL_STATE[source]

None

ACTIVE_STATE[source]

None

FINAL_STATES[source]

()

FINAL_OR_ACTIVE_STATES[source]

()

delete_after_final_statuses[source]

None

classmethod normalize_status(status: str | None) str[source]
classmethod get_or_create_by_hook(snapshot: archivebox.core.models.Snapshot, plugin: str, hook_name: str, *, defaults: collections.abc.Mapping[str, Any] | None = None) tuple[archivebox.core.models.ArchiveResult, bool][source]
static output_files_upload_complete(output_files: dict[str, dict[str, Any]]) bool[source]
classmethod get_plugin_choices()[source]

Get plugin choices from discovered hooks (for forms/admin).

classmethod snapshot_count_subquery(*, status: str | None = None, outer_ref: str = 'pk') django.db.models.QuerySet[source]

Return a scalar subquery counting ArchiveResults for one outer Snapshot.

Use this instead of filtered join aggregates for per-row Snapshot counts: the scalar form lets SQLite probe the covering (snapshot_id, status) or (status, snapshot_id) indexes once per visible Snapshot row, instead of joining and grouping the whole candidate Snapshot queryset.

classmethod snapshot_half_count_subquery(*, outer_ref: str = 'snapshot_id') django.db.models.QuerySet[source]
classmethod snapshot_count_expr(*, status: str | None = None, outer_ref: str = 'pk')[source]
classmethod status_counts(queryset: django.db.models.QuerySet | None = None, statuses: collections.abc.Iterable[str] | None = None) dict[str, int][source]

Count requested statuses with separate indexed COUNT probes.

classmethod snapshot_ids_with_majority_status(status: str | collections.abc.Iterable[str]) django.db.models.QuerySet[source]

Return Snapshot IDs where more than half of ArchiveResults have status.

Start from ArchiveResult.status for every majority-status filter. The (status, snapshot_id) index keeps the plan predictable even when a user’s collection has an unusual status distribution.

id[source]

‘CompactUUIDField(…)’

created_at[source]

‘DateTimeField(…)’

modified_at[source]

‘DateTimeField(…)’

snapshot: archivebox.core.models.Snapshot[source]

‘ForeignKey(…)’

plugin[source]

‘CharField(…)’

hook_name[source]

‘CharField(…)’

process[source]

‘OneToOneField(…)’

output_str[source]

‘TextField(…)’

output_json[source]

‘JSONField(…)’

output_files[source]

‘JSONField(…)’

output_size[source]

‘BigIntegerField(…)’

output_mimetypes[source]

‘CharField(…)’

start_ts[source]

‘DateTimeField(…)’

end_ts[source]

‘DateTimeField(…)’

status[source]

‘CharField(…)’

retry_at[source]

‘DateTimeField(…)’

notes[source]

‘TextField(…)’

snapshot_id: uuid.UUID[source]

None

process_id: uuid.UUID | None[source]

None

class Meta[source]

Bases: archivebox.base_models.models.ModelWithDeleteAfter.Meta, archivebox.base_models.models.ModelWithOutputDir.Meta, archivebox.base_models.models.ModelWithNotes.Meta

app_label[source]

‘core’

verbose_name[source]

‘Archive Result’

verbose_name_plural[source]

‘Archive Results’

indexes: ClassVar[list[django.db.models.Index]][source]

None

constraints: ClassVar[list[django.db.models.BaseConstraint]][source]

None

__str__()[source]
static _format_output_line_for_display(line: str) str[source]
output_str_for_display() str[source]
get_delete_after_config_value()[source]
classmethod missing_delete_at_candidates()[source]
property created_by[source]

Convenience property to access the user who created this archive result via its snapshot’s crawl.

to_json(*, snapshot_output_dir: pathlib.Path | None = None) dict[source]

Convert ArchiveResult model instance to a JSON-serializable dict.

static from_json(record: dict[str, Any], overrides: dict[str, Any] | None = None)[source]

Create/update ArchiveResult from JSON dict.

Args: record: JSON dict with ‘snapshot_id’, ‘plugin’, etc. overrides: Optional dict of field overrides

Returns: ArchiveResult instance or None

save(*args, **kwargs)[source]
safe_update(update_fields: collections.abc.Mapping[str, Any], *, refresh: bool = True) bool[source]

Compare-and-swap one loaded ArchiveResult without opening a transaction.

schedule_delete_cleanup(*, using: str | None = None) None[source]

Remove shared plugin output and refresh persisted Snapshot metadata after commit.

static refresh_snapshot_output_sizes(snapshot_ids)[source]
snapshot_dir()[source]
url()[source]
property api_url: str[source]
get_absolute_url()[source]
property is_paused: bool[source]
static _normalize_output_files(raw_output_files: Any) dict[str, dict[str, Any]][source]
static _coerce_output_file_size(value: Any) int[source]
output_file_map() dict[str, dict[str, Any]][source]
output_file_paths() list[str][source]
update_output_metadata_from_filesystem(snapshot_dir: pathlib.Path | None = None, save: bool = True) bool[source]
static _looks_like_output_path(raw_output: str | None, plugin_name: str | None = None) bool[source]
_existing_output_path(raw_output: str | None) str | None[source]
static _fallback_output_file_path(output_file_paths: collections.abc.Sequence[str], plugin_name: str | None = None, output_file_map: dict[str, dict[str, Any]] | None = None) str | None[source]
static _find_best_output_file(dir_path: pathlib.Path, plugin_name: str | None = None) pathlib.Path | None[source]
embed_path_db(output_file_map: dict[str, dict[str, Any]] | None = None) str | None[source]
embed_path() str | None[source]

Get the relative path to the embeddable output file for this result.

This is intentionally DB-backed only so snapshot/admin rendering stays fast and predictable without filesystem probes.

property output_dir_name: str[source]
property output_dir_parent: str[source]
property process_record[source]
property pwd: str[source]

Working directory, derived from the snapshot/plugin path if the Process row is gone.

property cmd: list[source]

Command array (from Process).

property cmd_version: str[source]

Command version (from Process.binary).

property binary[source]

Binary FK (from Process).

property iface[source]

Network interface FK (from Process).

property machine[source]

Machine FK (from Process).

property timeout: int[source]

Timeout in seconds (from Process).

_url_passes_filters(url: str) bool[source]

Check if URL passes URL_ALLOWLIST and URL_DENYLIST config filters.

Uses the centralized config resolver so frozen crawl/snapshot values and live Machine/Persona execution values apply in their scoped order.

property output_dir: pathlib.Path[source]

Get the output directory for this plugin’s results.