Beispiel #1
0
class TestConfigBase(ConfigBase):
    BOOL = BoolConfigEntry(key_path=["test", "bool"], default=False)
    STRING = StringConfigEntry(key_path=["test", "string"],
                               default="default value")
    REGEX = RegexConfigEntry(key_path=["test", "regex"],
                             default="^[a-zA-Z0-9]$")
    INT = IntConfigEntry(key_path=["test", "int"], default=100)
    FLOAT = FloatConfigEntry(key_path=["test", "float"], default=1.23)
    DATE = DateConfigEntry(
        key_path=["test", "this", "date", "is", "nested", "deep"],
        default=datetime.now())
    TIMEDELTA = TimeDeltaConfigEntry(
        key_path=["test", "this", "timediff", "is", "in", "this", "branch"],
        default=timedelta(seconds=10))
    FILE = FileConfigEntry(key_path=["test", "file"], )
    DIRECTORY = DirectoryConfigEntry(key_path=["test", "directory"], )
    RANGE = RangeConfigEntry(key_path=["test", "this", "is", "a", "range"],
                             default=Range(0, 100))
    DICT = DictConfigEntry(key_path=["dict"], schema=Schema({str: str}))

    DICT_LIST = ListConfigEntry(
        item_type=DictConfigEntry,
        item_args={"schema": Schema({str: str})},
        key_path=[
            "dict_list",
        ],
    )
    STRING_LIST = ListConfigEntry(item_type=StringConfigEntry,
                                  key_path=["test", "this", "is", "a", "list"],
                                  example=["these", "are", "test", "values"],
                                  secret=False)

    NONE_INT = IntConfigEntry(
        key_path=["none", "int"],
        default=None,
    )
    NONE_DATE = DateConfigEntry(
        key_path=["none", "date"],
        default=None,
    )

    SECRET_BOOL = BoolConfigEntry(key_path=["secret", "bool"],
                                  default=False,
                                  secret=True)
    SECRET_INT = IntConfigEntry(key_path=["secret", "int"],
                                default=None,
                                secret=True)
    SECRET_REGEX = RegexConfigEntry(key_path=["secret", "regex"],
                                    default=None,
                                    secret=True)
    SECRET_LIST = ListConfigEntry(item_type=RegexConfigEntry,
                                  key_path=["secret", "list"],
                                  default=["[a-zA-Z]*"],
                                  secret=True)
Beispiel #2
0
class Config(ConfigBase):
    def __new__(cls, *args, **kwargs):
        data_sources = [
            EnvSource(),
            YamlSource(FILE_NAME),
            TomlSource(FILE_NAME)
        ]
        kwargs["data_sources"] = data_sources
        return super(Config, cls).__new__(cls, *args, **kwargs)

    TELEGRAM_BOT_TOKEN = StringConfigEntry(
        key_path=[KEY_ROOT, KEY_TELEGRAM, "bot_token"],
        description="ID of the telegram chat to send messages to.",
        required=True,
        secret=True,
        example="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")

    TELEGRAM_CHAT_ID = StringConfigEntry(
        key_path=[KEY_ROOT, KEY_TELEGRAM, "chat_id"],
        description="ID of the telegram chat to send messages to.",
        required=True,
        secret=True,
        example="-123456789")

    RETRY_ENABLED = BoolConfigEntry(
        key_path=[KEY_ROOT, KEY_RETRY, "enabled"],
        description="Whether to retry sending messages or not.",
        default=True,
    )

    RETRY_TIMEOUT = TimeDeltaConfigEntry(
        key_path=[KEY_ROOT, KEY_RETRY, "timeout"],
        description="Timeout between tries.",
        default="10s",
    )

    RETRY_GIVE_UP_AFTER = TimeDeltaConfigEntry(
        key_path=[KEY_ROOT, KEY_RETRY, "give_up_after"],
        description="Time interval after which the retry should be cancelled.",
        default="1h",
    )
    def test_timedelta_entry(self):
        from datetime import timedelta

        config_entry = TimeDeltaConfigEntry(key_path=["timedelta"])
        input_output = [
            ("20:56:35", timedelta(hours=20, minutes=56, seconds=35)),
            ("32m", timedelta(minutes=32)),
            ("4h0m3s", timedelta(hours=4, minutes=0, seconds=3)),
            ("4h3s", timedelta(hours=4, minutes=0, seconds=3)),
            ("4:13", timedelta(hours=0, minutes=4, seconds=13)),
        ]

        self.assert_input_output(config_entry, input_output)
