Allow callable in configuration for plugin.type

Example:

```python3
\# Load default configuration
my_config = config.load()

\# Pass a class directly
my_config.update({"auth": {"type": MyAuth}})

\# Pass an object directly
my_rights = MyRights()
my_config.update({"rights": {"type": lambda config: my_rights}})

app = Application(my_config)
````
This commit is contained in:
Unrud 2020-01-15 03:20:48 +01:00
parent 72f8b29190
commit 9c622b57d5
3 changed files with 20 additions and 4 deletions

View File

@ -81,6 +81,12 @@ def list_of_ip_address(value):
return [ip_address(s.strip()) for s in value.split(",")] return [ip_address(s.strip()) for s in value.split(",")]
def str_or_callable(value):
if callable(value):
return value
return str(value)
def unspecified_type(value): def unspecified_type(value):
return value return value
@ -150,7 +156,7 @@ DEFAULT_CONFIG_SCHEMA = OrderedDict([
("type", { ("type", {
"value": "none", "value": "none",
"help": "authentication method", "help": "authentication method",
"type": str, "type": str_or_callable,
"internal": auth.INTERNAL_TYPES}), "internal": auth.INTERNAL_TYPES}),
("htpasswd_filename", { ("htpasswd_filename", {
"value": "/etc/radicale/users", "value": "/etc/radicale/users",
@ -172,7 +178,7 @@ DEFAULT_CONFIG_SCHEMA = OrderedDict([
("type", { ("type", {
"value": "owner_only", "value": "owner_only",
"help": "rights backend", "help": "rights backend",
"type": str, "type": str_or_callable,
"internal": rights.INTERNAL_TYPES}), "internal": rights.INTERNAL_TYPES}),
("file", { ("file", {
"value": "/etc/radicale/rights", "value": "/etc/radicale/rights",
@ -182,7 +188,7 @@ DEFAULT_CONFIG_SCHEMA = OrderedDict([
("type", { ("type", {
"value": "multifilesystem", "value": "multifilesystem",
"help": "storage backend", "help": "storage backend",
"type": str, "type": str_or_callable,
"internal": storage.INTERNAL_TYPES}), "internal": storage.INTERNAL_TYPES}),
("filesystem_folder", { ("filesystem_folder", {
"value": "/var/lib/radicale/collections", "value": "/var/lib/radicale/collections",
@ -204,7 +210,7 @@ DEFAULT_CONFIG_SCHEMA = OrderedDict([
("type", { ("type", {
"value": "internal", "value": "internal",
"help": "web interface backend", "help": "web interface backend",
"type": str, "type": str_or_callable,
"internal": web.INTERNAL_TYPES})])), "internal": web.INTERNAL_TYPES})])),
("logging", OrderedDict([ ("logging", OrderedDict([
("level", { ("level", {

View File

@ -30,6 +30,7 @@ import tempfile
import defusedxml.ElementTree as DefusedET import defusedxml.ElementTree as DefusedET
import pytest import pytest
import radicale.tests.custom.storage_simple_sync
from radicale import Application, config, storage, xmlutils from radicale import Application, config, storage, xmlutils
from radicale.tests import BaseTest from radicale.tests import BaseTest
from radicale.tests.helpers import get_file_content from radicale.tests.helpers import get_file_content
@ -1495,3 +1496,9 @@ class TestCustomStorageSystem(BaseFileSystemTest):
if s.startswith("test_") and ("_sync_" in s or s.endswith("_sync")): if s.startswith("test_") and ("_sync_" in s or s.endswith("_sync")):
locals()[s] = getattr(BaseRequestsMixIn, s) locals()[s] = getattr(BaseRequestsMixIn, s)
del s del s
class TestCustomStorageSystemCallable(BaseFileSystemTest):
"""Test custom backend loading with ``callable``."""
storage_type = radicale.tests.custom.storage_simple_sync.Storage
test_add_event = BaseRequestsMixIn.test_add_event

View File

@ -23,6 +23,9 @@ from radicale.log import logger
def load_plugin(internal_types, module_name, class_name, configuration): def load_plugin(internal_types, module_name, class_name, configuration):
type_ = configuration.get(module_name, "type") type_ = configuration.get(module_name, "type")
if callable(type_):
logger.info("%s type is %r", module_name, type_)
return type_(configuration)
if type_ in internal_types: if type_ in internal_types:
module = "radicale.%s.%s" % (module_name, type_) module = "radicale.%s.%s" % (module_name, type_)
else: else: