def test_freeze_error(self): with self.assertRaises(pip_checker.PipError) as e: pip_checker.check( pip_command=[self._fake_pip_path, '--freeze-returncode=1'], packages=['six'], clean=True) self.assertIn('freeze', e.exception.command)
def test_uninstall_error(self): with self.assertRaises(pip_checker.PipError) as e: pip_checker.check(pip_command=[ self._fake_pip_path, '--expected-install-args=-U,six', '--uninstall-returncode=1', '--freeze-output=six==1.2.3\n' ], packages=['six'], clean=True) self.assertIn('uninstall', e.exception.command)
def test_check_warning(self, mock_docker, mock__call_pypi_json_api): mock_docker.return_value = MockDockerClient() expected_list_output = [{ 'name': 'six', 'version': '1.2.3', 'latest_version': '1.2.4', }] expected_dependency_info = { 'six': { 'installed_version': '1.2.3', 'installed_version_time': '2018-05-10T15:00:00', 'latest_version': '1.2.4', 'current_time': '2018-06-13T16:13:33.744591', 'latest_version_time': '2018-06-13T18:29:51', 'is_latest': False } } mock_datetime = mock.Mock() mock_now = mock.Mock() mock_now.isoformat.return_value = '2018-06-13T16:13:33.744591' mock_datetime.datetime.now.return_value = mock_now patch = mock.patch('pip_checker.datetime', mock_datetime) mock__call_pypi_json_api.return_value = { 'releases': { '1.2.4': [ { 'upload_time': '2018-06-13T18:29:51', }, ], '1.2.3': [ { 'upload_time': '2018-05-10T15:00:00', } ], }, } with patch: check_result = pip_checker.check( pip_command=[ self._fake_pip_path, '--check-returncode=1', '--check-output=bad-check', '--freeze-output=six==1.2.3\n', '--list-output={}'.format( json.dumps(expected_list_output)) ], packages=['six']) expected_check_result = pip_checker.PipCheckResult( packages=['six'], result_type=pip_checker.PipCheckResultType.CHECK_WARNING, result_text='bad-check', dependency_info=expected_dependency_info) self.assertEqual( check_result, expected_check_result)
def test_all_whitelists_pip_install(self): py2_pkgs, py3_pkgs = [], [] for pkg in configs.WHITELIST_PKGS: if pkg not in configs.PKG_PY_VERSION_NOT_SUPPORTED[2]: py2_pkgs.append(pkg) if pkg not in configs.PKG_PY_VERSION_NOT_SUPPORTED[3]: py3_pkgs.append(pkg) for url, pkg in configs.WHITELIST_URLS.items(): if pkg not in configs.PKG_PY_VERSION_NOT_SUPPORTED[2]: py2_pkgs.append(url) if pkg not in configs.PKG_PY_VERSION_NOT_SUPPORTED[3]: py3_pkgs.append(url) args = [ # ('python', py2_pkgs), ('python3', py3_pkgs), ] for command, packages in args: pip_result = pip_checker.check([command, '-m', 'pip'], packages, clean=True) self.assertIsNotNone(pip_result) results = dict(result=pip_result.result_type.name, packages=pip_result.packages, description=pip_result.result_text, dependency_info=pip_result.dependency_info) if results['result'] == 'INSTALL_ERROR': logging.warning(command) logging.warning(results['description']) self.assertFalse(results['result'] == 'INSTALL_ERROR')
def check(): packages = flask.request.args.getlist('package') if not packages: return flask.make_response( "Request must specify at least one 'package' parameter", 400) sanitized_packages = _sanitize_packages(packages) unsupported_packages = frozenset(packages) - frozenset(sanitized_packages) if unsupported_packages: return flask.make_response( 'Request contains unrecognized packages: {}'.format( ', '.join(unsupported_packages)), 400) python_version = flask.request.args.get('python-version') if not python_version: return flask.make_response( "Request must specify 'python-version' parameter", 400) if python_version not in PYTHON_VERSION_TO_COMMAND: return flask.make_response( 'Invalid Python version specified. Must be one of: {}'.format( ', '.join(PYTHON_VERSION_TO_COMMAND), 400)) python_command = PYTHON_VERSION_TO_COMMAND[python_version] try: pip_result = pip_checker.check(python_command, packages) except pip_checker.PipCheckerError as pip_error: return flask.make_response(pip_error.error_msg, 500) return flask.jsonify(result=pip_result.result_type.name, packages=pip_result.packages, description=pip_result.result_text, dependency_info=pip_result.dependency_info)
def test_success_with_clean(self, mock__call_pypi_json_api): expected_list_output = [{ 'name': 'six', 'version': '1.2.3', 'latest_version': '1.2.4', }] expected_dependency_info = { 'six': { 'installed_version': '1.2.3', 'installed_version_time': '2018-05-10T15:00:00', 'latest_version': '1.2.4', 'current_time': '2018-06-13T16:13:33.744591', 'latest_version_time': '2018-06-13T18:29:51', 'is_latest': False } } mock_datetime = mock.Mock() mock_now = mock.Mock() mock_now.isoformat.return_value = '2018-06-13T16:13:33.744591' mock_datetime.datetime.now.return_value = mock_now patch = mock.patch('pip_checker.datetime', mock_datetime) mock__call_pypi_json_api.return_value = { 'releases': { '1.2.4': [ { 'upload_time': '2018-06-13T18:29:51', }, ], '1.2.3': [{ 'upload_time': '2018-05-10T15:00:00', }], }, } with patch: check_result = pip_checker.check(pip_command=[ self._fake_pip_path, '--expected-install-args=-U,six', '--uninstall-returncode=0', '--freeze-output=six==1.2.3\n', '--list-output={}'.format(json.dumps(expected_list_output)) ], packages=['six'], clean=True) expected_check_result = pip_checker.PipCheckResult( packages=['six'], result_type=pip_checker.PipCheckResultType.SUCCESS, result_text=None, dependency_info=expected_dependency_info) self.assertEqual(check_result, expected_check_result)
def test_install_failure(self): check_result = pip_checker.check(pip_command=[ self._fake_pip_path, '--expected-install-args=-U,six', '--install-returncode=1', '--install-output=bad-install' ], packages=['six']) self.assertEqual( check_result, pip_checker.PipCheckResult( packages=['six'], result_type=pip_checker.PipCheckResultType.INSTALL_ERROR, result_text='bad-install', dependency_info=None))
def _check(self, start_response, python_version, packages): if not packages: start_response('400 Bad Request', [('Content-Type', 'text/plain; charset=utf-8')]) return [b'Request must specify at least one package'] if not python_version: start_response('400 Bad Request', [('Content-Type', 'text/plain; charset=utf-8')]) return [b'Request must specify the Python version to use'] if python_version not in self._python_version_to_interpreter: start_response('400 Bad Request', [('Content-Type', 'text/plain; charset=utf-8')]) return [ b'Invalid Python version specified. Must be one of: %s' % (', '.join( self._python_version_to_interpreter).encode('utf-8')) ] python_command = self._python_version_to_interpreter[python_version] if self._install_once: self._shutdown() try: pip_result = pip_checker.check([python_command, '-m', 'pip'], packages, clean=self._clean) except pip_checker.PipError as pip_error: start_response('500 Internal Server Error', [('Content-Type', 'text/plain; charset=utf-8')]) with open(pip_error.stderr_path, 'r') as f: error_text = f.read() logging.error('pip command ("%s") failed with:\n%s\n', pip_error.command_string, error_text) return [ b'pip command ("%s") ' % pip_error.command_string.encode('utf-8'), b'failed with:\n', error_text.encode('utf-8'), b'\n' ] results = dict(result=pip_result.result_type.name, packages=pip_result.packages, description=pip_result.result_text, dependency_info=pip_result.dependency_info) start_response('200 OK', [('Content-Type', 'application/json')]) return [json.dumps(results).encode('utf-8')]
def _check(self, start_response, python_version, packages): if not packages: start_response('400 Bad Request', [('Content-Type', 'text/plain; charset=utf-8')]) return [b'Request must specify at least one package'] sanitized_packages = _sanitize_packages(packages) if sanitized_packages != packages: start_response('400 Bad Request', [('Content-Type', 'text/plain; charset=utf-8')]) return [b'Request contains third party github head packages.'] if not python_version: start_response('400 Bad Request', [('Content-Type', 'text/plain; charset=utf-8')]) return [b'Request must specify the Python version to use'] if python_version not in PYTHON_VERSION_TO_COMMAND: start_response('400 Bad Request', [('Content-Type', 'text/plain; charset=utf-8')]) return [ b'Invalid Python version specified. Must be one of: %s' % (', '.join(PYTHON_VERSION_TO_COMMAND).encode('utf-8')) ] python_command = PYTHON_VERSION_TO_COMMAND[python_version] try: pip_result = pip_checker.check(python_command, packages) except pip_checker.PipCheckerError as pip_error: start_response('500 Internal Server Error', [('Content-Type', 'text/plain; charset=utf-8')]) logging.error('Command failed with:\n%s\n', pip_error.error_msg) return [b'pip command failed with:\n', pip_error.error_msg, b'\n'] results = dict(result=pip_result.result_type.name, packages=pip_result.packages, description=pip_result.result_text, dependency_info=pip_result.dependency_info) start_response('200 OK', [('Content-Type', 'application/json')]) return [json.dumps(results).encode('utf-8')]