Example #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)
    def test_env(self):
        str_entry = StringConfigEntry(
            key_path=["test-ing", "key1"],
            default="value"
        )
        int_entry = IntConfigEntry(
            key_path=["testing", "key2"],
            default=2
        )

        source = EnvSource()
        original_key = EnvSource.env_key(str_entry)
        expected = "expected"
        with mock.patch.dict(os.environ, {original_key: expected}, clear=True):
            source.load()

        self.assertTrue(source.has(str_entry))
        self.assertEqual(source.get(str_entry), expected)
        self.assertFalse(source.has(int_entry))

        normalized_env_key = original_key.replace('-', '_')
        self.assertNotEqual(original_key, normalized_env_key)
        with mock.patch.dict(os.environ, {normalized_env_key: expected + '2'}, clear=True):
            source.load()

        self.assertTrue(source.has(str_entry))
        self.assertEqual(source.get(str_entry), expected + '2')
        self.assertFalse(source.has(int_entry))
 def test_json(self):
     str_entry = StringConfigEntry(key_path=["testing", "key1"],
                                   default="value")
     int_entry = IntConfigEntry(key_path=["testing", "key2"], default=2)
     source = JsonSource("test")
     source.load()
     self.assertTrue(source.has(str_entry))
     self.assertEqual(source.get(str_entry), "value")
     self.assertTrue(source.has(int_entry))
     self.assertEqual(source.get(int_entry), 2)
Example #4
0
class AppConfig(ConfigBase):
    def __new__(cls, *args, **kwargs):
        yaml_source = YamlSource("deinemudda")
        data_sources = [EnvSource(), yaml_source]
        return super(AppConfig, cls).__new__(cls, data_sources=data_sources)

    TELEGRAM_BOT_TOKEN = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_TELEGRAM, "bot_token"],
        required=True,
        secret=True,
        example="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")

    TELEGRAM_ADMIN_USERNAMES = ListConfigEntry(
        item_type=StringConfigEntry,
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_TELEGRAM, "admin_usernames"],
        default=[],
        example=["myadminuser", "myotheradminuser"])

    SQL_PERSISTENCE_URL = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_PERSISTENCE, "url"],
        default=DEFAULT_SQL_PERSISTENCE_URL,
        secret=True)

    WORD_COUNT_RANGE = RangeConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_BEHAVIOUR, CONFIG_NODE_WORD_COUNT_RANGE
    ],
                                        default="[1..10]")

    CHAR_COUNT_RANGE = RangeConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_BEHAVIOUR, CONFIG_NODE_CHAR_COUNT_RANGE
    ],
                                        default="[3..255]")

    STATS_PORT = IntConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_STATS, CONFIG_NODE_PORT],
        default=8000)
    def test_int_entry(self):
        config_entry = IntConfigEntry(key_path=["int"], range=Range(-5, 5))
        input_output = [("5", 5), (5, 5), ("-3", -3), (-3, -3),
                        (-6, ValueError)]

        self.assert_input_output(config_entry, input_output)
