mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2025-05-14 07:04:27 -04:00
fix plugin loading and admin config display
This commit is contained in:
parent
d0e3c9502e
commit
8e41aec099
19 changed files with 316 additions and 48 deletions
|
@ -38,7 +38,7 @@ from hashlib import md5
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Optional, Type, Tuple, Dict, Union, List
|
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 configparser import ConfigParser
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import importlib.metadata
|
import importlib.metadata
|
||||||
|
@ -825,7 +825,7 @@ def hint(text: Union[Tuple[str, ...], List[str], str], prefix=' ', config: Op
|
||||||
|
|
||||||
|
|
||||||
# Dependency Metadata Helpers
|
# 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"""
|
"""check the presence and return valid version line of a specified binary"""
|
||||||
|
|
||||||
abspath = bin_path(binary)
|
abspath = bin_path(binary)
|
||||||
|
@ -834,11 +834,21 @@ def bin_version(binary: Optional[str]) -> Optional[str]:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bin_env = os.environ | {'LANG': 'C'}
|
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:
|
if not version_str:
|
||||||
version_str = run([abspath, "--version"], stdout=PIPE).stdout.strip().decode()
|
version_str = run(cmd or [abspath, "--version"], shell=is_cmd_str, stdout=PIPE, stderr=STDOUT).stdout.strip().decode()
|
||||||
# take first 3 columns of first line of version info
|
|
||||||
return ' '.join(version_str.split('\n')[0].strip().split()[:3])
|
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:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
# stderr(f'[X] Unable to find working version of dependency: {binary}', color='red')
|
# stderr(f'[X] Unable to find working version of dependency: {binary}', color='red')
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
__package__ = 'archivebox.core'
|
__package__ = 'archivebox.core'
|
||||||
|
|
||||||
|
default_app_config = 'core.apps.CoreAppConfig'
|
|
@ -12,6 +12,7 @@ from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.auth.models import Group, Permission
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from ..util import htmldecode, urldecode, ansi_to_html
|
from ..util import htmldecode, urldecode, ansi_to_html
|
||||||
|
@ -436,6 +437,8 @@ class ArchiveBoxAdmin(admin.AdminSite):
|
||||||
|
|
||||||
admin.site = ArchiveBoxAdmin()
|
admin.site = ArchiveBoxAdmin()
|
||||||
admin.site.register(get_user_model())
|
admin.site.register(get_user_model())
|
||||||
|
admin.site.register(Group)
|
||||||
|
admin.site.register(Permission)
|
||||||
admin.site.register(Snapshot, SnapshotAdmin)
|
admin.site.register(Snapshot, SnapshotAdmin)
|
||||||
admin.site.register(Tag, TagAdmin)
|
admin.site.register(Tag, TagAdmin)
|
||||||
admin.site.register(ArchiveResult, ArchiveResultAdmin)
|
admin.site.register(ArchiveResult, ArchiveResultAdmin)
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class CoreConfig(AppConfig):
|
class CoreAppConfig(AppConfig):
|
||||||
name = 'core'
|
name = 'core'
|
||||||
|
# label = 'Archive Data'
|
||||||
|
verbose_name = "Archive Data"
|
||||||
|
|
||||||
# WIP: broken by Django 3.1.2 -> 4.0 migration
|
# WIP: broken by Django 3.1.2 -> 4.0 migration
|
||||||
default_auto_field = 'django.db.models.UUIDField'
|
default_auto_field = 'django.db.models.UUIDField'
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Tag(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "Tag"
|
verbose_name = "Tag"
|
||||||
verbose_name_plural = "Tags"
|
verbose_name_plural = "🏷️ Tags"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -98,6 +98,10 @@ class Snapshot(models.Model):
|
||||||
|
|
||||||
keys = ('url', 'timestamp', 'title', 'tags', 'updated')
|
keys = ('url', 'timestamp', 'title', 'tags', 'updated')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "Snapshot"
|
||||||
|
verbose_name_plural = "⭐️ Archived Webpages (Snapshots)"
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
title = self.title or '-'
|
title = self.title or '-'
|
||||||
return f'[{self.timestamp}] {self.url[:64]} ({title[:64]})'
|
return f'[{self.timestamp}] {self.url[:64]} ({title[:64]})'
|
||||||
|
@ -282,5 +286,9 @@ class ArchiveResult(models.Model):
|
||||||
|
|
||||||
objects = ArchiveResultManager()
|
objects = ArchiveResultManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "ArchiveResult"
|
||||||
|
verbose_name_plural = "📑 Logs (ArchiveResults)"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.extractor
|
return self.extractor
|
||||||
|
|
1
archivebox/plugins/defaults/__init__.py
Normal file
1
archivebox/plugins/defaults/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'plugins.defaults.apps.DefaultsPluginAppConfig'
|
|
@ -8,11 +8,10 @@ from .models import (
|
||||||
|
|
||||||
|
|
||||||
class DependencyAdmin(SingletonModelAdmin):
|
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):
|
class ExtractorAdmin(SingletonModelAdmin):
|
||||||
# readonly_fields = ('REQUIRED', 'ENABLED', 'BINARY', 'ARGS', 'bin_path', 'bin_version', 'is_valid', 'is_enabled')
|
readonly_fields = ('id', 'NAME', 'LABEL', 'DEFAULT_ENABLED', 'DEFAULT_CMD', 'CMD', 'ARGS', 'TIMEOUT', 'dependency', 'is_valid', 'is_enabled')
|
||||||
pass
|
|
||||||
|
|
||||||
print('DefaultsPluginConfig.admin')
|
print('DefaultsPluginConfig.admin')
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
__package__ = 'archivebox.plugins.defaults'
|
# __package__ = 'archivebox.plugins.defaults'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class DefaultsPluginConfig(AppConfig):
|
class DefaultsPluginAppConfig(AppConfig):
|
||||||
label = "ArchiveBox Defaults"
|
name = "plugins.defaults"
|
||||||
name = "defaults"
|
|
||||||
|
# label = "ArchiveBox Defaults"
|
||||||
|
verbose_name = "Plugin Configuration Defaults"
|
||||||
|
|
||||||
default_auto_field = "django.db.models.AutoField"
|
default_auto_field = "django.db.models.AutoField"
|
||||||
|
|
||||||
|
|
|
@ -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
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ class Migration(migrations.Migration):
|
||||||
('id', models.AutoField(default=1, primary_key=True, serialize=False)),
|
('id', models.AutoField(default=1, primary_key=True, serialize=False)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Dependency Configuration Defaults',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -33,6 +34,7 @@ class Migration(migrations.Migration):
|
||||||
('id', models.AutoField(default=1, primary_key=True, serialize=False)),
|
('id', models.AutoField(default=1, primary_key=True, serialize=False)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Extractor Configuration Defaults',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -10,17 +10,20 @@ from django.utils.functional import cached_property
|
||||||
|
|
||||||
from solo.models import SingletonModel
|
from solo.models import SingletonModel
|
||||||
|
|
||||||
|
|
||||||
|
from config import bin_path, bin_version
|
||||||
|
|
||||||
ConfigDict = Dict[str, Any]
|
ConfigDict = Dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
def bin_path(binary: str) -> str | None:
|
# def bin_path(binary: str) -> str | None:
|
||||||
return shutil.which(str(Path(binary).expanduser())) or shutil.which(str(binary)) or binary
|
# 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:
|
# def bin_version(bin_path: str, cmd: str | None=None) -> str | None:
|
||||||
return '0.0.0'
|
# return '0.0.0'
|
||||||
|
|
||||||
|
|
||||||
class ArchiveBoxBaseDependency(SingletonModel):
|
class ArchiveBoxBaseDependency(models.Model):
|
||||||
singleton_instance_id = 1
|
singleton_instance_id = 1
|
||||||
|
|
||||||
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
||||||
|
@ -37,11 +40,11 @@ class ArchiveBoxBaseDependency(SingletonModel):
|
||||||
PIP_DEPENDENCIES = []
|
PIP_DEPENDENCIES = []
|
||||||
NPM_DEPENDENCIES = []
|
NPM_DEPENDENCIES = []
|
||||||
|
|
||||||
DEFAULT_BINARY = '/bin/false'
|
DEFAULT_BINARY = '/bin/bash'
|
||||||
DEFAULT_START_CMD = '/bin/false'
|
DEFAULT_START_CMD = '/bin/bash -c "while true; do sleep 1; done"'
|
||||||
DEFAULT_PID_FILE = 'logs/{NAME}_WORKER.pid'
|
DEFAULT_PID_FILE = 'logs/{NAME}_WORKER.pid'
|
||||||
DEFAULT_STOP_CMD = 'kill "$(<{PID_FILE})"'
|
DEFAULT_STOP_CMD = 'kill "$(<{PID_FILE})"'
|
||||||
DEFAULT_VERSION_COMMAND = '{CMD} --version'
|
DEFAULT_VERSION_COMMAND = '{BINARY} --version'
|
||||||
DEFAULT_ARGS = ''
|
DEFAULT_ARGS = ''
|
||||||
|
|
||||||
VERSION_CMD = '{BINARY} --version'
|
VERSION_CMD = '{BINARY} --version'
|
||||||
|
@ -58,7 +61,7 @@ class ArchiveBoxBaseDependency(SingletonModel):
|
||||||
app_label = 'defaults'
|
app_label = 'defaults'
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{self.LABEL} Dependency Configuration"
|
return f"{self.LABEL} Dependency Configuration"
|
||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
return {
|
return {
|
||||||
|
@ -79,7 +82,9 @@ class ArchiveBoxBaseDependency(SingletonModel):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def bin_version(self):
|
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
|
@cached_property
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
|
@ -157,12 +162,15 @@ class ArchiveBoxDefaultDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
|
|
||||||
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
||||||
|
|
||||||
|
ENABLED = models.BooleanField(default=True, editable=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'defaults'
|
app_label = 'defaults'
|
||||||
|
verbose_name = 'Default Configuration: Dependencies'
|
||||||
|
|
||||||
|
|
||||||
class ArchiveBoxBaseExtractor(SingletonModel):
|
class ArchiveBoxBaseExtractor(models.Model):
|
||||||
singleton_instance_id = 1
|
singleton_instance_id = 1
|
||||||
|
|
||||||
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
||||||
|
@ -258,7 +266,7 @@ class ArchiveBoxBaseExtractor(SingletonModel):
|
||||||
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
assert self.is_valid
|
# assert self.is_valid
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
result = super().save(*args, **kwargs)
|
result = super().save(*args, **kwargs)
|
||||||
|
@ -356,6 +364,11 @@ class ArchiveBoxDefaultExtractor(ArchiveBoxBaseExtractor, SingletonModel):
|
||||||
|
|
||||||
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
id = models.AutoField(default=singleton_instance_id, primary_key=True)
|
||||||
|
|
||||||
|
DEPENDENCY = ArchiveBoxDefaultDependency
|
||||||
|
|
||||||
|
ENABLED = models.BooleanField(default=True, editable=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'defaults'
|
app_label = 'defaults'
|
||||||
|
verbose_name = 'Default Configuration: Extractors'
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
def register_plugin_settings(settings=settings, name='defaults'):
|
def register_plugin_settings(settings=settings, name='defaults'):
|
||||||
|
|
||||||
settings.STATICFILES_DIRS += [
|
settings.STATICFILES_DIRS += [
|
||||||
str(Path(PACKAGE_DIR) / f'plugins/{name}/static'),
|
str(Path(settings.PACKAGE_DIR) / f'plugins/{name}/static'),
|
||||||
]
|
]
|
||||||
|
|
||||||
settings.TEMPLATE_DIRS += [
|
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)
|
print('REGISTERED PLUGIN SETTINGS', name)
|
1
archivebox/plugins/system/__init__.py
Normal file
1
archivebox/plugins/system/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'plugins.system.apps.SystemPluginAppConfig'
|
|
@ -5,6 +5,9 @@ from plugins.defaults.admin import DependencyAdmin, ExtractorAdmin
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
BashEnvironmentDependency,
|
BashEnvironmentDependency,
|
||||||
|
PythonEnvironmentDependency,
|
||||||
|
NodeJSEnvironmentDependency,
|
||||||
|
|
||||||
AptEnvironmentDependency,
|
AptEnvironmentDependency,
|
||||||
BrewEnvironmentDependency,
|
BrewEnvironmentDependency,
|
||||||
PipEnvironmentDependency,
|
PipEnvironmentDependency,
|
||||||
|
@ -20,8 +23,20 @@ from .models import (
|
||||||
|
|
||||||
print('DefaultsPluginConfig.admin')
|
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(AptEnvironmentDependency, DependencyAdmin)
|
||||||
admin.site.register(BrewEnvironmentDependency, DependencyAdmin)
|
admin.site.register(BrewEnvironmentDependency, DependencyAdmin)
|
||||||
admin.site.register(PipEnvironmentDependency, DependencyAdmin)
|
admin.site.register(PipEnvironmentDependency, DependencyAdmin)
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class SystemPluginConfig(AppConfig):
|
class SystemPluginAppConfig(AppConfig):
|
||||||
label = "ArchiveBox System"
|
name = "plugins.system"
|
||||||
name = "system"
|
# label = "ArchiveBox System"
|
||||||
|
verbose_name = "Host System Configuration"
|
||||||
|
|
||||||
default_auto_field = "django.db.models.AutoField"
|
default_auto_field = "django.db.models.AutoField"
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ class SystemPluginConfig(AppConfig):
|
||||||
|
|
||||||
from django.conf import settings
|
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)
|
register_plugin_settings(settings, name=self.name)
|
||||||
|
|
||||||
|
|
|
@ -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
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default='-qq', max_length=255)),
|
('ARGS', models.CharField(default='-qq', max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Package Manager: apt',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -32,6 +33,7 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
|
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Internal Dependency: ArchiveBox Package',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -44,6 +46,7 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default='-c', max_length=255)),
|
('ARGS', models.CharField(default='-c', max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Shell Environment: bash',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -56,6 +59,7 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default='', max_length=255)),
|
('ARGS', models.CharField(default='', max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Package Manager: brew',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -68,6 +72,20 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
|
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
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,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -80,6 +98,7 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default='', max_length=255)),
|
('ARGS', models.CharField(default='', max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Package Manager: npm',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -92,6 +111,20 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default='', max_length=255)),
|
('ARGS', models.CharField(default='', max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
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,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -104,6 +137,7 @@ class Migration(migrations.Migration):
|
||||||
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
|
('ARGS', models.CharField(default=[], editable=False, max_length=255)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name': 'Internal Dependency: SQLite3 Package',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -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'},
|
||||||
|
),
|
||||||
|
]
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,7 +6,7 @@ import shutil
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
import django
|
import django
|
||||||
import sqlite3
|
from sqlite3 import dbapi2 as sqlite3
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Dict, Any
|
from typing import List, Dict, Any
|
||||||
|
@ -16,12 +16,14 @@ from django.utils.functional import cached_property
|
||||||
|
|
||||||
from solo.models import SingletonModel
|
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]
|
ConfigDict = Dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
class BashEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
class BashEnvironmentDependency(ArchiveBoxBaseDependency):
|
||||||
singleton_instance_id = 1
|
singleton_instance_id = 1
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
|
@ -43,6 +45,53 @@ class BashEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
DEFAULT_STOP_CMD = None
|
DEFAULT_STOP_CMD = None
|
||||||
DEFAULT_PID_FILE = None
|
DEFAULT_PID_FILE = None
|
||||||
DEFAULT_ARGS = '-c'
|
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'
|
VERSION_CMD = '{BINARY} --version'
|
||||||
|
|
||||||
ENABLED = models.BooleanField(default=True, editable=not REQUIRED)
|
ENABLED = models.BooleanField(default=True, editable=not REQUIRED)
|
||||||
|
@ -55,15 +104,44 @@ class BashEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Shell Environment: python3"
|
||||||
|
|
||||||
# @task
|
class NodeJSEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
def install_pkgs(self, os_pkgs=()):
|
singleton_instance_id = 1
|
||||||
assert self.is_valid, 'Bash environment is not available on this host'
|
|
||||||
|
|
||||||
for os_dependency in os_pkgs:
|
id = models.AutoField(primary_key=True)
|
||||||
assert bin_path(os_dependency)
|
|
||||||
|
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):
|
class AptEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
singleton_instance_id = 1
|
singleton_instance_id = 1
|
||||||
|
@ -95,6 +173,7 @@ class AptEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Package Manager: apt"
|
||||||
|
|
||||||
# @task
|
# @task
|
||||||
def install_pkgs(self, apt_pkgs=()):
|
def install_pkgs(self, apt_pkgs=()):
|
||||||
|
@ -136,6 +215,7 @@ class BrewEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Package Manager: brew"
|
||||||
|
|
||||||
# @task
|
# @task
|
||||||
def install_pkgs(self, brew_pkgs=()):
|
def install_pkgs(self, brew_pkgs=()):
|
||||||
|
@ -182,6 +262,7 @@ class PipEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Package Manager: pip"
|
||||||
|
|
||||||
# @task
|
# @task
|
||||||
def install_pkgs(self, pip_pkgs=()):
|
def install_pkgs(self, pip_pkgs=()):
|
||||||
|
@ -224,6 +305,7 @@ class NPMEnvironmentDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Package Manager: npm"
|
||||||
|
|
||||||
# @task
|
# @task
|
||||||
def install_pkgs(self, npm_pkgs=()):
|
def install_pkgs(self, npm_pkgs=()):
|
||||||
|
@ -266,6 +348,7 @@ class DjangoDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Internal Dependency: django"
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def bin_path(self):
|
def bin_path(self):
|
||||||
|
@ -273,7 +356,7 @@ class DjangoDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def bin_version(self):
|
def bin_version(self):
|
||||||
return django.VERSION
|
return '.'.join(str(v) for v in django.VERSION[:3])
|
||||||
|
|
||||||
|
|
||||||
class SQLiteDependency(ArchiveBoxBaseDependency, SingletonModel):
|
class SQLiteDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
|
@ -307,6 +390,7 @@ class SQLiteDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Internal Dependency: sqlite3"
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def bin_path(self):
|
def bin_path(self):
|
||||||
|
@ -316,7 +400,7 @@ class SQLiteDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
def bin_version(self):
|
def bin_version(self):
|
||||||
return sqlite3.version
|
return sqlite3.version
|
||||||
|
|
||||||
class ArchiveBoxDependency(ArchiveBoxBaseDependency, SingletonModel):
|
class ArchiveBoxDependency(ArchiveBoxBaseDependency):
|
||||||
singleton_instance_id = 1
|
singleton_instance_id = 1
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
|
@ -349,6 +433,7 @@ class ArchiveBoxDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
app_label = 'system'
|
app_label = 'system'
|
||||||
|
verbose_name = "Internal Dependency: archivebox"
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def bin_path(self):
|
def bin_path(self):
|
||||||
|
@ -357,5 +442,5 @@ class ArchiveBoxDependency(ArchiveBoxBaseDependency, SingletonModel):
|
||||||
@cached_property
|
@cached_property
|
||||||
def bin_version(self):
|
def bin_version(self):
|
||||||
# return config['VERSION']
|
# return config['VERSION']
|
||||||
return '0.7.3+editable'
|
return VERSION
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue