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 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')

View file

@ -1 +1,3 @@
__package__ = 'archivebox.core' __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.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)

View file

@ -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'

View file

@ -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

View file

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

View file

@ -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')

View file

@ -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"

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 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,
}, },
), ),

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 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'

View file

@ -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)

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 ( 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)

View file

@ -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)

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 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,
}, },
), ),

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 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