fix plugin loading and admin config display

This commit is contained in:
Nick Sweeting 2024-01-24 02:15:02 -08:00
parent d0e3c9502e
commit 8e41aec099
19 changed files with 316 additions and 48 deletions

View file

@ -38,7 +38,7 @@ from hashlib import md5
from pathlib import Path
from datetime import datetime, timezone
from typing import Optional, Type, Tuple, Dict, Union, List
from subprocess import run, PIPE, DEVNULL
from subprocess import run, PIPE, STDOUT, DEVNULL
from configparser import ConfigParser
from collections import defaultdict
import importlib.metadata
@ -825,7 +825,7 @@ def hint(text: Union[Tuple[str, ...], List[str], str], prefix=' ', config: Op
# Dependency Metadata Helpers
def bin_version(binary: Optional[str]) -> Optional[str]:
def bin_version(binary: Optional[str], cmd=None) -> Optional[str]:
"""check the presence and return valid version line of a specified binary"""
abspath = bin_path(binary)
@ -834,11 +834,21 @@ def bin_version(binary: Optional[str]) -> Optional[str]:
try:
bin_env = os.environ | {'LANG': 'C'}
version_str = run([abspath, "--version"], stdout=PIPE, env=bin_env).stdout.strip().decode()
is_cmd_str = cmd and isinstance(cmd, str)
version_str = run(cmd or [abspath, "--version"], shell=is_cmd_str, stdout=PIPE, stderr=STDOUT, env=bin_env).stdout.strip().decode()
if not version_str:
version_str = run([abspath, "--version"], stdout=PIPE).stdout.strip().decode()
# take first 3 columns of first line of version info
return ' '.join(version_str.split('\n')[0].strip().split()[:3])
version_str = run(cmd or [abspath, "--version"], shell=is_cmd_str, stdout=PIPE, stderr=STDOUT).stdout.strip().decode()
version_ptn = re.compile(r"\d+?\.\d+?\.?\d*", re.MULTILINE)
try:
version_nums = version_ptn.findall(version_str.split('\n')[0])[0]
if version_nums:
return version_nums
else:
raise IndexError
except IndexError:
# take first 3 columns of first line of version info
return ' '.join(version_str.split('\n')[0].strip().split()[:3])
except OSError:
pass
# stderr(f'[X] Unable to find working version of dependency: {binary}', color='red')

View file

@ -1 +1,3 @@
__package__ = 'archivebox.core'
default_app_config = 'core.apps.CoreAppConfig'

View file

@ -12,6 +12,7 @@ from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.shortcuts import render, redirect
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django import forms
from ..util import htmldecode, urldecode, ansi_to_html
@ -436,6 +437,8 @@ class ArchiveBoxAdmin(admin.AdminSite):
admin.site = ArchiveBoxAdmin()
admin.site.register(get_user_model())
admin.site.register(Group)
admin.site.register(Permission)
admin.site.register(Snapshot, SnapshotAdmin)
admin.site.register(Tag, TagAdmin)
admin.site.register(ArchiveResult, ArchiveResultAdmin)

View file

@ -1,7 +1,10 @@
from django.apps import AppConfig
class CoreConfig(AppConfig):
class CoreAppConfig(AppConfig):
name = 'core'
# label = 'Archive Data'
verbose_name = "Archive Data"
# WIP: broken by Django 3.1.2 -> 4.0 migration
default_auto_field = 'django.db.models.UUIDField'

View file

@ -50,7 +50,7 @@ class Tag(models.Model):
class Meta:
verbose_name = "Tag"
verbose_name_plural = "Tags"
verbose_name_plural = "🏷️ Tags"
def __str__(self):
return self.name
@ -98,6 +98,10 @@ class Snapshot(models.Model):
keys = ('url', 'timestamp', 'title', 'tags', 'updated')
class Meta:
verbose_name = "Snapshot"
verbose_name_plural = "⭐️ Archived Webpages (Snapshots)"
def __repr__(self) -> str:
title = self.title or '-'
return f'[{self.timestamp}] {self.url[:64]} ({title[:64]})'
@ -282,5 +286,9 @@ class ArchiveResult(models.Model):
objects = ArchiveResultManager()
class Meta:
verbose_name = "ArchiveResult"
verbose_name_plural = "📑 Logs (ArchiveResults)"
def __str__(self):
return self.extractor

View file

@ -0,0 +1 @@
default_app_config = 'plugins.defaults.apps.DefaultsPluginAppConfig'

View file

@ -8,11 +8,10 @@ from .models import (
class DependencyAdmin(SingletonModelAdmin):
readonly_fields = ('REQUIRED', 'ENABLED', 'BINARY', 'ARGS', 'bin_path', 'bin_version', 'is_valid', 'is_enabled')
readonly_fields = ('id', 'NAME', 'LABEL', 'REQUIRED', 'bin_path', 'bin_version', 'is_valid', 'is_enabled')
class ExtractorAdmin(SingletonModelAdmin):
# readonly_fields = ('REQUIRED', 'ENABLED', 'BINARY', 'ARGS', 'bin_path', 'bin_version', 'is_valid', 'is_enabled')
pass
readonly_fields = ('id', 'NAME', 'LABEL', 'DEFAULT_ENABLED', 'DEFAULT_CMD', 'CMD', 'ARGS', 'TIMEOUT', 'dependency', 'is_valid', 'is_enabled')
print('DefaultsPluginConfig.admin')

View file

@ -1,13 +1,15 @@
__package__ = 'archivebox.plugins.defaults'
# __package__ = 'archivebox.plugins.defaults'
from django.apps import AppConfig
class DefaultsPluginConfig(AppConfig):
label = "ArchiveBox Defaults"
name = "defaults"
class DefaultsPluginAppConfig(AppConfig):
name = "plugins.defaults"
# label = "ArchiveBox Defaults"
verbose_name = "Plugin Configuration Defaults"
default_auto_field = "django.db.models.AutoField"

View file

@ -1,4 +1,4 @@
# Generated by Django 3.1.14 on 2024-01-24 08:06
# Generated by Django 3.1.14 on 2024-01-24 08:56
from django.db import migrations, models
@ -20,6 +20,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(default=1, primary_key=True, serialize=False)),
],
options={
'verbose_name': 'Dependency Configuration Defaults',
'abstract': False,
},
),
@ -33,6 +34,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(default=1, primary_key=True, serialize=False)),
],
options={
'verbose_name': 'Extractor Configuration Defaults',
'abstract': False,
},
),

