type and test fixes

This commit is contained in:
Nick Sweeting
2026-03-15 20:12:27 -07:00
parent 3889eb4efa
commit bc21d4bfdb
52 changed files with 762 additions and 1317 deletions

View File

@@ -1,16 +1,17 @@
__package__ = 'archivebox.core'
from django.contrib import admin
from django.utils.html import format_html, mark_safe
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from archivebox.misc.paginators import AccelleratedPaginator
from archivebox.base_models.admin import BaseModelAdmin
from archivebox.core.models import Tag
from archivebox.core.models import SnapshotTag, Tag
class TagInline(admin.TabularInline):
model = Tag.snapshot_set.through # type: ignore
model = SnapshotTag
# fk_name = 'snapshot'
fields = ('id', 'tag')
extra = 1
@@ -173,4 +174,3 @@ class TagAdmin(BaseModelAdmin):
def register_admin(admin_site):
admin_site.register(Tag, TagAdmin)

View File

@@ -2,8 +2,9 @@ __package__ = 'archivebox.core'
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.html import format_html, mark_safe
from django.contrib.auth import get_user_model
from django.utils.html import format_html
from django.utils.safestring import mark_safe
class CustomUserAdmin(UserAdmin):
@@ -16,7 +17,7 @@ class CustomUserAdmin(UserAdmin):
add_fieldsets = UserAdmin.add_fieldsets
# Extend fieldsets for change form only (not user creation)
fieldsets = [*UserAdmin.fieldsets, ('Data', {'fields': readonly_fields})]
fieldsets = [*(UserAdmin.fieldsets or ()), ('Data', {'fields': readonly_fields})]
@admin.display(description='Snapshots')
def snapshot_set(self, obj):

View File

