From f21abf62d4d1470c4deaec3ea8314ca64edbfc3e Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Tue, 21 Dec 2021 00:39:07 +0200 Subject: [PATCH] Simplify converter registration --- sanic/config.py | 29 ++++++++++++----------------- tests/test_config.py | 6 ++++-- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/sanic/config.py b/sanic/config.py index 7eb5ab94ae..d4057a71a1 100644 --- a/sanic/config.py +++ b/sanic/config.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections import deque from inspect import getmembers, isclass, isdatadescriptor from os import environ from pathlib import Path @@ -49,16 +48,6 @@ DEPRECATED_CONFIG = ("SERVER_RUNNING", "RELOADER_PROCESS", "RELOADED_FILES") -class CastRegistry(deque): - def add(self, cast: Callable[[str], Any]) -> None: - if cast in self: - error_logger.warning( - f"Type cast '{cast.__name__}' has already been registered" - ) - return None - self.appendleft(cast) - - class DescriptorMeta(type): def __init__(cls, *_): cls.__setters__ = {name for name, _ in getmembers(cls, cls._is_setter)} @@ -106,11 +95,12 @@ def __init__( defaults = defaults or {} super().__init__({**DEFAULT_CONFIG, **defaults}) - self._cast_registry = CastRegistry((int, float, str_to_bool, str)) + self._converters = [str, str_to_bool, float, int] self._LOGO = "" if converters: - self.register_type(*converters) + for converter in converters: + self.register_type(converter) if keep_alive is not None: self.KEEP_ALIVE = keep_alive @@ -244,7 +234,7 @@ def __init__(self, name) -> None: _, config_key = key.split(prefix, 1) - for converter in self._cast_registry: + for converter in reversed(self._converters): try: self[config_key] = converter(value) break @@ -320,11 +310,16 @@ class C: load = update_config - def register_type(self, *cast: Callable[[str], Any]) -> None: + def register_type(self, converter: Callable[[str], Any]) -> None: """ Allows for adding custom function to cast from a string value to any other type. The function should raise ValueError if it is not the correct type. """ - for item in cast: - self._cast_registry.add(item) + if converter in self._converters: + error_logger.warning( + f"Configuration value converter '{converter.__name__}' has " + "already been registered" + ) + return + self._converters.append(converter) diff --git a/tests/test_config.py b/tests/test_config.py index 41e36f105a..7c5bab05cd 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -158,14 +158,16 @@ def test_add_converter_multiple_times(caplog): def converter(): ... - message = "Type cast 'converter' has already been registered" + message = ( + "Configuration value converter 'converter' has already been registered" + ) config = Config() config.register_type(converter) with caplog.at_level(logging.WARNING): config.register_type(converter) assert ("sanic.error", logging.WARNING, message) in caplog.record_tuples - assert len(config._cast_registry) == 5 + assert len(config._converters) == 5 def test_load_from_file(app):