View file

@ -0,0 +1,31 @@
# Generated by Django 3.1.14 on 2024-01-24 09:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('defaults', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='archiveboxdefaultdependency',
options={'verbose_name': 'Default Configuration: Dependencies'},
),
migrations.AlterModelOptions(
name='archiveboxdefaultextractor',
options={'verbose_name': 'Default Configuration: Extractors'},
),
migrations.AlterField(
model_name='archiveboxdefaultdependency',
name='BINARY',
field=models.CharField(default='/bin/bash', max_length=255),
),
migrations.AlterField(
model_name='archiveboxdefaultdependency',
name='ENABLED',
field=models.BooleanField(default=True),
),
]

View file

@ -10,17 +10,20 @@ from django.utils.functional import cached_property
from solo.models import SingletonModel
from config import bin_path, bin_version
ConfigDict = Dict[str, Any]
def bin_path(binary: str) -> str | None:
return shutil.which(str(Path(binary).expanduser())) or shutil.which(str(binary)) or binary
# def bin_path(binary: str) -> str | None:
# return shutil.which(str(Path(binary).expanduser())) or shutil.which(str(binary)) or binary
def bin_version(bin_path: str, cmd: str | None=None) -> str | None:
return '0.0.0'
# def bin_version(bin_path: str, cmd: str | None=None) -> str | None:
# return '0.0.0'
class ArchiveBoxBaseDependency(SingletonModel):
class ArchiveBoxBaseDependency(models.Model):
singleton_instance_id = 1
id = models.AutoField(default=singleton_instance_id, primary_key=True)
@ -37,11 +40,11 @@ class ArchiveBoxBaseDependency(SingletonModel):
PIP_DEPENDENCIES = []
NPM_DEPENDENCIES = []
DEFAULT_BINARY = '/bin/false'
DEFAULT_START_CMD = '/bin/false'
DEFAULT_BINARY = '/bin/bash'
DEFAULT_START_CMD = '/bin/bash -c "while true; do sleep 1; done"'
DEFAULT_PID_FILE = 'logs/{NAME}_WORKER.pid'
DEFAULT_STOP_CMD = 'kill "$(<{PID_FILE})"'
DEFAULT_VERSION_COMMAND = '{CMD} --version'
DEFAULT_VERSION_COMMAND = '{BINARY} --version'
DEFAULT_ARGS = ''
VERSION_CMD = '{BINARY} --version'
@ -58,7 +61,7 @@ class ArchiveBoxBaseDependency(SingletonModel):
app_label = 'defaults'
def __str__(self):
return "{self.LABEL} Dependency Configuration"
return f"{self.LABEL} Dependency Configuration"
def __json__(self):
return {
@ -79,7 +82,9 @@ class ArchiveBoxBaseDependency(SingletonModel):
@cached_property
def bin_version(self):
return bin_version(self.bin_path, cmd=self.VERSION_CMD)
print(f'ArchiveBoxBaseDependency.bin_version({self.bin_path}, cmd={self.VERSION_CMD.format(BINARY=self.BINARY)})')
return bin_version(self.bin_path, cmd=self.VERSION_CMD.format(BINARY=self.BINARY))
# return bin_version(self.bin_path, cmd=self.VERSION_CMD)
@cached_property
def is_valid(self):
@ -157,12 +162,15 @@ class ArchiveBoxDefaultDependency(ArchiveBoxBaseDependency, SingletonModel):
id = models.AutoField(default=singleton_instance_id, primary_key=True)
ENABLED = models.BooleanField(default=True, editable=True)
class Meta:
abstract = False
app_label = 'defaults'
verbose_name = 'Default Configuration: Dependencies'
class ArchiveBoxBaseExtractor(SingletonModel):
class ArchiveBoxBaseExtractor(models.Model):
singleton_instance_id = 1
id = models.AutoField(default=singleton_instance_id, primary_key=True)
@ -258,7 +266,7 @@ class ArchiveBoxBaseExtractor(SingletonModel):
def save(self, *args, **kwargs):
assert self.is_valid
# assert self.is_valid
with transaction.atomic():
result = super().save(*args, **kwargs)
@ -356,6 +364,11 @@ class ArchiveBoxDefaultExtractor(ArchiveBoxBaseExtractor, SingletonModel):
id = models.AutoField(default=singleton_instance_id, primary_key=True)
DEPENDENCY = ArchiveBoxDefaultDependency
ENABLED = models.BooleanField(default=True, editable=True)
class Meta:
abstract = False
app_label = 'defaults'
verbose_name = 'Default Configuration: Extractors'

View file

@ -1,12 +1,15 @@
from pathlib import Path
from django.conf import settings
def register_plugin_settings(settings=settings, name='defaults'):
settings.STATICFILES_DIRS += [
str(Path(PACKAGE_DIR) / f'plugins/{name}/static'),
str(Path(settings.PACKAGE_DIR) / f'plugins/{name}/static'),
]
settings.TEMPLATE_DIRS += [
str(Path(PACKAGE_DIR) / f'plugins/{name}/templates'),
str(Path(settings.PACKAGE_DIR) / f'plugins/{name}/templates'),
]
print('REGISTERED PLUGIN SETTINGS', name)

View file

@ -0,0 +1 @@
default_app_config = 'plugins.system.apps.SystemPluginAppConfig'

View file

@ -5,6 +5,9 @@ from plugins.defaults.admin import DependencyAdmin, ExtractorAdmin
from .models import (
BashEnvironmentDependency,
PythonEnvironmentDependency,
NodeJSEnvironmentDependency,
AptEnvironmentDependency,
BrewEnvironmentDependency,
PipEnvironmentDependency,
@ -20,8 +23,20 @@ from .models import (
print('DefaultsPluginConfig.admin')
class MultiDependencyAdmin(admin.ModelAdmin):
readonly_fields = DependencyAdmin.readonly_fields
list_display = ('id', 'NAME', 'ENABLED', 'BINARY', 'ARGS', 'bin_path', 'bin_version', 'is_valid', 'is_enabled')
class MultiExtractorAdmin(admin.ModelAdmin):
readonly_fields = DependencyAdmin.readonly_fields
list_display = ('id', 'NAME', 'CMD', 'ARGS', 'is_valid', 'is_enabled')
# admin.site.register(BashEnvironmentDependency, DependencyAdmin)
admin.site.register(BashEnvironmentDependency, MultiDependencyAdmin)
admin.site.register(PythonEnvironmentDependency, DependencyAdmin)
admin.site.register(NodeJSEnvironmentDependency, DependencyAdmin)
admin.site.register(BashEnvironmentDependency, DependencyAdmin)
admin.site.register(AptEnvironmentDependency, DependencyAdmin)
admin.site.register(BrewEnvironmentDependency, DependencyAdmin)
admin.site.register(PipEnvironmentDependency, DependencyAdmin)

View file

@ -4,9 +4,10 @@
from django.apps import AppConfig
class SystemPluginConfig(AppConfig):
label = "ArchiveBox System"
name = "system"
class SystemPluginAppConfig(AppConfig):
name = "plugins.system"
# label = "ArchiveBox System"
verbose_name = "Host System Configuration"
default_auto_field = "django.db.models.AutoField"
@ -15,7 +16,7 @@ class SystemPluginConfig(AppConfig):
from django.conf import settings
from .settings import register_plugin_settings
from plugins.defaults.settings import register_plugin_settings
register_plugin_settings(settings, name=self.name)

View file

@ -1,4 +1,4 @@
# Generated by Django 3.1.14 on 2024-01-24 08:06
# Generated by Django 3.1.14 on 2024-01-24 08:56
from django.db import migrations, models
@ -20,6 +20,7 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default='-qq', max_length=255)),
],
options={
'verbose_name': 'Package Manager: apt',
'abstract': False,
},
),
@ -32,6 +33,7 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
],
options={
'verbose_name': 'Internal Dependency: ArchiveBox Package',
'abstract': False,
},
),
@ -44,6 +46,7 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default='-c', max_length=255)),
],
options={
'verbose_name': 'Shell Environment: bash',
'abstract': False,
},
),
@ -56,6 +59,7 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default='', max_length=255)),
],
options={
'verbose_name': 'Package Manager: brew',
'abstract': False,
},
),
@ -68,6 +72,20 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
],
options={
'verbose_name': 'Internal Dependency: Django Package',
'abstract': False,
},
),
migrations.CreateModel(
name='NodeJSEnvironmentDependency',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('ENABLED', models.BooleanField(default=True)),
('BINARY', models.CharField(default='node', max_length=255)),
('ARGS', models.CharField(default='-c', max_length=255)),
],
options={
'verbose_name': 'Shell Environment: NodeJS',
'abstract': False,
},
),
@ -80,6 +98,7 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default='', max_length=255)),
],
options={
'verbose_name': 'Package Manager: npm',
'abstract': False,
},
),
@ -92,6 +111,20 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default='', max_length=255)),
],
options={
'verbose_name': 'Package Manager: pip',
'abstract': False,
},
),
migrations.CreateModel(
name='PythonEnvironmentDependency',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('ENABLED', models.BooleanField(default=True, editable=False)),
('BINARY', models.CharField(default='python3', max_length=255)),
('ARGS', models.CharField(default='-c', max_length=255)),
],
options={
'verbose_name': 'Shell Environment: Python3',
'abstract': False,
},
),
@ -104,6 +137,7 @@ class Migration(migrations.Migration):
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
],
options={
'verbose_name': 'Internal Dependency: SQLite3 Package',
'abstract': False,
},
),