@@ -22,12 +22,19 @@ def get_plugin_choices():
return [(name, name) for name in get_plugins()]
def get_choice_field(form: forms.Form, name: str) -> forms.ChoiceField:
field = form.fields[name]
if not isinstance(field, forms.ChoiceField):
raise TypeError(f'{name} must be a ChoiceField')
return field
class AddLinkForm(forms.Form):
# Basic fields
url = forms.RegexField(
label="URLs (one per line)",
regex=URL_REGEX,
min_length='6',
min_length=6,
strip=True,
widget=forms.Textarea,
required=True
@@ -162,22 +169,22 @@ class AddLinkForm(forms.Form):
extensions = {'twocaptcha', 'istilldontcareaboutcookies', 'ublock'}
# Populate plugin field choices
self.fields['chrome_plugins'].choices = [
get_choice_field(self, 'chrome_plugins').choices = [
(p, p) for p in sorted(all_plugins) if p in chrome_dependent
]
self.fields['archiving_plugins'].choices = [
get_choice_field(self, 'archiving_plugins').choices = [
(p, p) for p in sorted(all_plugins) if p in archiving
]
self.fields['parsing_plugins'].choices = [
get_choice_field(self, 'parsing_plugins').choices = [
(p, p) for p in sorted(all_plugins) if p in parsing
]
self.fields['search_plugins'].choices = [
get_choice_field(self, 'search_plugins').choices = [
(p, p) for p in sorted(all_plugins) if p in search
]
self.fields['binary_plugins'].choices = [
get_choice_field(self, 'binary_plugins').choices = [
(p, p) for p in sorted(all_plugins) if p in binary
]
self.fields['extension_plugins'].choices = [
get_choice_field(self, 'extension_plugins').choices = [
(p, p) for p in sorted(all_plugins) if p in extensions
]
@@ -185,13 +192,15 @@ class AddLinkForm(forms.Form):
self.fields['update'].initial = not ARCHIVING_CONFIG.ONLY_NEW
def clean(self):
cleaned_data = super().clean()
cleaned_data = super().clean() or {}
# Combine all plugin groups into single list
all_selected_plugins = []
for field in ['chrome_plugins', 'archiving_plugins', 'parsing_plugins',
'search_plugins', 'binary_plugins', 'extension_plugins']:
all_selected_plugins.extend(cleaned_data.get(field, []))
selected = cleaned_data.get(field)
if isinstance(selected, list):
all_selected_plugins.extend(selected)
# Store combined list for easy access
cleaned_data['plugins'] = all_selected_plugins
@@ -211,17 +220,13 @@ class AddLinkForm(forms.Form):
return schedule
class TagWidgetMixin:
class TagWidget(forms.TextInput):
def format_value(self, value):
if value is not None and not isinstance(value, str):
value = edit_string_for_tags(value)
return super().format_value(value)
class TagWidget(TagWidgetMixin, forms.TextInput):
pass
class TagField(forms.CharField):
widget = TagWidget
@@ -234,21 +239,21 @@ class TagField(forms.CharField):
"Please provide a comma-separated list of tags."
)
def has_changed(self, initial_value, data_value):
def has_changed(self, initial, data):
# Always return False if the field is disabled since self.bound_data
# always uses the initial value in this case.
if self.disabled:
return False
try:
data_value = self.clean(data_value)
cleaned_data = self.clean(data)
except forms.ValidationError:
pass
cleaned_data = data
if initial_value is None:
initial_value = []
initial_value = [] if initial is None else initial
initial_value = [tag.name for tag in initial_value]
initial_value.sort()
if not isinstance(initial_value, list):
initial_value = list(initial_value)
return initial_value != data_value
normalized_initial = sorted(tag.name for tag in initial_value)
return normalized_initial != cleaned_data

View File

@@ -2,8 +2,7 @@ __package__ = 'archivebox'
from django.core.management.base import BaseCommand
from .cli import run_subcommand
from archivebox.cli import main as run_cli
class Command(BaseCommand):
@@ -15,4 +14,5 @@ class Command(BaseCommand):
def handle(self, *args, **kwargs):
run_subcommand(kwargs['subcommand'], args=kwargs['command_args'])
command_args = [kwargs['subcommand'], *kwargs['command_args']]
run_cli(args=command_args)

View File

@@ -165,6 +165,8 @@ class ReverseProxyAuthMiddleware(RemoteUserMiddleware):
return
ip = request.META.get('REMOTE_ADDR')
if not isinstance(ip, str):
return
for cidr in SERVER_CONFIG.REVERSE_PROXY_WHITELIST.split(','):
try:

View File

@@ -3,10 +3,11 @@
import archivebox.base_models.models
import django.db.models.deletion
import django.utils.timezone
import uuid
from django.conf import settings
from django.db import migrations, models, connection
from archivebox.uuid_compat import uuid7
def copy_old_fields_to_new(apps, schema_editor):
"""Copy data from old field names to new field names after AddField operations."""
@@ -236,7 +237,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='archiveresult',
name='uuid',
field=models.UUIDField(blank=True, db_index=True, default=uuid.uuid7, null=True),
field=models.UUIDField(blank=True, db_index=True, default=uuid7, null=True),
),
migrations.AlterField(
model_name='snapshot',
@@ -246,7 +247,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='snapshot',
name='id',
field=models.UUIDField(default=uuid.uuid7, editable=False, primary_key=True, serialize=False, unique=True),
field=models.UUIDField(default=uuid7, editable=False, primary_key=True, serialize=False, unique=True),
),
migrations.AlterField(
model_name='snapshot',

View File

@@ -1,8 +1,9 @@
# Generated by Django 6.0 on 2026-01-02 10:02
import uuid
from django.db import migrations, models
from archivebox.uuid_compat import uuid7
class Migration(migrations.Migration):
@@ -14,6 +15,6 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='archiveresult',
name='id',
field=models.UUIDField(default=uuid.uuid7, editable=False, primary_key=True, serialize=False, unique=True),
field=models.UUIDField(default=uuid7, editable=False, primary_key=True, serialize=False, unique=True),
),
]