1 | #!/usr/bin/env python |
||
2 | # -*- coding: utf-8 -*- |
||
3 | |||
4 | 1 | from __future__ import unicode_literals |
|
5 | 1 | ||
6 | 1 | import os |
|
7 | 1 | import sys |
|
8 | 1 | import argparse |
|
9 | try: |
||
10 | import configparser # Python 3 |
||
11 | 1 | except ImportError: |
|
12 | 1 | import ConfigParser as configparser # Python 2 |
|
13 | import subprocess |
||
14 | import logging |
||
15 | 1 | ||
16 | |||
17 | 1 | CONFIG_FILENAMES = ['.verchew', '.verchewrc', 'verchew.ini', '.verchew.ini'] |
|
18 | |||
19 | log = logging.getLogger(__name__) |
||
20 | 1 | ||
21 | 1 | ||
22 | def main(): |
||
23 | args = parse_args() |
||
24 | configure_logging(args.verbose) |
||
25 | path = find_config() |
||
26 | config = parse_config(path) |
||
27 | if not check_dependencies(config): |
||
28 | sys.exit(1) |
||
29 | 1 | ||
30 | 1 | ||
31 | def parse_args(): |
||
32 | parser = argparse.ArgumentParser() |
||
33 | 1 | # TODO: add '--version' option |
|
34 | parser.add_argument('-v', '--verbose', action='count', default=0, |
||
35 | help="enable verbose logging") |
||
36 | 1 | ||
37 | return parser.parse_args() |
||
38 | |||
39 | 1 | ||
40 | def configure_logging(count=0): |
||
41 | if count == 0: |
||
42 | level = logging.WARNING |
||
43 | elif count == 1: |
||
44 | level = logging.INFO |
||
45 | else: |
||
46 | level = logging.DEBUG |
||
47 | |||
48 | logging.basicConfig(level=level, format="%(levelname)s: %(message)s") |
||
49 | |||
50 | 1 | ||
51 | 1 | def find_config(root=None, config_filenames=None): |
|
52 | 1 | root = root or os.getcwd() |
|
53 | config_filenames = config_filenames or CONFIG_FILENAMES |
||
54 | 1 | ||
55 | 1 | path = None |
|
56 | 1 | log.info("Looking for config file in: %s", root) |
|
57 | 1 | log.debug("Filename options: %s", ", ".join(config_filenames)) |
|
58 | 1 | for filename in os.listdir(root): |
|
59 | 1 | if filename in config_filenames: |
|
60 | 1 | path = os.path.join(root, filename) |
|
61 | 1 | log.info("Found config file: %s", path) |
|
62 | return path |
||
63 | 1 | ||
64 | 1 | msg = "No config file found in: {0}".format(root) |
|
65 | raise RuntimeError(msg) |
||
66 | |||
67 | 1 | ||
68 | 1 | def parse_config(path): |
|
69 | data = {} |
||
70 | 1 | ||
71 | 1 | log.info("Parsing config file: %s", path) |
|
72 | 1 | config = configparser.ConfigParser() |
|
73 | config.read(path) |
||
74 | 1 | ||
75 | 1 | for section in config.sections(): |
|
76 | 1 | data[section] = {} |
|
77 | 1 | for name, value in config.items(section): |
|
78 | data[section][name] = value |
||
79 | 1 | ||
80 | return data |
||
81 | |||
82 | 1 | ||
83 | def check_dependencies(config): |
||
84 | success = [] |
||
85 | |||
86 | for name, settings in config.items(): |
||
87 | show("Checking the version of {0}...".format(name), head=True) |
||
88 | output = get_version(settings['cli']) |
||
89 | if settings['version'] in output: |
||
90 | show("✔ MATCHED: {0}".format(settings['version'])) |
||
91 | success.append("✔") |
||
92 | else: |
||
93 | show("✖ EXPECTED: {0}".format(settings['version'])) |
||
94 | success.append("✖") |
||
95 | |||
96 | show("Results: " + " ".join(success), head=True) |
||
97 | |||
98 | return "✖" not in success |
||
99 | |||
100 | 1 | ||
101 | 1 | def get_version(program): |
|
102 | args = [program, '--version'] |
||
103 | 1 | ||
104 | 1 | show("$ {0}".format(" ".join(args))) |
|
105 | 1 | try: |
|
106 | 1 | except OSError: |
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
107 | 1 | output = "command not found" |
|
108 | 1 | log.debug("Command output: %r", output) |
|
109 | |||
110 | 1 | show(output.splitlines()[0]) |
|
111 | |||
112 | 1 | return output |
|
113 | |||
114 | |||
115 | 1 | def show(text, start='', end='\n', head=False): |
|
116 | """Python 2 and 3 compatible version of print.""" |
||
117 | 1 | if head: |
|
118 | start = '\n' |
||
119 | end = '\n\n' |
||
120 | |||
121 | 1 | if log.getEffectiveLevel() < logging.WARNING: |
|
122 | 1 | log.info(text) |
|
123 | else: |
||
124 | sys.stdout.write(start + text + end) |
||
125 | |||
126 | |||
127 | if __name__ == '__main__': # pragma: no cover |
||
128 | main() |
||
129 |