View file

@ -0,0 +1,33 @@
# Generated by Django 3.1.14 on 2024-01-24 09:43
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('system', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='archiveboxdependency',
options={'verbose_name': 'Internal Dependency: archivebox'},
),
migrations.AlterModelOptions(
name='djangodependency',
options={'verbose_name': 'Internal Dependency: django'},
),
migrations.AlterModelOptions(
name='nodejsenvironmentdependency',
options={'verbose_name': 'Shell Environment: node'},
),
migrations.AlterModelOptions(
name='pythonenvironmentdependency',
options={'verbose_name': 'Shell Environment: python3'},
),
migrations.AlterModelOptions(
name='sqlitedependency',
options={'verbose_name': 'Internal Dependency: sqlite3'},
),
]

View file

@ -0,0 +1,22 @@
# Generated by Django 3.1.14 on 2024-01-24 09:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('system', '0002_auto_20240124_0943'),
]
operations = [
migrations.AlterModelOptions(
name='bashenvironmentdependency',
options={'verbose_name': 'Shell Environment: bash', 'verbose_name_plural': 'Shell Environments: bash'},
),
migrations.AddField(
model_name='bashenvironmentdependency',
name='VERSION_CMD',
field=models.CharField(default='{BINARY} --version', max_length=255),
),
]

