3 """Test script to check for required functionality.
5 Execute this code at the command line by typing:
7 python swc-installation-test-2.py
9 How to get a command line:
11 - On OSX run this with the Terminal application.
13 - On Windows, go to the Start menu, select 'Run' and type 'cmd'
14 (without the quotes) to run the 'cmd.exe' Windows Command Prompt.
16 - On Linux, either use your login shell directly, or run one of a
17 number of graphical terminals (e.g. 'xterm', 'gnome-terminal', ...).
19 Run the script and follow the instructions it prints at the end.
21 This script requires at least Python 2.6. You can check the version
22 of Python that you have installed with 'swc-installation-test-1.py'.
25 import importlib as _importlib
26 import logging as _logging
28 import platform as _platform
30 import subprocess as _subprocess
36 # Comment out any entries you don't need
46 'hg', # Command line tool
47 'mercurial', # Python package
48 # Build tools and packaging
53 'nosetests', # Command line tool
54 'nose', # Python package
56 'sqlite3', # Command line tool
57 'sqlite3-python', # Python package
73 class DependencyError (Exception):
74 def __init__(self, checker, message):
75 self.checker = checker
76 self.message = message
79 return 'check for {0} failed:\n{1}'.format(
80 self.checker.full_name(), self.message)
83 def check(checks=None):
88 checker = CHECKER[check]
89 _sys.stdout.write('check {0}...\t'.format(checker.full_name()))
92 except DependencyError as e:
94 _sys.stdout.write('fail\n')
96 _sys.stdout.write('pass\n')
99 for failure in failures:
106 class Dependency (object):
107 def __init__(self, name, long_name=None, minimum_version=None,
108 version_delimiter='.', and_dependencies=None,
109 or_dependencies=None):
111 self.long_name = long_name or name
112 self.minimum_version = minimum_version
113 self.version_delimiter = version_delimiter
114 if not and_dependencies:
115 and_dependencies = []
116 self.and_dependencies = and_dependencies
117 if not or_dependencies:
119 self.or_dependencies = or_dependencies
122 return '<{0} {1}>'.format(type(self).__name__, self.name)
125 if self.name == self.long_name:
128 return '{0} ({1})'.format(self.long_name, self.name)
131 self._check_dependencies()
134 def _check_dependencies(self):
135 for dependency in self.and_dependencies:
136 if not hasattr(dependency, 'check'):
137 dependency = CHECKER[dependency]
139 or_pass = not bool(self.or_dependencies)
141 for dependency in self.or_dependencies:
142 if not hasattr(dependency, 'check'):
143 dependency = CHECKER[dependency]
146 except DependencyError as e:
155 version = self._get_version()
156 parsed_version = None
157 if hasattr(self, '_get_parsed_version'):
158 parsed_version = self._get_parsed_version()
159 if self.minimum_version:
160 self._check_version(version=version, parsed_version=parsed_version)
162 def _get_version(self):
163 raise NotImplementedError(self)
165 def _check_version(self, version, parsed_version=None):
166 if not parsed_version:
167 parsed_version = self._parse_version(version=version)
168 if parsed_version < self.minimum_version:
169 raise DependencyError(
171 message='outdated version of {0}: {1} (need >= {2})'.format(
172 self.full_name(), version,
173 self.version_delimiter.join(
174 str(part) for part in self.minimum_version)))
176 def _parse_version(self, version):
178 for part in version.split(self.version_delimiter):
180 parsed_version.append(int(part))
181 except ValueError as e:
182 raise NotImplementedError((version, part)) from e
183 return tuple(parsed_version)
186 class PythonDependency (Dependency):
187 def __init__(self, name='python', long_name='Python version',
188 minimum_version=(2, 6), **kwargs):
189 super(PythonDependency, self).__init__(
190 name=name, long_name=long_name, minimum_version=minimum_version,
193 def _get_version(self):
196 def _get_parsed_version(self):
197 return _sys.version_info
200 CHECKER['python'] = PythonDependency()
203 class CommandDependency (Dependency):
204 def __init__(self, command, version_option='--version',
205 version_regexp=None, version_stream='stdout', **kwargs):
206 if 'name' not in kwargs:
207 kwargs['name'] = command
208 super(CommandDependency, self).__init__(**kwargs)
209 self.command = command
210 self.version_option = version_option
211 if not version_regexp:
212 regexp = r'([\d][\d{0}]*[\d])'.format(self.version_delimiter)
213 version_regexp = _re.compile(regexp)
214 self.version_regexp = version_regexp
215 self.version_stream = version_stream
217 def _get_version_stream(self):
219 p = _subprocess.Popen(
220 [self.command, self.version_option],
221 stdout=_subprocess.PIPE, stderr=_subprocess.PIPE,
222 close_fds=True, shell=False, universal_newlines=True)
224 raise DependencyError(
226 message="could not find '{0}' executable".format(self.command),
228 stdout,stderr = p.communicate()
232 "failed to execute '{0} {1}':".format(
233 self.command, self.version_option),
234 'status: {0}'.format(status),
236 for name,string in [('stdout', stdout), ('stderr', stderr)]:
238 lines.extend([name + ':', string])
239 raise DependencyError(checker=self, message='\n'.join(lines))
240 for name,string in [('stdout', stdout), ('stderr', stderr)]:
241 if name == self.version_stream:
243 raise NotImplementedError(self.version_stream)
245 def _get_version(self):
246 version_stream = self._get_version_stream()
247 match = self.version_regexp.search(version_stream)
249 raise DependencyError(
251 message='no version string in output:\n{0}'.format(
253 return match.group(1)
256 for command,long_name,minimum_version in [
257 ('bash', 'Bourne Again Shell', (4, 0)),
258 ('easy_install', 'Setuptools easy_install', None),
259 ('git', 'Git', (1, 8, 0)),
260 ('hg', 'Mercurial', (2, 0, 0)),
261 ('make', None, None),
262 ('sqlite3', 'SQLite 3', None),
263 ('nosetests', 'Nose', (1, 0, 0)),
264 ('emacs', 'Emacs', None),
265 ('xemacs', 'XEmacs', None),
266 ('vim', 'Vim', None),
268 ('nano', 'Nano', None),
269 ('kate', 'Kate', None),
270 ('notepad++', 'Notepad++', None),
271 ('firefox', 'Firefox', None),
272 ('google-chrome', 'Google Chrome', None),
273 ('chromium', 'Chromium', None),
277 CHECKER[command] = CommandDependency(
278 command=command, long_name=long_name, minimum_version=minimum_version)
279 del command, long_name, minimum_version # cleanup namespace
282 class PythonPackageDependency (Dependency):
283 def __init__(self, package, **kwargs):
284 if 'name' not in kwargs:
285 kwargs['name'] = package
286 super(PythonPackageDependency, self).__init__(**kwargs)
287 self.package = package
289 def _get_version(self):
291 package = _importlib.import_module(self.package)
292 except ImportError as e:
293 raise DependencyError(
295 message="could not import the '{0}' package".format(
299 version = package.__version__
300 except AttributeError:
305 for package,name,long_name,minimum_version in [
306 ('mercurial', None, 'Mercurial Python package',
307 CHECKER['hg'].minimum_version),
308 ('nose', None, 'Nose Python package',
309 CHECKER['nosetests'].minimum_version),
310 ('sqlite3', 'sqlite3-python', 'SQLite Python package',
311 CHECKER['sqlite3'].minimum_version),
312 ('IPython', None, None, None),
313 ('numpy', None, 'NumPy', None),
314 ('scipy', None, 'SciPy', None),
315 ('matplotlib', None, 'Matplotlib', None),
316 ('sympy', None, 'SymPy', None),
317 ('Cython', None, None, None),
318 ('networkx', None, 'NetworkX', None),
319 ('mayavi.mlab', None, 'MayaVi', None),
320 ('setuptools', None, 'Setuptools', None),
326 CHECKER[name] = PythonPackageDependency(
327 package=package, name=name, long_name=long_name,
328 minimum_version=minimum_version)
329 del package, name, long_name, minimum_version # cleanup namespace
332 class VirtualDependency (Dependency):
337 for name,dependencies in [
347 ('virtual-browser', (
353 CHECKER[name] = VirtualDependency(
354 name=name, long_name=name, or_dependencies=dependencies)
355 del name, dependencies # cleanup namespace
358 def print_system_info():
359 print("If you do not understand why the above failures occurred,")
360 print("copy and send the *entire* output (all info above and summary")
361 print("below) to the instructor for help.")
363 print('==================')
364 print('System information')
365 print('==================')
366 print('os.name : {0}'.format(_os.name))
368 print('os.uname : {0}'.format(_os.uname()))
371 print('platform : {0}'.format(_sys.platform))
372 print('platform+ : {0}'.format(_platform.platform()))
373 print('prefix : {0}'.format(_sys.prefix))
374 print('exec_prefix : {0}'.format(_sys.exec_prefix))
375 print('executable : {0}'.format(_sys.executable))
376 print('version_info : {0}'.format(_sys.version_info))
377 print('version : {0}'.format(_sys.version))
378 print('environment :')
379 for key,value in sorted(_os.environ.items()):
380 print(' {0}={1}'.format(key, value))
381 print('==================')
384 if __name__ == '__main__':
385 if not check(_sys.argv[1:]):