forked from dfrc-korea/carpe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dependencies.py
190 lines (162 loc) · 7.38 KB
/
dependencies.py
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# -*- coding: utf-8 -*-
"""Functionality to check for the availability and version of dependencies.
This file is generated by l2tdevtools update-dependencies.py, any dependency
related changes should be made in dependencies.ini.
"""
from __future__ import print_function
from __future__ import unicode_literals
import re
# Dictionary that contains version tuples per module name.
#
# A version tuple consists of:
# (version_attribute_name, minimum_version, maximum_version, is_required)
#
# Where version_attribute_name is either a name of an attribute,
# property or method.
PYTHON_DEPENDENCIES = {
'artifacts': ('__version__', '20190305', None, True),
'compoundfiles': ('', '0.3', None, True), # for defa
'Crypto': ('__version__', '3.9.4', None, True), # kakaotalk
'cryptography': ('__version__', '2.0.2', None, True),
'dfdatetime': ('__version__', '20180704', None, True),
'dfvfs': ('__version__', '20190902', '20201105', True),
'dfwinreg': ('__version__', '20180712', None, True),
'dtfabric': ('__version__', '20181128', None, True),
'elasticsearch': ('__versionstr__', '6.0', None, True), # for defa
'google.protobuf': ('__version__', '3.12.2', None, True), # for android usagestats
'olefile': ('__version__', '0.46', None, True), # for windows sticky notes
'pdfminer': ('__version__', '20191125', None, True), # for defa
'pika': ('__version__', '1.1.0', None, True), # for carpe server
'pyewf': ('get_version()', '20171104', None, True),
'pyesedb': ('get_version()', '20150409', None, True),
'pyfsapfs': ('get_version()', '20181205', None, True),
'pyfsntfs': ('get_version()', '20201027', None, True),
'pyfwnt': ('get_version()', '20200723', None, True),
'pymysql': ('__version__', '0.9.3', None, True),
'pyregf': ('get_version()', '20150315', None, True),
'pysigscan': ('get_version()', '20190629', None, True),
'pysmdev': ('get_version()', '20140529', None, True),
'pysmraw': ('get_version()', '20140612', None, True),
'pytsk3': ('get_version()', '20190507', None, True),
'pytz': ('__version__', '', None, True),
'pyvshadow': ('get_version()', '20191221', None, True),
'six': ('__version__', '1.1.0', None, True),
'xlrd': ('__version__', '1.2.0', None, True),
'yaml': ('__version__', '3.10', None, True)
}
_VERSION_SPLIT_REGEX = re.compile(r'\.|\-')
def _CheckPythonModule(
module_name, version_attribute_name, minimum_version,
is_required=True, maximum_version=None, verbose_output=True):
"""Checks the availability of a Python module.
Args:
module_name (str): name of the module.
version_attribute_name (str): name of the attribute that contains
the module version or method to retrieve the module version.
minimum_version (str): minimum required version.
is_required (Optional[bool]): True if the Python module is a required
dependency.
maximum_version (Optional[str]): maximum required version. Should only be
used if there is a later version that is not supported.
verbose_output (Optional[bool]): True if output should be verbose.
Returns:
bool: True if the Python module is available and conforms to
the minimum required version, False otherwise.
"""
module_object = _ImportPythonModule(module_name)
if not module_object:
if not is_required:
print('[OPTIONAL]\tmissing: {0:s}.'.format(module_name))
return True
print('[FAILURE]\tmissing: {0:s}.'.format(module_name))
return False
if not version_attribute_name or not minimum_version:
if verbose_output:
print('[OK]\t\t{0:s}'.format(module_name))
return True
module_version = None
if not version_attribute_name.endswith('()'):
module_version = getattr(module_object, version_attribute_name, None)
else:
version_method = getattr(module_object, version_attribute_name[:-2], None)
if version_method:
module_version = version_method()
if not module_version:
if not is_required:
print((
'[OPTIONAL]\tunable to determine version information '
'for: {0:s}').format(module_name))
return True
print((
'[FAILURE]\tunable to determine version information '
'for: {0:s}').format(module_name))
return False
# Make sure the module version is a string.
module_version = '{0!s}'.format(module_version)
# Split the version string and convert every digit into an integer.
# A string compare of both version strings will yield an incorrect result.
module_version_map = list(
map(int, _VERSION_SPLIT_REGEX.split(module_version)))
minimum_version_map = list(
map(int, _VERSION_SPLIT_REGEX.split(minimum_version)))
if module_version_map < minimum_version_map:
if not is_required:
print((
'[OPTIONAL]\t{0:s} version: {1!s} is too old, {2!s} or later '
'required.').format(module_name, module_version, minimum_version))
return True
print((
'[FAILURE]\t{0:s} version: {1!s} is too old, {2!s} or later '
'required.').format(module_name, module_version, minimum_version))
return False
if maximum_version:
maximum_version_map = list(
map(int, _VERSION_SPLIT_REGEX.split(maximum_version)))
if module_version_map > maximum_version_map:
if not is_required:
print((
'[OPTIONAL]\t{0:s} version: {1!s} is too recent, {2!s} or earlier '
'required.').format(module_name, module_version, minimum_version))
return True
print((
'[FAILURE]\t{0:s} version: {1!s} is too recent, {2!s} or earlier '
'required.').format(module_name, module_version, maximum_version))
return False
if verbose_output:
print('[OK]\t\t{0:s} version: {1!s}'.format(module_name, module_version))
return True
def _ImportPythonModule(module_name):
"""Imports a Python module.
Args:
module_name (str): name of the module.
Returns:
module: Python module or None if the module cannot be imported.
"""
try:
module_object = list(map(__import__, [module_name]))[0]
except ImportError:
return None
# If the module name contains dots get the upper most module object.
if '.' in module_name:
for submodule_name in module_name.split('.')[1:]:
module_object = getattr(module_object, submodule_name, None)
return module_object
def CheckDependencies(verbose_output=True):
"""Checks the availability of the dependencies.
Args:
verbose_output (Optional[bool]): True if output should be verbose.
Returns:
bool: True if the dependencies are available, False otherwise.
"""
print('Checking availability and versions of dependencies.')
check_result = True
for module_name, version_tuple in sorted(PYTHON_DEPENDENCIES.items()):
if not _CheckPythonModule(
module_name, version_tuple[0], version_tuple[1],
is_required=version_tuple[3], maximum_version=version_tuple[2],
verbose_output=verbose_output):
check_result = False
if check_result and not verbose_output:
print('[OK]')
print('')
return check_result