View file

@ -6,7 +6,7 @@ import shutil
import sys
import inspect
import django
import sqlite3
from sqlite3 import dbapi2 as sqlite3
from pathlib import Path
from typing import List, Dict, Any
@ -16,12 +16,14 @@ from django.utils.functional import cached_property
from solo.models import SingletonModel
from plugins.defaults.models import ArchiveBoxBaseDependency, bin_path, bin_version
from config import bin_path, bin_version, VERSION
from plugins.defaults.models import ArchiveBoxBaseDependency
ConfigDict = Dict[str, Any]
class BashEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
class BashEnvironmentDependency(ArchiveBoxBaseDependency):
singleton_instance_id = 1
id = models.AutoField(primary_key=True)
@ -43,6 +45,53 @@ class BashEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
DEFAULT_STOP_CMD = None
DEFAULT_PID_FILE = None
DEFAULT_ARGS = '-c'
ENABLED = models.BooleanField(default=True, editable=not REQUIRED)
BINARY = models.CharField(max_length=255, default=DEFAULT_BINARY)
ARGS = models.CharField(max_length=255, default=DEFAULT_ARGS)
VERSION_CMD = models.CharField(max_length=255, default='{BINARY} --version')
# START_CMD = models.CharField(max_length=255, default=DEFAULT_START_CMD)
# WORKERS = models.IntegerField(default=1)
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Shell Environment: bash"
verbose_name_plural = "Shell Environments: bash"
# @task
def install_pkgs(self, os_pkgs=()):
assert self.is_valid, 'Bash environment is not available on this host'
for os_dependency in os_pkgs:
assert bin_path(os_dependency)
return True
class PythonEnvironmentDependency(ArchiveBoxBaseDependency):
singleton_instance_id = 1
id = models.AutoField(primary_key=True)
NAME = 'PYTHON'
LABEL = "Python"
REQUIRED = True
PARENT_DEPENDENCIES = []
BIN_DEPENDENCIES = ['python3']
APT_DEPENDENCIES = []
BREW_DEPENDENCIES = []
PIP_DEPENDENCIES = []
NPM_DEPENDENCIES = []
DEFAULT_BINARY = 'python3'
DEFAULT_START_CMD = None
DEFAULT_STOP_CMD = None
DEFAULT_PID_FILE = None
DEFAULT_ARGS = '-c'
VERSION_CMD = '{BINARY} --version'
ENABLED = models.BooleanField(default=True, editable=not REQUIRED)
@ -55,15 +104,44 @@ class BashEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Shell Environment: python3"
# @task
def install_pkgs(self, os_pkgs=()):
assert self.is_valid, 'Bash environment is not available on this host'
class NodeJSEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
singleton_instance_id = 1
for os_dependency in os_pkgs:
assert bin_path(os_dependency)
id = models.AutoField(primary_key=True)
NAME = 'NODEJS'
LABEL = "NodeJS"
REQUIRED = True
PARENT_DEPENDENCIES = []
BIN_DEPENDENCIES = ['node']
APT_DEPENDENCIES = []
BREW_DEPENDENCIES = []
PIP_DEPENDENCIES = []
NPM_DEPENDENCIES = []
DEFAULT_BINARY = 'node'
DEFAULT_START_CMD = None
DEFAULT_STOP_CMD = None
DEFAULT_PID_FILE = None
DEFAULT_ARGS = '-c'
VERSION_CMD = '{BINARY} --version'
ENABLED = models.BooleanField(default=True, editable=True)
BINARY = models.CharField(max_length=255, default=DEFAULT_BINARY)
ARGS = models.CharField(max_length=255, default=DEFAULT_ARGS)
# START_CMD = models.CharField(max_length=255, default=DEFAULT_START_CMD)
# WORKERS = models.IntegerField(default=1)
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Shell Environment: node"
return True
class AptEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
singleton_instance_id = 1
@ -95,6 +173,7 @@ class AptEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Package Manager: apt"
# @task
def install_pkgs(self, apt_pkgs=()):
@ -136,6 +215,7 @@ class BrewEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Package Manager: brew"
# @task
def install_pkgs(self, brew_pkgs=()):
@ -182,6 +262,7 @@ class PipEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Package Manager: pip"
# @task
def install_pkgs(self, pip_pkgs=()):
@ -224,6 +305,7 @@ class NPMEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Package Manager: npm"
# @task
def install_pkgs(self, npm_pkgs=()):
@ -266,6 +348,7 @@ class DjangoDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Internal Dependency: django"
@cached_property
def bin_path(self):
@ -273,7 +356,7 @@ class DjangoDependency(ArchiveBoxBaseDependency, SingletonModel):
@cached_property
def bin_version(self):
return django.VERSION
return '.'.join(str(v) for v in django.VERSION[:3])
class SQLiteDependency(ArchiveBoxBaseDependency, SingletonModel):
@ -307,6 +390,7 @@ class SQLiteDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Internal Dependency: sqlite3"
@cached_property
def bin_path(self):
@ -316,7 +400,7 @@ class SQLiteDependency(ArchiveBoxBaseDependency, SingletonModel):
def bin_version(self):
return sqlite3.version
class ArchiveBoxDependency(ArchiveBoxBaseDependency, SingletonModel):
class ArchiveBoxDependency(ArchiveBoxBaseDependency):
singleton_instance_id = 1
id = models.AutoField(primary_key=True)
@ -349,6 +433,7 @@ class ArchiveBoxDependency(ArchiveBoxBaseDependency, SingletonModel):
class Meta:
abstract = False
app_label = 'system'
verbose_name = "Internal Dependency: archivebox"
@cached_property
def bin_path(self):
@ -357,5 +442,5 @@ class ArchiveBoxDependency(ArchiveBoxBaseDependency, SingletonModel):
@cached_property
def bin_version(self):
# return config['VERSION']
return '0.7.3+editable'
return VERSION