2 Copyright (c) 2018-2019 Intel Corporation
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
22 from distutils.version import LooseVersion
25 "protobuf": "google.protobuf",
26 "test-generator": "generator",
28 critical_modules = ["networkx"]
30 message = "\nDetected not satisfied dependencies:\n" \
32 "Please install required versions of components or use install_prerequisites script\n" \
34 "Note that install_prerequisites scripts may install additional components."
37 def check_python_version():
39 Checks python version to be greater or equal than 3.4
40 :return: exit code (1 - error, None - successful)
42 if sys.version_info < (3, 4):
43 print('Python version should be of version 3.4 or newer')
47 def get_module_version_list_from_file(file_name):
49 Please do not add parameter type annotations (param:type).
50 Because we import this file while checking Python version.
51 Python 2.x will fail with no clear message on type annotations.
53 Reads file with requirements
54 :param file_name: Name of the requirements file
55 :return: list of tuples of strings like (name_of_module, sign, version)
63 [('tensorflow', '>=', '1.2.0'), ('networkx', '==', '2.1'), ('numpy', None, None)]
66 with open(file_name) as f:
68 line = line.strip('\n')
69 line = line.strip(' ')
72 splited_line = re.split(r"==|>=|<=|>|<", line)
73 if len(splited_line) == 1:
74 req_dict.append((splited_line[0], None, None))
77 req_dict.append((splited_line[0], '==', splited_line[1]))
79 req_dict.append((splited_line[0], '>=', splited_line[1]))
81 req_dict.append((splited_line[0], '<=', splited_line[1]))
83 req_dict.append((splited_line[0], '<', splited_line[1]))
85 req_dict.append((splited_line[0], '>', splited_line[1]))
89 def version_check(name, installed_v, required_v, sign, not_satisfied_v, exit_code):
91 Please do not add parameter type annotations (param:type).
92 Because we import this file while checking Python version.
93 Python 2.x will fail with no clear message on type annotations.
95 Evaluates comparison of installed and required versions according to requirements file of one module.
96 If installed version does not satisfy requirements appends this module to not_stisfied_v list.
97 :param name: module name
98 :param installed_v: installed version of module
99 :param required_v: required version of module
100 :param sign: sing for comparison of required and installed versions
101 :param not_satisfied_v: list of modules with not satisfying versions
102 :param exit_code: flag of successful execution (0 - successful, 1 - error)
106 req_ver = LooseVersion(required_v)
109 satisfied = installed_v > req_ver
111 satisfied = installed_v >= req_ver
113 satisfied = installed_v <= req_ver
115 satisfied = installed_v < req_ver
117 satisfied = installed_v == req_ver
119 log.error("Error during version comparison")
123 not_satisfied_v.append((name, 'installed: {}'.format(installed_v), 'required: {}'.format(required_v)))
124 if name in critical_modules:
129 def check_requirements(framework=None):
131 Please do not add parameter type annotations (param:type).
132 Because we import this file while checking Python version.
133 Python 2.x will fail with no clear message on type annotations.
135 Checks if installed modules versions satisfy required versions in requirements file
136 Logs a warning in case of permissible dissatisfaction
137 Logs an error in cases of critical dissatisfaction
138 :param framework: framework name
139 :return: exit code (0 - execution successful, 1 - error)
141 if framework is None:
142 framework_suffix = ""
144 framework_suffix = "_{}".format(framework)
145 file_name = "requirements{}.txt".format(framework_suffix)
146 requirements_file = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, file_name))
147 requirements_list = get_module_version_list_from_file(requirements_file)
148 not_satisfied_versions = []
150 for name, key, required_version in requirements_list:
152 importable_name = modules.get(name, name)
153 exec("import {}".format(importable_name))
154 installed_version = sys.modules[importable_name].__version__
155 exit_code = version_check(name, installed_version, required_version, key, not_satisfied_versions, exit_code)
156 exec("del {}".format(importable_name))
157 except (AttributeError, ImportError):
158 not_satisfied_versions.append((name, 'not installed', 'required: {}'.format(required_version)))
161 except Exception as e:
162 log.error('Error happened while importing {} module. It may happen due to unsatisfied requirements of '
163 'that module. Please run requirements installation script once more.\n'
164 'Details on module importing failure: {}'.format(name, e))
165 not_satisfied_versions.append((name, 'package error', 'required: {}'.format(required_version)))
169 if len(not_satisfied_versions) != 0:
170 extension = 'bat' if os.name == 'nt' else 'sh'
171 install_file = 'install_prerequisites{0}.{1}'.format(framework_suffix, extension)
172 helper_command = os.path.join(os.path.dirname(requirements_file), 'install_prerequisites', install_file)
173 missed_modules_message = ""
174 for module in not_satisfied_versions:
175 missed_modules_message += "\t{}: {}, {}\n".format(module[0], module[1], module[2])
177 log.error(message.format(missed_modules_message, helper_command))
179 log.error(message.format(missed_modules_message, helper_command), extra={'is_warning': True})