mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2025-05-21 10:25:11 -04:00
migrate plugin loading process to new pluggy-powered system based on djp
This commit is contained in:
parent
efd341d8ad
commit
8ed3155ec5
28 changed files with 690 additions and 321 deletions
|
@ -1,11 +1,12 @@
|
|||
__package__ = "archivebox.plugantic"
|
||||
|
||||
import abx
|
||||
from typing import List
|
||||
|
||||
from django.core.checks import Warning, Tags, register
|
||||
|
||||
from .base_hook import BaseHook, HookType
|
||||
from ..config_stubs import AttrDict
|
||||
|
||||
|
||||
class BaseCheck(BaseHook):
|
||||
hook_type: HookType = "CHECK"
|
||||
|
@ -28,21 +29,18 @@ class BaseCheck(BaseHook):
|
|||
def register(self, settings, parent_plugin=None):
|
||||
# self._plugin = parent_plugin # backref to parent is for debugging only, never rely on this!
|
||||
|
||||
self.register_with_django_check_system(settings) # (SIDE EFFECT)
|
||||
abx.pm.hook.register_django_check(check=self, settings=settings)
|
||||
|
||||
# install hook into settings.CHECKS
|
||||
settings.CHECKS = getattr(settings, "CHECKS", None) or AttrDict({})
|
||||
settings.CHECKS[self.id] = self
|
||||
|
||||
# record installed hook in settings.HOOKS
|
||||
super().register(settings, parent_plugin=parent_plugin)
|
||||
|
||||
def register_with_django_check_system(self, settings):
|
||||
def run_check(app_configs, **kwargs) -> List[Warning]:
|
||||
import logging
|
||||
return self.check(settings, logging.getLogger("checks"))
|
||||
@abx.hookspec
|
||||
@abx.hookimpl
|
||||
def register_django_check(check: BaseCheck, settings):
|
||||
def run_check(app_configs, **kwargs) -> List[Warning]:
|
||||
import logging
|
||||
return check.check(settings, logging.getLogger("checks"))
|
||||
|
||||
run_check.__name__ = self.id
|
||||
run_check.tags = [self.tag]
|
||||
register(self.tag)(run_check)
|
||||
run_check.__name__ = check.id
|
||||
run_check.tags = [check.tag]
|
||||
register(check.tag)(run_check)
|
||||
|
||||
|
|
|
@ -227,26 +227,34 @@ class ArchiveBoxBaseConfig(BaseSettings):
|
|||
print(f' {key}={original_value} -> {value}')
|
||||
self.__init__()
|
||||
return self
|
||||
|
||||
def as_legacy_config_schema(self):
|
||||
# shim for backwards compatibility with old config schema style
|
||||
model_values = self.model_dump()
|
||||
return benedict({
|
||||
key: {'type': field.annotation, 'default': model_values[key]}
|
||||
for key, field in self.model_fields.items()
|
||||
})
|
||||
|
||||
class BaseConfigSet(ArchiveBoxBaseConfig, BaseHook): # type: ignore[type-arg]
|
||||
hook_type: ClassVar[HookType] = 'CONFIG'
|
||||
|
||||
section: ClassVar[ConfigSectionName] = 'GENERAL_CONFIG'
|
||||
|
||||
def register(self, settings, parent_plugin=None):
|
||||
# self._plugin = parent_plugin # for debugging only, never rely on this!
|
||||
# def register(self, settings, parent_plugin=None):
|
||||
# # self._plugin = parent_plugin # for debugging only, never rely on this!
|
||||
|
||||
# settings.FLAT_CONFIG = benedict(getattr(settings, "FLAT_CONFIG", settings.CONFIG))
|
||||
# # pass FLAT_CONFIG so far into our config model to load it
|
||||
# loaded_config = self.__class__(**settings.FLAT_CONFIG)
|
||||
# # then dump our parsed config back into FLAT_CONFIG for the next plugin to use
|
||||
# settings.FLAT_CONFIG.merge(loaded_config.model_dump(include=set(self.model_fields.keys())))
|
||||
# settings.FLAT_CONFIG = benedict(getattr(settings, "FLAT_CONFIG", {}))
|
||||
# # pass FLAT_CONFIG so far into our config model to load it
|
||||
# loaded_config = self
|
||||
# # then dump our parsed config back into FLAT_CONFIG for the next plugin to use
|
||||
# settings.FLAT_CONFIG.merge(loaded_config.model_dump(include=set(self.model_fields.keys())))
|
||||
|
||||
settings.CONFIGS = getattr(settings, "CONFIGS", None) or benedict({})
|
||||
settings.CONFIGS[self.id] = self
|
||||
self._original_id = id(self)
|
||||
# settings.REGISTERED_CONFIGS = getattr(settings, "REGISTERED_CONFIGS", None) or benedict({})
|
||||
# settings.REGISTERED_CONFIGS[self.id] = self
|
||||
# self._original_id = id(self)
|
||||
|
||||
super().register(settings, parent_plugin=parent_plugin)
|
||||
# super().register(settings, parent_plugin=parent_plugin)
|
||||
|
||||
# def ready(self, settings):
|
||||
# # reload config from environment, in case it's been changed by any other plugins
|
||||
|
|
|
@ -96,32 +96,32 @@ class BaseHook(BaseModel):
|
|||
# e.g. /admin/environment/config/LdapConfig/
|
||||
return f"/admin/environment/{self.hook_type.lower()}/{self.id}/"
|
||||
|
||||
def register(self, settings, parent_plugin=None):
|
||||
"""Load a record of an installed hook into global Django settings.HOOKS at runtime."""
|
||||
self._plugin = parent_plugin # for debugging only, never rely on this!
|
||||
# def register(self, settings, parent_plugin=None):
|
||||
# """Load a record of an installed hook into global Django settings.HOOKS at runtime."""
|
||||
# self._plugin = parent_plugin # for debugging only, never rely on this!
|
||||
|
||||
# assert json.dumps(self.model_json_schema(), indent=4), f"Hook {self.hook_module} has invalid JSON schema."
|
||||
# # assert json.dumps(self.model_json_schema(), indent=4), f"Hook {self.hook_module} has invalid JSON schema."
|
||||
|
||||
# print(' -', self.hook_module, '.register()')
|
||||
# # print(' -', self.hook_module, '.register()')
|
||||
|
||||
# record installed hook in settings.HOOKS
|
||||
settings.HOOKS[self.id] = self
|
||||
# # record installed hook in settings.HOOKS
|
||||
# settings.REGISTERED_HOOKS[self.id] = self
|
||||
|
||||
if settings.HOOKS[self.id]._is_registered:
|
||||
raise Exception(f"Tried to run {self.hook_module}.register() but its already been called!")
|
||||
# if settings.REGISTERED_HOOKS[self.id]._is_registered:
|
||||
# raise Exception(f"Tried to run {self.hook_module}.register() but its already been called!")
|
||||
|
||||
settings.HOOKS[self.id]._is_registered = True
|
||||
# settings.REGISTERED_HOOKS[self.id]._is_registered = True
|
||||
|
||||
# print("REGISTERED HOOK:", self.hook_module)
|
||||
# # print("REGISTERED HOOK:", self.hook_module)
|
||||
|
||||
def ready(self, settings):
|
||||
"""Runs any runtime code needed when AppConfig.ready() is called (after all models are imported)."""
|
||||
# def ready(self, settings):
|
||||
# """Runs any runtime code needed when AppConfig.ready() is called (after all models are imported)."""
|
||||
|
||||
# print(' -', self.hook_module, '.ready()')
|
||||
# # print(' -', self.hook_module, '.ready()')
|
||||
|
||||
assert self.id in settings.HOOKS, f"Tried to ready hook {self.hook_module} but it is not registered in settings.HOOKS."
|
||||
# assert self.id in settings.REGISTERED_HOOKS, f"Tried to ready hook {self.hook_module} but it is not registered in settings.REGISTERED_HOOKS."
|
||||
|
||||
if settings.HOOKS[self.id]._is_ready:
|
||||
raise Exception(f"Tried to run {self.hook_module}.ready() but its already been called!")
|
||||
# if settings.REGISTERED_HOOKS[self.id]._is_ready:
|
||||
# raise Exception(f"Tried to run {self.hook_module}.ready() but its already been called!")
|
||||
|
||||
settings.HOOKS[self.id]._is_ready = True
|
||||
# settings.REGISTERED_HOOKS[self.id]._is_ready = True
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
__package__ = 'archivebox.plugantic'
|
||||
|
||||
import abx
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
|
||||
|
@ -21,9 +22,6 @@ from benedict import benedict
|
|||
|
||||
from .base_hook import BaseHook, HookType
|
||||
|
||||
from ..config import bump_startup_progress_bar
|
||||
|
||||
|
||||
class BasePlugin(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
extra='forbid',
|
||||
|
@ -107,9 +105,10 @@ class BasePlugin(BaseModel):
|
|||
|
||||
default_auto_field = 'django.db.models.AutoField'
|
||||
|
||||
def ready(self):
|
||||
from django.conf import settings
|
||||
plugin_self.ready(settings)
|
||||
# handled by abx.hookimpl ready()
|
||||
# def ready(self):
|
||||
# from django.conf import settings
|
||||
# plugin_self.ready(settings)
|
||||
|
||||
return PluginAppConfig
|
||||
|
||||
|
@ -125,64 +124,60 @@ class BasePlugin(BaseModel):
|
|||
hooks[hook.hook_type][hook.id] = hook
|
||||
return hooks
|
||||
|
||||
def register(self, settings=None):
|
||||
def register(self, settings):
|
||||
"""Loads this plugin's configs, binaries, extractors, and replayers into global Django settings at import time (before models are imported or any AppConfig.ready() are called)."""
|
||||
|
||||
if settings is None:
|
||||
from django.conf import settings as django_settings
|
||||
settings = django_settings
|
||||
|
||||
# print()
|
||||
# print(self.plugin_module_full, '.register()')
|
||||
from ..config import bump_startup_progress_bar
|
||||
|
||||
# assert json.dumps(self.model_json_schema(), indent=4), f'Plugin {self.plugin_module} has invalid JSON schema.'
|
||||
# assert settings.PLUGINS[self.id] == self
|
||||
# # assert self.id not in settings.PLUGINS, f'Tried to register plugin {self.plugin_module} but it conflicts with existing plugin of the same name ({self.app_label}).'
|
||||
|
||||
assert self.id not in settings.PLUGINS, f'Tried to register plugin {self.plugin_module} but it conflicts with existing plugin of the same name ({self.app_label}).'
|
||||
# ### Mutate django.conf.settings... values in-place to include plugin-provided overrides
|
||||
|
||||
### Mutate django.conf.settings... values in-place to include plugin-provided overrides
|
||||
settings.PLUGINS[self.id] = self
|
||||
# if settings.PLUGINS[self.id]._is_registered:
|
||||
# raise Exception(f"Tried to run {self.plugin_module}.register() but its already been called!")
|
||||
|
||||
if settings.PLUGINS[self.id]._is_registered:
|
||||
raise Exception(f"Tried to run {self.plugin_module}.register() but its already been called!")
|
||||
# for hook in self.hooks:
|
||||
# hook.register(settings, parent_plugin=self)
|
||||
|
||||
for hook in self.hooks:
|
||||
hook.register(settings, parent_plugin=self)
|
||||
|
||||
settings.PLUGINS[self.id]._is_registered = True
|
||||
# print('√ REGISTERED PLUGIN:', self.plugin_module)
|
||||
# settings.PLUGINS[self.id]._is_registered = True
|
||||
# # print('√ REGISTERED PLUGIN:', self.plugin_module)
|
||||
bump_startup_progress_bar()
|
||||
|
||||
def ready(self, settings=None):
|
||||
"""Runs any runtime code needed when AppConfig.ready() is called (after all models are imported)."""
|
||||
|
||||
if settings is None:
|
||||
from django.conf import settings as django_settings
|
||||
settings = django_settings
|
||||
from ..config import bump_startup_progress_bar
|
||||
|
||||
# print()
|
||||
# print(self.plugin_module_full, '.ready()')
|
||||
|
||||
assert (
|
||||
self.id in settings.PLUGINS and settings.PLUGINS[self.id]._is_registered
|
||||
), f"Tried to run plugin.ready() for {self.plugin_module} but plugin is not yet registered in settings.PLUGINS."
|
||||
# if settings is None:
|
||||
# from django.conf import settings as django_settings
|
||||
# settings = django_settings
|
||||
|
||||
if settings.PLUGINS[self.id]._is_ready:
|
||||
raise Exception(f"Tried to run {self.plugin_module}.ready() but its already been called!")
|
||||
# # print()
|
||||
# # print(self.plugin_module_full, '.ready()')
|
||||
|
||||
for hook in self.hooks:
|
||||
hook.ready(settings)
|
||||
# assert (
|
||||
# self.id in settings.PLUGINS and settings.PLUGINS[self.id]._is_registered
|
||||
# ), f"Tried to run plugin.ready() for {self.plugin_module} but plugin is not yet registered in settings.PLUGINS."
|
||||
|
||||
# if settings.PLUGINS[self.id]._is_ready:
|
||||
# raise Exception(f"Tried to run {self.plugin_module}.ready() but its already been called!")
|
||||
|
||||
# for hook in self.hooks:
|
||||
# hook.ready(settings)
|
||||
|
||||
settings.PLUGINS[self.id]._is_ready = True
|
||||
# settings.PLUGINS[self.id]._is_ready = True
|
||||
bump_startup_progress_bar()
|
||||
|
||||
# @validate_call
|
||||
# def install_binaries(self) -> Self:
|
||||
# new_binaries = []
|
||||
# for idx, binary in enumerate(self.binaries):
|
||||
# new_binaries.append(binary.install() or binary)
|
||||
# return self.model_copy(update={
|
||||
# 'binaries': new_binaries,
|
||||
# })
|
||||
@validate_call
|
||||
def install_binaries(self) -> Self:
|
||||
new_binaries = []
|
||||
for idx, binary in enumerate(self.binaries):
|
||||
new_binaries.append(binary.install() or binary)
|
||||
return self.model_copy(update={
|
||||
'binaries': new_binaries,
|
||||
})
|
||||
|
||||
@validate_call
|
||||
def load_binaries(self, cache=True) -> Self:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue