release: archivebox 0.9.33rc42

This commit is contained in:
Nick Sweeting 2026-05-29 04:28:08 -07:00
parent 9704d933e6
commit e094c51d67
No known key found for this signature in database
6 changed files with 27 additions and 65 deletions

View File

@ -30,7 +30,7 @@ class PersonaAdminForm(PluginConfigFormMixin, forms.ModelForm):
label="Permissions",
choices=PERMISSIONS_CHOICES,
required=True,
help_text="Default visibility for crawls and snapshots that use this persona.",
help_text="Default visibility for crawls and snapshots created using this persona.",
)
import_mode = forms.ChoiceField(
required=False,

View File

@ -1210,14 +1210,14 @@ def queued_plugins_for_snapshot(snapshot_id: str) -> list[str] | None:
]
if obsolete_result_ids:
# Hook names are the scheduler identity for ArchiveResults. If an old
# queued row names a hook that the current plugin model cannot run, mark
# only that row final so the Snapshot scheduler can drain normally instead
# of re-running the whole plugin forever.
# queued row names a hook that the current plugin model cannot run, hard
# fail only that row so the scheduler drains without hiding stale/broken
# plugin state as an intentional skip.
ArchiveResult.objects.filter(
id__in=obsolete_result_ids,
status=ArchiveResult.StatusChoices.QUEUED,
).update(
status=ArchiveResult.StatusChoices.SKIPPED,
status=ArchiveResult.StatusChoices.FAILED,
output_str="Hook no longer exists in the current plugin set.",
modified_at=timezone.now(),
)

View File

@ -16,10 +16,6 @@
radial-gradient(circle at top right, rgba(67, 97, 238, 0.10), transparent 32%),
linear-gradient(135deg, #fff7ed 0%, #ffffff 45%, #ecfeff 100%);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
display: grid;
gap: 18px;
grid-template-columns: minmax(0, 1.8fr) minmax(280px, 1fr);
align-items: start;
}
.persona-import-hero h2 {
@ -32,37 +28,14 @@
.persona-import-hero p {
margin: 0;
color: #475569;
max-width: 70ch;
max-width: 92ch;
font-size: 14px;
}
.persona-import-hero__meta {
display: grid;
gap: 10px;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
.persona-import-hero__stat {
padding: 14px 16px;
border-radius: 14px;
background: rgba(255, 255, 255, 0.86);
border: 1px solid rgba(203, 213, 225, 0.85);
}
.persona-import-hero__stat span {
display: block;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
font-weight: 700;
color: #64748b;
margin-bottom: 8px;
}
.persona-import-hero__stat strong,
.persona-import-hero__stat code {
font-size: 18px;
.persona-import-copy {
cursor: pointer;
color: #0f172a;
border-bottom: 1px dashed #64748b;
}
.field-import_mode ul,
@ -194,12 +167,6 @@
color: #991b1b;
}
@media (max-width: 960px) {
.persona-import-hero {
grid-template-columns: 1fr;
}
}
body.model-persona.change-form #content-main form fieldset.persona-card-primary {
flex: 1 1 520px !important;
max-width: calc(66.66% - 10px) !important;
@ -260,6 +227,7 @@ document.addEventListener('DOMContentLoaded', function () {
const discoveredRow = document.querySelector('.form-row.field-import_discovered_profile');
const sourceRow = document.querySelector('.form-row.field-import_source');
const profileRow = document.querySelector('.form-row.field-import_profile_name');
const copyInspect = document.querySelector('[data-copy-text]');
const updateVisibility = () => {
const selected = modeInputs.find((input) => input.checked)?.value || 'none';
@ -270,6 +238,12 @@ document.addEventListener('DOMContentLoaded', function () {
modeInputs.forEach((input) => input.addEventListener('change', updateVisibility));
updateVisibility();
if (copyInspect) {
copyInspect.addEventListener('click', function () {
navigator.clipboard?.writeText(this.dataset.copyText || this.textContent.trim());
});
}
});
</script>
{% endblock %}
@ -277,25 +251,13 @@ document.addEventListener('DOMContentLoaded', function () {
{% block form_top %}
<section class="persona-import-hero">
<div>
<h2>Bootstrap a persona from a real browser session</h2>
<h2>Create a new Persona (Authentication + Configuration Profile)</h2>
<p>
Pick a local Chromium profile, paste an absolute profile path, or attach to a live CDP endpoint.
The form saves the Persona normally, then imports profile files, cookies, and optional tab storage into
the Persona's own directories.
Import cookies and settings from any Chrome-based browser by pasting in the local path of a User Data Directory to import from,
or by pasting in your CDP url from
<code class="persona-import-copy" data-copy-text="chrome://inspect#remote-debugging" title="Copy chrome://inspect#remote-debugging">chrome://inspect#remote-debugging</code>.
</p>
</div>
<div class="persona-import-hero__meta">
<div class="persona-import-hero__stat">
<span>Detected profiles</span>
<strong>{{ detected_profile_count }}</strong>
</div>
<div class="persona-import-hero__stat">
<span>Persona artifacts</span>
<code>chrome_profile</code>
<code>cookies.txt</code>
<code>auth.json</code>
</div>
</div>
</section>
{{ block.super }}
{% endblock %}

View File

@ -1220,7 +1220,7 @@ class TestRecoverOrchestratorState:
assert result.status == ArchiveResult.StatusChoices.SUCCEEDED
assert snapshot.retry_at is None
def test_run_due_snapshot_skips_obsolete_queued_hook_name(self):
def test_run_due_snapshot_fails_obsolete_queued_hook_name(self):
from django.utils import timezone
from archivebox.base_models.models import get_or_create_system_user_pk
@ -1251,7 +1251,7 @@ class TestRecoverOrchestratorState:
result.refresh_from_db()
snapshot.refresh_from_db()
assert result.status == ArchiveResult.StatusChoices.SKIPPED
assert result.status == ArchiveResult.StatusChoices.FAILED
assert snapshot.retry_at is None
def test_recover_orchestrator_state_ignores_sealed_downloaded_snapshot_without_results(self):

View File

@ -1,6 +1,6 @@
{
"name": "archivebox",
"version": "0.9.33rc41",
"version": "0.9.33rc42",
"repository": "github:ArchiveBox/ArchiveBox",
"license": "MIT",
"dependencies": {

View File

@ -1,6 +1,6 @@
[project]
name = "archivebox"
version = "0.9.33rc41"
version = "0.9.33rc42"
requires-python = ">=3.13"
description = "Self-hosted internet archiving solution."
authors = [{name = "Nick Sweeting", email = "pyproject.toml@archivebox.io"}]
@ -79,9 +79,9 @@ dependencies = [
### Extractor dependencies (optional binaries detected at runtime via shutil.which)
### Binary/Package Management
"abxbus==2.5.8", # EventBus API
"abxpkg>=1.11.67", # for: detecting, versioning, and installing binaries via apt/brew/pip/npm
"abx-plugins>=1.11.73", # shared ArchiveBox plugin package with Chrome/Puppeteer dependency wiring
"abx-dl>=1.11.73", # shared ArchiveBox downloader package with blocking install preflight
"abxpkg>=1.11.68", # for: detecting, versioning, and installing binaries via apt/brew/pip/npm
"abx-plugins>=1.11.74", # shared ArchiveBox plugin package with Chrome/Puppeteer dependency wiring
"abx-dl>=1.11.74", # shared ArchiveBox downloader package with blocking install preflight
### UUID7 backport for Python <3.14
"uuid7>=0.1.0; python_version < '3.14'", # provides the uuid_extensions module on Python 3.13
]