class Config(ConfigBase):

    def __new__(cls, *args, **kwargs):
        yaml_source = YamlSource(NODE_MAIN)
        toml_source = TomlSource(NODE_MAIN)
        data_sources = [
            EnvSource(),
            yaml_source,
            toml_source
        ]
        return super(Config, cls).__new__(cls, data_sources=data_sources)

    LOG_LEVEL = StringConfigEntry(
        description="Log level",
        key_path=[
            NODE_MAIN,
            "log_level"
        ],
        regex=re.compile(f"{'|'.join(logging._nameToLevel.keys())}", flags=re.IGNORECASE),
        default="WARNING",
    )

    TELEGRAM_BOT_TOKEN = StringConfigEntry(
        description="The telegram bot token to use",
        key_path=[
            NODE_MAIN,
            NODE_TELEGRAM,
            "bot_token"
        ],
        example="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
        secret=True,
        required=True
    )

    TELEGRAM_ADMIN_USERNAMES = ListConfigEntry(
        item_type=StringConfigEntry,
        key_path=[
            NODE_MAIN,
            NODE_TELEGRAM,
            "admin_usernames"
        ],
        required=True,
        example=[
            "myadminuser",
            "myotheradminuser"
        ]
    )

    TELEGRAM_CHAT_IDS = ListConfigEntry(
        item_type=StringConfigEntry,
        key_path=[
            NODE_MAIN,
            NODE_TELEGRAM,
            "chat_ids"
        ],
        required=True,
        example=[
            12345678,
            87654321
        ]
    )

    KEEL_HOST = StringConfigEntry(
        description="Hostname of the keel HTTP endpoint",
        key_path=[
            NODE_MAIN,
            NODE_KEEL,
            NODE_HOST
        ],
        default="localhost",
        required=True
    )

    KEEL_PORT = IntConfigEntry(
        description="Port of the keel HTTP endpoint",
        key_path=[
            NODE_MAIN,
            NODE_KEEL,
            NODE_PORT
        ],
        default=9300,
        required=True
    )

    KEEL_SSL = BoolConfigEntry(
        description="Whether to use HTTPS or not",
        key_path=[
            NODE_MAIN,
            NODE_KEEL,
            "ssl"
        ],
        default=True
    )

    KEEL_USER = StringConfigEntry(
        description="Keel basic auth username",
        key_path=[
            NODE_MAIN,
            NODE_KEEL,
            "username"
        ],
        required=True
    )

    KEEL_PASSWORD = StringConfigEntry(
        description="Keel basic auth password",
        key_path=[
            NODE_MAIN,
            NODE_KEEL,
            "password"
        ],
        required=True,
        secret=True
    )

    MONITOR_INTERVAL = TimeDeltaConfigEntry(
        description="Interval to check for new pending approvals",
        key_path=[
            NODE_MAIN,
            "monitor"
            "interval"
        ],
        default="1m",
        required=True,
    )

    STATS_ENABLED = BoolConfigEntry(
        description="Whether to enable prometheus statistics or not.",
        key_path=[
            NODE_MAIN,
            NODE_STATS,
            NODE_ENABLED
        ],
        default=True
    )

    STATS_PORT = IntConfigEntry(
        description="The port to expose statistics on.",
        key_path=[
            NODE_MAIN,
            NODE_STATS,
            NODE_PORT
        ],
        default=8000
    )
