Welcome to mirror list, hosted at ThFree Co, Russian Federation.

config.py « nextcloud_news_updater - github.com/nextcloud/news-updater.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6ec77a2f4a011b82cfaf61a2aa296201c124c291 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import configparser
import os
from typing import List, Union, Any
from typing import Optional


class InvalidConfigException(Exception):
    pass


class InvalidConfigKeyException(Exception):
    pass


class Types:
    """
    In Python 3.4 we could use enums
    """
    integer = 0
    boolean = 1
    string = 2


class Config:
    """
    Class that holds the config values, defaults etc
    Once 3.5 can be required, we can add typings :D
    """
    config_keys = {
        'user': Types.string,
        'password': Types.string,
        'url': Types.string,
        'loglevel': Types.string,
        'phpini': Types.string,
        'apilevel': Types.string,
        'mode': Types.string,
        'threads': Types.integer,
        'interval': Types.integer,
    }

    def __init__(self) -> None:
        self.loglevel = 'error'
        self.interval = 15 * 60
        self.timeout = 5 * 60
        self.apilevel = 'v1-2'
        self.threads = 10
        self.mode = 'endless'
        self.password = ''
        self.user = None  # type: Optional[str]
        self.url = None  # type: Optional[str]
        self.phpini = None  # type: Optional[str]

    def is_web(self) -> bool:
        return self.url is not None and (self.url.startswith('http://') or
                                         self.url.startswith('https://'))


class ConfigValidator:
    def validate(self, config: Config) -> List[str]:
        result = []  # type: List[str]
        if not config.url:
            return ['No url given']

        if config.is_web() and not config.user:
            return ['Url given but no user present']
        elif not config.is_web() and not os.path.isabs(config.url):
            return ['Absolute path or full Url required']
        elif not config.is_web() and not os.path.isdir(config.url):
            return ['Given path is not a directory']

        if config.mode not in ['endless', 'singlerun']:
            result += ['Unknown mode: %s' % config.mode]
        if config.loglevel not in ['info', 'error']:
            result += ['Unknown loglevel: %s' % config.loglevel]
        if config.apilevel not in ['v1-2', 'v2']:
            result += ['Unknown apilevel: %s' % config.apilevel]

        if config.phpini and not os.path.isabs(config.phpini):
            result += ['Path to php.ini must be absolute']

        return result


class ConfigParser:
    def parse_file(self, path: str) -> Config:
        parser = configparser.ConfigParser()
        successfully_parsed = parser.read(path)
        if len(successfully_parsed) <= 0:
            raise InvalidConfigException(
                'Error: could not find config file %s' % path)
        contents = parser['updater']

        config = Config()
        for key in contents:
            if not hasattr(config, key):
                msg = 'Error: unknown config key with name "%s"' % key
                raise InvalidConfigKeyException(msg)

        for key, type_enum in Config.config_keys.items():
            if key in contents:
                value = self._parse_ini_value(type_enum, contents, key)
                setattr(config, key, value)

        return config

    def _parse_ini_value(self, type_enum: int, contents: Any, key: str) -> \
            Union[str, int, bool]:
        if type_enum == Types.integer:
            return int(contents.get(key))
        elif type_enum == Types.boolean:
            return contents.getboolean(key)
        else:
            return contents.get(key)


def merge_configs(args, config: Config) -> None:
    """
    Merges values from argparse and configparser. Values from argparse will
    always override values from the config. Resulting values are set on the
    config object
    :argument args the argument parser arguments
    :argument config the config
    """
    for key, type_enum in Config.config_keys.items():
        if hasattr(args, key) and getattr(args, key):
            setattr(config, key, getattr(args, key))