def test_install_pypi_before_non_pypi(self): # Given config = Configuration() config.update(auth=("nono", "le petit robot")) session = Session.from_configuration(config) session.authenticate(config.auth) repository = repository_factory(session, config.indices) enpkg = Enpkg(repository, session, [self.prefix]) enpkg.execute = mock.Mock() # When with mock_print() as mocked_print: with mock_raw_input("yes"): install_req(enpkg, config, "swig 2.0.2", FakeOptions()) # Then self._assert_ask_for_pypi(mocked_print) # When with mock_print() as mocked_print: with mock_raw_input("yes"): install_req(enpkg, config, "swig 2.0.2-1", FakeOptions()) # Then self._assert_ask_for_pypi(mocked_print)
def test_another_platform(self, config): # Given self._mock_auth() entries = [ dummy_repository_package_factory("MKL", "10.3", 1), dummy_repository_package_factory("numpy", "1.8.0", 1, dependencies=["MKL 10.3"]), ] _mock_index(entries, "rh5-64") _mock_index([], "rh5-32") r_output = textwrap.dedent("""\ Resolving dependencies for numpy: numpy-1.8.0-1.egg mkl 10.3 """) # When with mock_print() as m: main(["numpy", "--platform=rh5-32"]) # Then self.assertMultiLineEqual(m.value, "No egg found for requirement numpy\n") # When with mock_print() as m: main(["numpy", "--platform=rh5-64"]) # Then self.assertMultiLineEqual(m.value, r_output)
def test_invalid_certificate_config(self): self.maxDiff = None # Given url = "http://acme.com" config = Configuration() config.update(store_url=url) config.update(auth=("nono", "le petit robot")) config.write(self.config) responses.add_callback(responses.GET, re.compile(url + "/*"), self._dummy_ssl_error_callback) error_message = "To connect to 'acme.com' insecurely, add the `-k` " \ "flag to enpkg command" # When with use_given_config_context(self.config): with mock_print() as m: with self.assertRaises(SystemExit): main(["--config"]) # Then last_line = m.value.splitlines()[-1] self.assertMultiLineEqual(last_line, error_message)
def test_invalid_certificate_dont_webservice(self): self.maxDiff = None # Given url = "http://acme.com" config = Configuration() config.update(use_webservice=False, indexed_repositories=["http://acme.com/repo/"]) config.update(auth=("nono", "le petit robot")) config.write(self.config) def callback(request): msg = "Dummy SSL error" raise requests.exceptions.SSLError(msg, request=request) responses.add_callback(responses.HEAD, re.compile(url + "/*"), callback) error_message = textwrap.dedent("""\ SSL error: Dummy SSL error To connect to 'acme.com' insecurely, add the `-k` flag to enpkg command """) # When with use_given_config_context(self.config): with mock_print() as m: with self.assertRaises(SystemExit): main(["dummy_requirement"]) # Then self.assertMultiLineEqual(m.value, error_message)
def test_recursive_install_unavailable_dependency(self): config = Configuration() session = Session(DummyAuthenticator(), self.prefix) auth = ("nono", "le gros robot") session.authenticate(auth) config.update(auth=auth) r_output = textwrap.dedent(""" Cannot install 'scipy', as this package (or some of its requirements) are not available at your subscription level 'Canopy / EPD Free' (You are logged in as 'nono'). """) self.maxDiff = None numpy = dummy_repository_package_factory("numpy", "1.7.1", 1) numpy.available = False scipy = dummy_repository_package_factory("scipy", "0.12.0", 1) scipy.packages = ["numpy 1.7.1"] remote_entries = [numpy, scipy] with mock.patch("enstaller.main.Enpkg.execute"): enpkg = create_prefix_with_eggs(config, self.prefix, [], remote_entries) with mock_print() as m: with self.assertRaises(SystemExit): install_req(enpkg, config, "scipy", FakeOptions()) self.assertMultiLineEqual(m.value, r_output)
def test_enpkg_req_with_invalid_auth(self): """ Ensure 'enpkg req' doesn't crash when creds are invalid """ self.maxDiff = None responses.add(responses.GET, "https://api.enthought.com/accounts/user/info/", status=401, content_type='application/json') r_output = textwrap.dedent("""\ Could not authenticate as 'nono' (server answered: 'Invalid credentials.') Ensure your username and password are correct. You can change your authentication details with 'enpkg --userpass'. """) with open(self.config, "w") as fp: fp.write("EPD_auth = '{0}'".format(FAKE_CREDS)) with mock_print() as m: with use_given_config_context(self.config): with self.assertRaises(SystemExit): main_noexc(["nono"]) self.assertMultiLineEqual(m.value, r_output)
def test_install_broken_pypi_requirement(self): self.maxDiff = None # Given r_message = textwrap.dedent(""" Broken pypi package 'rednose-0.2.3-1.egg': missing dependency 'python_termstyle' Pypi packages are not officially supported. If this package is important to you, please contact Enthought support to request its inclusion in our officially supported repository. In the mean time, you may want to try installing 'rednose-0.2.3-1.egg' from sources with pip as follows: $ enpkg pip $ pip install <requested_package> """) config = Configuration() session = Session.from_configuration(config) session.authenticate(("nono", "le petit robot")) repository = repository_factory(session, config.indices) enpkg = Enpkg(repository, session, [self.prefix]) enpkg.execute = mock.Mock() # When with self.assertRaises(SystemExit): with mock_print() as mocked_print: with mock_raw_input("yes"): install_req(enpkg, config, "rednose", FakeOptions()) # Then self.assertMultiLineEqual(mocked_print.value, r_message)
def test_repository_factory(self): self.maxDiff = None # Given store_url = "https://acme.com" config = Configuration(store_url=store_url, use_webservice=False) config.set_repositories_from_names(["enthought/foo"]) responses.add(responses.GET, config.indices[0][0], status=404) session = mocked_session_factory(self.tempdir) r_warning = textwrap.dedent("""\ Warning: Could not fetch the following indices: - 'neko' Those repositories do not exist (or you do not have the rights to access them). You should edit your configuration to remove those repositories. """) # When with mock_print() as m: with mock.patch("enstaller.cli.utils._display_store_name", return_value="neko"): repository = repository_factory(session, config.indices) # Then self.assertEqual(len(list(repository.iter_packages())), 0) self.assertMultiLineEqual(m.value, r_warning) # When/Then with self.assertRaises(requests.exceptions.HTTPError): repository_factory(session, config.indices, raise_on_error=True)
def test_crash_handling_debug(self): with set_env_vars(ENSTALLER_DEBUG="1"): with mock.patch("enstaller.main.main", side_effect=Exception): with mock_print() as mocked_print: with self.assertRaises(Exception): main_noexc() self.assertMultiLineEqual(mocked_print.value, "")
def test_update_all_epd_updates(self): r_output = textwrap.dedent("""\ EPD 7.3-2 is available. To update to it (with confirmation warning), run 'enpkg epd'. The following updates and their dependencies will be installed Name installed available ============================================================ scipy 0.13.0-1 0.13.2-1 """) config = Configuration() installed_entries = [ dummy_installed_package_factory("numpy", "1.7.1", 2), dummy_installed_package_factory("scipy", "0.13.0", 1), dummy_installed_package_factory("epd", "7.3", 1), ] remote_entries = [ dummy_repository_package_factory("numpy", "1.7.1", 1), dummy_repository_package_factory("scipy", "0.13.2", 1), dummy_repository_package_factory("epd", "7.3", 2), ] with mkdtemp() as d: enpkg = create_prefix_with_eggs(config, d, installed_entries, remote_entries) with mock.patch("enstaller.cli.commands.install_req") as mocked_install_req: with mock_print() as m: update_all(enpkg, config, FakeOptions()) self.assertMultiLineEqual(m.value, r_output) mocked_install_req.assert_called()
def test_whats_new_no_new_epd(self): # Given r_output = textwrap.dedent("""\ Name installed available ============================================================ scipy 0.12.0-1 0.13.0-1 numpy 1.7.1-1 1.7.1-2 """) installed_entries = [ dummy_installed_package_factory("numpy", "1.7.1", 1), dummy_installed_package_factory("scipy", "0.12.0", 1) ] remote_entries = [ dummy_repository_package_factory("numpy", "1.7.1", 2), dummy_repository_package_factory("scipy", "0.13.0", 1) ] remote, installed = create_repositories(remote_entries, installed_entries) # When with mock_print() as m: whats_new(remote, installed) # Then # FIXME: we splitlines and compared wo caring about order, as # the actual line order depends on dict ordering from # EggCollection.query_installed. assertCountEqual(self, m.value.splitlines(), r_output.splitlines())
def test_update_all_epd_updates(self): r_output = textwrap.dedent("""\ EPD 7.3-2 is available. To update to it (with confirmation warning), run 'enpkg epd'. The following updates and their dependencies will be installed Name installed available ============================================================ scipy 0.13.0-1 0.13.2-1 """) config = Configuration() installed_entries = [ dummy_installed_package_factory("numpy", "1.7.1", 2), dummy_installed_package_factory("scipy", "0.13.0", 1), dummy_installed_package_factory("epd", "7.3", 1), ] remote_entries = [ dummy_repository_package_factory("numpy", "1.7.1", 1), dummy_repository_package_factory("scipy", "0.13.2", 1), dummy_repository_package_factory("epd", "7.3", 2), ] with mkdtemp() as d: enpkg = create_prefix_with_eggs(config, d, installed_entries, remote_entries) with mock.patch("enstaller.cli.commands.install_req" ) as mocked_install_req: with mock_print() as m: update_all(enpkg, config, FakeOptions()) self.assertMultiLineEqual(m.value, r_output) mocked_install_req.assert_called()
def test_401_index_handling(self): self.maxDiff = None # Given repo = "http://acme.com/repo/ets/" config = Configuration() config.update(use_webservice=False, indexed_repositories=[repo]) config.update(auth=("nono", "le petit robot")) config.write(self.config) url = repo + "index.json" responses.add(responses.HEAD, url, status=401) error_message = textwrap.dedent("""\ Could not authenticate as 'nono' (server answered: 'Invalid credentials') Ensure your username and password are correct. You can change your authentication details with 'enpkg --userpass'. """) # When with use_given_config_context(self.config): with mock_print() as m: with self.assertRaises(SystemExit): main(["dummy_requirement"]) # Then self.assertMultiLineEqual(m.value, error_message)
def test_log(self): with mock.patch("enstaller.cli.commands.History", spec=History) as mocked_history: with self.assertRaises(SystemExit) as e: with mock_print() as m: main_noexc(["--log"]) self.assertEqual(e.exception.code, 0) self.assertTrue(mocked_history.return_value.print_log.called) self.assertMultiLineEqual(m.value, "")
def test_enstaller_in_req(self): r_output = textwrap.dedent("""\ Enstaller has been updated. Please re-run your previous command. """) with mock_print() as m: with mock.patch("enstaller.main.inplace_update"): main(["enstaller"]) self.assertMultiLineEqual(m.value, r_output)
def test_freeze(self): installed_requirements = ["dummy 1.0.0-1", "another_dummy 1.0.1-1"] with mock.patch("enstaller.cli.commands.get_freeze_list", return_value=installed_requirements): with self.assertRaises(SystemExit) as e: with mock_print() as m: main_noexc(["--freeze"]) self.assertEqual(e.exception.code, 0) self.assertMultiLineEqual(m.value, "dummy 1.0.0-1\nanother_dummy 1.0.1-1\n")
def test_auth_requested_without_config(self): """ Ensure we ask for authentication if no .enstaller4rc is found. """ with no_initial_configuration_context(self.config): with mock_print() as m: with self.assertRaises(SystemExit): main_noexc([]) self.assertEqual(m.value, "No authentication configured, required " "to continue.To login, type 'enpkg --userpass'.\n")
def test__print_warning(self): # Given message = "fail to crash" r_output = "Warning: fail to crash\n\n" # When with mock_print() as m: _print_warning(message) # Then self.assertMultiLineEqual(m.value, r_output)
def test_auth_requested_without_config(self): """ Ensure we ask for authentication if no .enstaller4rc is found. """ with use_given_config_context(self.config): with mock_print() as m: with mock.patch("enstaller.main.configure_authentication_or_exit", lambda *a: sys.exit(-1)): with self.assertRaises(SystemExit): main_noexc([]) self.assertMultiLineEqual(m.value, "")
def test_list_bare(self): # Given sys_prefix = os.path.normpath(sys.prefix) # When with mock.patch("enstaller.cli.commands.print_installed"): with self.assertRaises(SystemExit) as e: with mock_print() as m: main_noexc(["--list"]) # Then self.assertEqual(e.exception.code, 0) self.assertMultiLineEqual(m.value, "prefix: {0}\n\n".format(sys_prefix))
def test_simple_non_existing_requirement(self): config = Configuration() r_error_string = "No egg found for requirement 'nono_le_petit_robot'.\n" non_existing_requirement = "nono_le_petit_robot" with mock.patch("enstaller.main.Enpkg.execute") as mocked_execute: enpkg = create_prefix_with_eggs(config, self.prefix, []) with mock_print() as mocked_print: with self.assertRaises(SystemExit) as e: install_req(enpkg, config, non_existing_requirement, FakeOptions()) self.assertEqual(exception_code(e), 1) self.assertEqual(mocked_print.value, r_error_string) mocked_execute.assert_not_called()
def test_userpass_with_config(self): """ Ensure enpkg --userpass doesn't crash when creds are invalid """ r_output = ("Could not authenticate. Please check your credentials " "and try again.\nNo modification was written.\n") with no_initial_configuration_context(self.config): with mock_print() as m: with mock_input_auth("nono", "robot"): with self.assertRaises(SystemExit): main_noexc(["--userpass"]) self.assertMultiLineEqual(m.value, r_output)
def test_crash_handling_default(self): r_output = textwrap.dedent("""\ enstaller: Error: enstaller crashed (uncaught exception {0}: Exception()). Please report this on enstaller issue tracker: http://github.com/enthought/enstaller/issues You can get a full traceback by setting the ENSTALLER_DEBUG environment variable """.format(Exception)) env = ControlledEnv(["ENSTALLER_DEBUG"]) with mock.patch("enstaller.main.os.environ", env): with mock.patch("enstaller.main.main", side_effect=Exception): with mock_print() as mocked_print: with self.assertRaises(SystemExit) as e: main_noexc() self.assertEqual(exception_code(e), 1) self.assertMultiLineEqual(mocked_print.value, r_output)
def test_print_installed(self): with mkdtemp() as d: r_out = textwrap.dedent("""\ Name Version Store ============================================================ dummy 1.0.1-1 {0} """.format(disp_store_info(d))) ec = EggInst(DUMMY_EGG, d) ec.install() repository = Repository._from_prefixes([d]) with mock_print() as m: print_installed(repository) self.assertMultiLineEqual(m.value, r_out) r_out = textwrap.dedent("""\ Name Version Store ============================================================ """) repository = Repository._from_prefixes([d]) with mock_print() as m: print_installed(repository, pat=re.compile("no_dummy")) self.assertEqual(m.value, r_out)
def test_enpkg_req_with_invalid_auth(self): """ Ensure 'enpkg req' doesn't crash when creds are invalid """ r_output = textwrap.dedent("""\ Could not authenticate with user 'nono'. You can change your authentication details with 'enpkg --userpass' """) with open(self.config, "w") as fp: fp.write("EPD_auth = '{0}'".format(FAKE_CREDS)) with mock_print() as m: with no_initial_configuration_context(self.config): with self.assertRaises(SystemExit): main_noexc(["nono"]) self.assertMultiLineEqual(m.value, r_output)
def test_print_config(self): self.maxDiff = None # Given config = Configuration() config.update(prefix=sys.prefix) template = textwrap.dedent("""\ Python version: {pyver} enstaller version: {version} sys.prefix: {sys_prefix} platform: {platform} architecture: {arch} use_webservice: True keyring backend: {keyring_backend} settings: prefix = {prefix} repository_cache = {repository_cache} noapp = False proxy = None You are logged in as 'dummy' (David Cournapeau). Subscription level: Canopy / EPD Basic or above """) r_output = template.format(pyver=PY_VER, sys_prefix=os.path.normpath(sys.prefix), version=__version__, platform=platform.platform(), arch=platform.architecture()[0], keyring_backend=_keyring_backend_name(), prefix=os.path.normpath(config.prefix), repository_cache=config.repository_cache) responses.add(responses.GET, "https://api.enthought.com/accounts/user/info/", body=json.dumps(R_JSON_AUTH_RESP)) # When with self.assertRaises(SystemExit) as e: with mock_print() as m: main_noexc(["--config"]) # Then self.assertEqual(e.exception.code, 0) self.assertMultiLineEqual(m.value, r_output)
def test_update_all_no_updates(self): r_output = "No new version of any installed package is available\n" config = Configuration() installed_entries = [ dummy_installed_package_factory("numpy", "1.7.1", 2), dummy_installed_package_factory("scipy", "0.13.0", 1) ] remote_entries = [ dummy_repository_package_factory("numpy", "1.7.1", 1), dummy_repository_package_factory("scipy", "0.12.0", 1) ] with mkdtemp() as d: enpkg = create_prefix_with_eggs(config, d, installed_entries, remote_entries) with mock_print() as m: update_all(enpkg, config, FakeOptions()) self.assertMultiLineEqual(m.value, r_output)
def test_info_option(self): self.maxDiff = None # Given entries = [dummy_repository_package_factory("enstaller", "4.6.2", 1), dummy_repository_package_factory("enstaller", "4.6.3", 1)] mtime = 0.0 r_output = textwrap.dedent("""\ Package: enstaller Version: 4.6.2-1 Product: commercial Available: True Python version: {python_version} Store location: {store_location_1} Last modified: {last_modified} MD5: {md5} Size: {size} Requirements: None Version: 4.6.3-1 Product: commercial Available: True Python version: {python_version} Store location: {store_location_2} Last modified: {last_modified} MD5: {md5} Size: {size} Requirements: None """.format(md5=FAKE_MD5, size=FAKE_SIZE, python_version=PY_VER, store_location_1=entries[0].source_url, store_location_2=entries[1].source_url, last_modified=datetime.datetime.fromtimestamp(mtime))) remote_repository, installed_repository = \ create_repositories(remote_entries=entries) # When with mock_print() as m: info_option(remote_repository, installed_repository, "enstaller") # Then self.assertMultiLineEqual(m.value, r_output)
def test_info_option(self): self.maxDiff = None # Given mtime = 0.0 r_output = textwrap.dedent("""\ Package: enstaller Version: 4.6.2-1 Product: commercial Available: True Python version: {2} Store location: {3} Last modified: {4} MD5: {0} Size: {1} Requirements: None Version: 4.6.3-1 Product: commercial Available: True Python version: {2} Store location: {3} Last modified: {4} MD5: {0} Size: {1} Requirements: None """.format(FAKE_MD5, FAKE_SIZE, PY_VER, "", datetime.datetime.fromtimestamp(mtime))) entries = [ dummy_repository_package_factory("enstaller", "4.6.2", 1), dummy_repository_package_factory("enstaller", "4.6.3", 1) ] remote_repository, installed_repository = \ create_repositories(remote_entries=entries) # When with mock_print() as m: info_option(remote_repository, installed_repository, "enstaller") # Then self.assertMultiLineEqual(m.value, r_output)
def test_whats_new_new_epd(self): # Given r_output = "EPD 7.3-2 is available. To update to it (with " \ "confirmation warning), run 'enpkg epd'.\n" installed_entries = [ dummy_installed_package_factory("EPD", "7.2", 1), ] remote_entries = [ dummy_repository_package_factory("EPD", "7.3", 2), ] remote, installed = create_repositories(remote_entries, installed_entries) # When with mock_print() as m: whats_new(remote, installed) # Then self.assertMultiLineEqual(m.value, r_output)
def test_simple(self, config): # Given self._mock_auth() entries = [ dummy_repository_package_factory("MKL", "10.3", 1), dummy_repository_package_factory("numpy", "1.8.0", 1, dependencies=["MKL 10.3"]), ] _mock_index(entries) r_output = textwrap.dedent("""\ Resolving dependencies for numpy: numpy-1.8.0-1.egg mkl 10.3 """) # When with mock_print() as m: main(["numpy"]) # Then self.assertMultiLineEqual(m.value, r_output)
def test_info_option(self): self.maxDiff = None # Given mtime = 0.0 r_output = textwrap.dedent("""\ Package: enstaller Version: 4.6.2-1 Product: commercial Available: True Python version: {2} Store location: {3} Last modified: {4} MD5: {0} Size: {1} Requirements: None Version: 4.6.3-1 Product: commercial Available: True Python version: {2} Store location: {3} Last modified: {4} MD5: {0} Size: {1} Requirements: None """.format(FAKE_MD5, FAKE_SIZE, PY_VER, "", datetime.datetime.fromtimestamp(mtime))) entries = [dummy_repository_package_factory("enstaller", "4.6.2", 1), dummy_repository_package_factory("enstaller", "4.6.3", 1)] remote_repository, installed_repository = \ create_repositories(remote_entries=entries) # When with mock_print() as m: info_option(remote_repository, installed_repository, "enstaller") # Then self.assertMultiLineEqual(m.value, r_output)
def test_simple(self): # Given config = Configuration() session = Session.from_configuration(config) entries = [ dummy_repository_package_factory("MKL", "10.3", 1), dummy_repository_package_factory("numpy", "1.8.0", 1, dependencies=["MKL 10.3"]), ] _mock_index(entries) r_output = textwrap.dedent("""\ Resolving dependencies for numpy: numpy-1.8.0-1.egg mkl 10.3 """) # When with mock_print() as m: query_platform(session, config.repositories, "numpy", custom_plat) # Then self.assertMultiLineEqual(m.value, r_output)
def test_whats_new_no_updates(self): # Given r_output = "No new version of any installed package is available\n" installed_entries = [ dummy_installed_package_factory("numpy", "1.7.1", 2), dummy_installed_package_factory("scipy", "0.13.0", 1) ] remote_entries = [ dummy_repository_package_factory("numpy", "1.7.1", 1), dummy_repository_package_factory("scipy", "0.12.0", 1) ] remote, installed = create_repositories(remote_entries, installed_entries) # When with mock_print() as m: whats_new(remote, installed) # Then self.assertMultiLineEqual(m.value, r_output)
def test_simple(self): # Given config = Configuration() session = Session.from_configuration(config) entries = [ dummy_repository_package_factory("MKL", "10.3", 1), dummy_repository_package_factory("numpy", "1.8.0", 1, dependencies=["MKL 10.3"]), ] _mock_index(entries) r_output = textwrap.dedent("""\ Resolving dependencies for numpy: numpy-1.8.0-1.egg mkl 10.3 """) # When with mock_print() as m: query_platform(session, config.indices, "numpy", custom_plat) # Then self.assertMultiLineEqual(m.value, r_output)
def test_install_pypi_requirement(self): self.maxDiff = None # Given r_message = textwrap.dedent("""\ The following packages/requirements are coming from the PyPi repo: rednose The PyPi repository which contains >10,000 untested ("as is") packages. Some packages are licensed under GPL or other licenses which are prohibited for some users. Dependencies may not be provided. If you need an updated version or if the installation fails due to unmet dependencies, the Knowledge Base article Installing external packages into Canopy Python (https://support.enthought.com/entries/23389761) may help you with installing it. Are you sure that you wish to proceed? (y/[n]) """) config = Configuration() session = Session.from_configuration(config) session.authenticate(("nono", "le petit robot")) repository = repository_factory(session, config.indices) enpkg = Enpkg(repository, session, [self.prefix]) enpkg.execute = mock.Mock() # When with mock_print() as mocked_print: with mock_raw_input("yes"): install_req(enpkg, config, "rednose", FakeOptions()) # Then self.assertMultiLineEqual(mocked_print.value, r_message)