Beispiel #5
0
class Config(ConfigBase):
    def __new__(cls, *args, **kwargs):
        yaml_source = YamlSource(NODE_MAIN)
        toml_source = TomlSource(NODE_MAIN)
        data_sources = [EnvSource(), yaml_source, toml_source]
        return super(Config, cls).__new__(cls, data_sources=data_sources)

    LOG_LEVEL = StringConfigEntry(
        description="Log level",
        key_path=[NODE_MAIN, "log_level"],
        regex=re.compile(f"{'|'.join(logging._nameToLevel.keys())}",
                         flags=re.IGNORECASE),
        default="WARNING",
    )

    LOCALE = StringConfigEntry(
        description="Bot Locale",
        key_path=[NODE_MAIN, "locale"],
        default="en",
    )

    TELEGRAM_BOT_TOKEN = StringConfigEntry(
        description="The telegram bot token to use",
        key_path=[NODE_MAIN, NODE_TELEGRAM, "bot_token"],
        example="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
        secret=True)

    TELEGRAM_ADMIN_USERNAMES = ListConfigEntry(
        item_type=StringConfigEntry,
        key_path=[NODE_MAIN, NODE_TELEGRAM, "admin_usernames"],
        required=True,
        example=["myadminuser", "myotheradminuser"])

    GROCY_CACHE_DURATION = TimeDeltaConfigEntry(
        description="Duration to cache Grocy REST api call responses",
        key_path=[NODE_MAIN, NODE_GROCY, "cache_duration"],
        required=True,
        default="60s",
    )

    NOTIFICATION_CHAT_IDS = ListConfigEntry(
        item_type=StringConfigEntry,
        key_path=[NODE_MAIN, NODE_NOTIFICATION, "chat_ids"],
        default=[])

    GROCY_HOST = StringConfigEntry(
        description="Hostname of the Grocy instance",
        key_path=[NODE_MAIN, NODE_GROCY, NODE_HOST],
        required=True,
        default="127.0.0.1")

    GROCY_PORT = IntConfigEntry(description="Port of the Grocy REST api",
                                key_path=[NODE_MAIN, NODE_GROCY, NODE_PORT],
                                range=Range(1, 65535),
                                default=80)

    GROCY_API_KEY = StringConfigEntry(
        description="Grocy API Key used for REST authentication",
        key_path=[NODE_MAIN, NODE_GROCY, NODE_API_KEY],
        required=True,
        example="abcdefgh12345678",
        secret=True)

    STATS_ENABLED = BoolConfigEntry(
        description="Whether to enable prometheus statistics or not.",
        key_path=[NODE_MAIN, NODE_STATS, NODE_ENABLED],
        default=True)

    STATS_PORT = IntConfigEntry(
        description="The port to expose statistics on.",
        key_path=[NODE_MAIN, NODE_STATS, NODE_PORT],
        default=8000)