Example #6
0
class AppConfig(ConfigBase):
    """
    Main InfiniteWisdom bot configuration
    """

    LOGGER = logging.getLogger(__name__)

    def __new__(cls, *args, **kwargs):
        yaml_source = YamlSource(CONFIG_FILE_NAME)
        data_sources = [EnvSource(), yaml_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="DEBUG",
    )

    TELEGRAM_BOT_TOKEN = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_TELEGRAM, "bot_token"],
        example="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
        secret=True)

    TELEGRAM_INLINE_BADGE_SIZE = IntConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_TELEGRAM, "inline_badge_size"],
        default=16)

    TELEGRAM_GREETING_MESSAGE = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_TELEGRAM, "greeting_message"],
        required=False,
        default=
        'Send /inspire for more inspiration :blush: Or use @InfiniteWisdomBot in a group chat and select one of the suggestions.'
    )

    TELEGRAM_CAPTION_IMAGES_WITH_TEXT = BoolConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_TELEGRAM, "caption_images_with_text"
    ],
                                                        default=False)

    TELEGRAM_ADMIN_USERNAMES = ListConfigEntry(
        item_type=StringConfigEntry,
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_TELEGRAM, "admin_usernames"],
        default=[],
        example=["myadminuser", "myotheradminuser"])

    UPLOADER_INTERVAL = FloatConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_UPLOADER, CONFIG_NODE_INTERVAL
    ],
                                         default=3.0)

    UPLOADER_CHAT_ID = IntConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_UPLOADER, "chat_id"],
        default=None,
        example=12345678)

    CRAWLER_INTERVAL = FloatConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_CRAWLER, CONFIG_NODE_INTERVAL],
        default=1.0)

    SQL_PERSISTENCE_URL = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_PERSISTENCE, "url"],
        default=DEFAULT_SQL_PERSISTENCE_URL,
        secret=True)

    FILE_PERSISTENCE_BASE_PATH = StringConfigEntry(
        key_path=[CONFIG_NODE_ROOT, CONFIG_NODE_PERSISTENCE, "file_base_path"],
        default=DEFAULT_FILE_PERSISTENCE_BASE_PATH)

    IMAGE_ANALYSIS_INTERVAL = FloatConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS, CONFIG_NODE_INTERVAL
    ],
                                               default=1.0)

    IMAGE_ANALYSIS_TESSERACT_ENABLED = BoolConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS, CONFIG_NODE_TESSERACT,
        CONFIG_NODE_ENABLED
    ],
                                                       default=False)

    IMAGE_ANALYSIS_GOOGLE_VISION_ENABLED = BoolConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS,
        CONFIG_NODE_GOOGLE_VISION, CONFIG_NODE_ENABLED
    ],
                                                           default=False)

    IMAGE_ANALYSIS_GOOGLE_VISION_AUTH_FILE = StringConfigEntry(
        key_path=[
            CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS,
            CONFIG_NODE_GOOGLE_VISION, "auth_file"
        ],
        default=None,
        example="./InfiniteWisdom-1522618e7d39.json")

    IMAGE_ANALYSIS_GOOGLE_VISION_CAPACITY = IntConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS,
        CONFIG_NODE_GOOGLE_VISION, CONFIG_NODE_CAPACITY_PER_MONTH
    ],
                                                           default=None,
                                                           example=1000)

    IMAGE_ANALYSIS_MICROSOFT_AZURE_ENABLED = BoolConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS,
        CONFIG_NODE_MICROSOFT_AZURE, CONFIG_NODE_ENABLED
    ],
                                                             default=False)

    IMAGE_ANALYSIS_MICROSOFT_AZURE_SUBSCRIPTION_KEY = StringConfigEntry(
        key_path=[
            CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS,
            CONFIG_NODE_MICROSOFT_AZURE, "subscription_key"
        ],
        default=None,
        example="1234567890684c3baa5a0605712345ab",
        secret=True)

    IMAGE_ANALYSIS_MICROSOFT_AZURE_REGION = StringConfigEntry(
        key_path=[
            CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS,
            CONFIG_NODE_MICROSOFT_AZURE, "region"
        ],
        default="francecentral")

    IMAGE_ANALYSIS_MICROSOFT_AZURE_CAPACITY = IntConfigEntry(key_path=[
        CONFIG_NODE_ROOT, CONFIG_NODE_IMAGE_ANALYSIS,
        CONFIG_NODE_MICROSOFT_AZURE, CONFIG_NODE_CAPACITY_PER_MONTH
    ],
                                                             default=5000)

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

    def _validate(self):
        """
        Validates the current configuration and throws an exception if something is wrong
        """
        if len(self.TELEGRAM_BOT_TOKEN.value) <= 0:
            raise AssertionError("Bot token is missing!")
        if self.CRAWLER_INTERVAL.value < 0:
            raise AssertionError("Image polling interval must be >= 0!")

        if self.IMAGE_ANALYSIS_GOOGLE_VISION_ENABLED.value:
            if self.IMAGE_ANALYSIS_GOOGLE_VISION_AUTH_FILE.value is None:
                raise AssertionError(
                    "Google Vision authentication file is required")

            if not os.path.isfile(
                    self.IMAGE_ANALYSIS_GOOGLE_VISION_AUTH_FILE.value):
                raise IsADirectoryError(
                    "Google Vision Auth file path is not a file: {}".format(
                        self.IMAGE_ANALYSIS_GOOGLE_VISION_AUTH_FILE.value))

        if self.IMAGE_ANALYSIS_MICROSOFT_AZURE_ENABLED.value:
            if self.IMAGE_ANALYSIS_MICROSOFT_AZURE_SUBSCRIPTION_KEY.value is None:
                raise AssertionError(
                    "Microsoft Azure subscription key is required")

            if self.IMAGE_ANALYSIS_MICROSOFT_AZURE_REGION.value is None:
                raise AssertionError("Microsoft Azure region is required")
Example #7
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",
    )

    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
    )
Example #8
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)
Example #9
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)
Example #10
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!")