Beispiel #6
0
class DeduplicatorConfig(ConfigBase):
    def __new__(cls, *args, **kwargs):
        yaml_source = YamlSource("py_image_dedup")
        data_sources = [EnvSource(), yaml_source]
        return super(DeduplicatorConfig,
                     cls).__new__(cls, data_sources=data_sources)

    DRY_RUN = BoolConfigEntry(
        description="If enabled no source file will be touched",
        key_path=[NODE_MAIN, NODE_DRY_RUN],
        default=True)

    ELASTICSEARCH_HOST = StringConfigEntry(
        description="Hostname of the elasticsearch backend instance to use",
        key_path=[NODE_MAIN, NODE_ELASTICSEARCH, NODE_HOST],
        default="127.0.0.1")

    ELASTICSEARCH_PORT = IntConfigEntry(
        description="Hostname of the elasticsearch backend instance to use",
        key_path=[NODE_MAIN, NODE_ELASTICSEARCH, NODE_PORT],
        range=Range(1, 65535),
        default=9200)

    ELASTICSEARCH_MAX_DISTANCE = FloatConfigEntry(
        description=
        "Maximum signature distance [0..1] to query from elasticsearch backend.",
        key_path=[NODE_MAIN, NODE_ELASTICSEARCH, NODE_MAX_DISTANCE],
        default=0.10)

    ELASTICSEARCH_AUTO_CREATE_INDEX = BoolConfigEntry(
        description=
        "Whether to automatically create an index in the target database.",
        key_path=[NODE_MAIN, NODE_ELASTICSEARCH, NODE_AUTO_CREATE_INDEX],
        default=True)

    ELASTICSEARCH_INDEX = StringConfigEntry(
        description=
        "The index name to use for storing and querying image analysis data.",
        key_path=[NODE_MAIN, NODE_ELASTICSEARCH, NODE_INDEX],
        default="images")

    ANALYSIS_USE_EXIF_DATA = BoolConfigEntry(
        description="Whether to scan for EXIF data or not.",
        key_path=[NODE_MAIN, NODE_ANALYSIS, NODE_USE_EXIF_DATA],
        default=True)

    SOURCE_DIRECTORIES = ListConfigEntry(
        description=
        "Comma separated list of source paths to analyse and deduplicate.",
        item_type=DirectoryConfigEntry,
        item_args={"check_existence": True},
        key_path=[NODE_MAIN, NODE_ANALYSIS, NODE_SOURCE_DIRECTORIES],
        required=True,
        example=["/home/myuser/pictures/"])

    RECURSIVE = BoolConfigEntry(
        description="When set all directories will be recursively analyzed.",
        key_path=[NODE_MAIN, NODE_ANALYSIS, NODE_RECURSIVE],
        default=True)

    SEARCH_ACROSS_ROOT_DIRS = BoolConfigEntry(
        description=
        "When set duplicates will be found even if they are located in different root directories.",
        key_path=[NODE_MAIN, NODE_ANALYSIS, NODE_SEARCH_ACROSS_ROOT_DIRS],
        default=False)

    FILE_EXTENSION_FILTER = ListConfigEntry(
        description="Comma separated list of file extensions.",
        item_type=StringConfigEntry,
        key_path=[NODE_MAIN, NODE_ANALYSIS, NODE_FILE_EXTENSIONS],
        required=True,
        default=[".png", ".jpg", ".jpeg"])

    ANALYSIS_THREADS = IntConfigEntry(
        description="Number of threads to use for image analysis phase.",
        key_path=[NODE_MAIN, NODE_ANALYSIS, NODE_THREADS],
        default=1)

    MAX_FILE_MODIFICATION_TIME_DELTA = TimeDeltaConfigEntry(
        description="Maximum file modification date difference between multiple "
        "duplicates to be considered the same image",
        key_path=[
            NODE_MAIN, NODE_DEDUPLICATION, NODE_MAX_FILE_MODIFICATION_TIME_DIFF
        ],
        default=None,
        example=timedelta(minutes=5))

    REMOVE_EMPTY_FOLDERS = BoolConfigEntry(
        description="Whether to remove empty folders or not.",
        key_path=[NODE_MAIN, NODE_REMOVE_EMPTY_FOLDERS],
        default=False)

    DEDUPLICATOR_DUPLICATES_TARGET_DIRECTORY = DirectoryConfigEntry(
        description=
        "Directory path to move duplicates to instead of deleting them.",
        key_path=[
            NODE_MAIN, NODE_DEDUPLICATION, NODE_DUPLICATES_TARGET_DIRECTORY
        ],
        check_existence=True,
        default=None,
        example="/home/myuser/pictures/duplicates/")

    DAEMON_PROCESSING_TIMEOUT = TimeDeltaConfigEntry(
        description=
        "Time to wait for filesystems changes to settle before analysing.",
        key_path=[NODE_MAIN, NODE_DAEMON, NODE_PROCESSING_TIMEOUT],
        default="30s")

    DAEMON_FILE_OBSERVER_TYPE = StringConfigEntry(
        description="Type of file observer to use.",
        key_path=[NODE_MAIN, NODE_DAEMON, NODE_FILE_OBSERVER_TYPE],
        regex="|".join(
            [FILE_OBSERVER_TYPE_POLLING, FILE_OBSERVER_TYPE_INOTIFY]),
        default=FILE_OBSERVER_TYPE_POLLING,
        required=True)

    STATS_ENABLED = BoolConfigEntry(
        description="Whether to enable prometheus statistics or not.",
        key_path=[NODE_MAIN, NODE_STATS, NODE_ENABLED],
        default=True)

    STATS_PORT = IntConfigEntry(
        description="The port to expose statistics on.",
        key_path=[NODE_MAIN, NODE_STATS, NODE_PORT],
        default=8000)
Beispiel #7
0
class AppConfig(ConfigBase):
    def __new__(cls, *args, **kwargs):
        yaml_source = YamlSource(CONFIG_NODE_ROOT)
        toml_source = TomlSource(CONFIG_NODE_ROOT)
        data_sources = [
            EnvSource(),
            yaml_source,
            toml_source,
        ]
        return super(AppConfig, cls).__new__(cls, data_sources=data_sources)

    LOG_LEVEL = StringConfigEntry(
        description="Log level",
        key_path=[CONFIG_NODE_ROOT, "log_level"],
        regex=re.compile(f" {'|'.join(logging._nameToLevel.keys())}",
                         flags=re.IGNORECASE),
        default="INFO",
    )

    SERVER_HOST = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_SERVER, "host"],
        default=DEFAULT_SERVER_HOST,
        secret=True)

    SERVER_PORT = IntConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_SERVER, CONFIG_NODE_PORT],
        range=Range(1, 65534),
        default=9465)

    SERVER_API_TOKEN = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_SERVER, "api_token"],
        default=None,
        secret=True)

    DROP_EVENT_QUEUE_AFTER = TimeDeltaConfigEntry(
        key_path=[CONFIG_NODE_ROOT, "drop_event_queue_after"],
        default="2h",
    )

    RETRY_INTERVAL = TimeDeltaConfigEntry(
        key_path=[CONFIG_NODE_ROOT, "retry_interval"],
        default="2s",
    )

    HTTP_METHOD = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_HTTP, "method"],
        required=True,
        default="POST",
        regex="GET|POST|PUT|PATCH")

    HTTP_URL = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_HTTP, "url"], required=False)

    HTTP_HEADERS = ListConfigEntry(
        item_type=StringConfigEntry,
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_HTTP, "headers"],
        default=[])

    MQTT_HOST = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "host"], required=False)
    MQTT_PORT = IntConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "port"],
        required=True,
        default=1883,
        range=Range(1, 65534),
    )

    MQTT_CLIENT_ID = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "client_id"],
        default="barcode-server")

    MQTT_USER = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "user"])

    MQTT_PASSWORD = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "password"], secret=True)

    MQTT_TOPIC = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "topic"],
        default="barcode-server/barcode",
        required=True)

    MQTT_QOS = IntConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "qos"],
        default=2,
        required=True)

    MQTT_RETAIN = BoolConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_MQTT, "retain"],
        default=False,
        required=True)

    DEVICE_PATTERNS = ListConfigEntry(item_type=RegexConfigEntry,
                                      item_args={"flags": re.IGNORECASE},
                                      key_path=[CONFIG_NODE_ROOT, "devices"],
                                      default=[])

    DEVICE_PATHS = ListConfigEntry(item_type=FileConfigEntry,
                                   key_path=[CONFIG_NODE_ROOT, "device_paths"],
                                   default=[])

    STATS_PORT = IntConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_STATS, CONFIG_NODE_PORT],
        default=8000,
        required=False)

    def validate(self):
        super(AppConfig, self).validate()
        if len(self.DEVICE_PATHS.value) == len(
                self.DEVICE_PATTERNS.value) == 0:
            raise AssertionError(
                "You must provide at least one device pattern or device_path!")