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_from_configuration(self): # Given config = Configuration() # When/Then with Session.from_configuration(config) as session: self.assertTrue(session._raw.verify) self.assertIsInstance(session._authenticator, LegacyCanopyAuthManager) # When/Then config = Configuration() config.update(verify_ssl=False) with Session.from_configuration(config) as session: self.assertFalse(session._raw.verify) # Given config = Configuration() config.update(verify_ssl=False, use_webservice=False) # When/Then with Session.from_configuration(config) as session: self.assertFalse(session._raw.verify) self.assertIsInstance(session._authenticator, OldRepoAuthManager) # Given config = Configuration() config.update(store_url="brood+http://acme.com") # When/Then with Session.from_configuration(config) as session: self.assertIsInstance(session._authenticator, BroodAuthenticator)
def test_download(self): # Given url = "http://acme.com/foo.bin" responses.add(responses.GET, url, body=b"some data") config = Configuration() # When with Session.from_configuration(config) as session: target = session.download(url) # Then try: self.assertTrue(os.path.exists(target)) with open(target, "rb") as fp: self.assertEqual(fp.read(), b"some data") finally: os.unlink(target) self.assertEqual(target, "foo.bin") # When with Session.from_configuration(config) as session: target = session.download(url, "foo.baz") # Then try: self.assertTrue(os.path.exists(target)) with open(target, "rb") as fp: self.assertEqual(fp.read(), b"some data") finally: os.unlink(target) self.assertEqual(target, "foo.baz")
def setUp(self): self.prefix = tempfile.mkdtemp() self.config = Configuration() self.config.update(use_webservice=False, indexed_repositories=["http://acme.com"]) self.session = Session(self.klass.from_configuration(self.config), self.prefix)
def test_from_configuration(self): # Given responses.add(responses.GET, self.config.api_url, status=200, body=json.dumps(R_JSON_AUTH_RESP)) authenticator = LegacyCanopyAuthManager.from_configuration(self.config) session = Session(authenticator, self.prefix) # When with session: # Then no exception session.authenticate((FAKE_USER, FAKE_PASSWORD))
def test_use_webservice_invalid_user(self): # Given config = Configuration() responses.add(responses.GET, config.api_url, body=json.dumps(R_JSON_NOAUTH_RESP), content_type='application/json') # When/Then session = Session(LegacyCanopyAuthManager(config.api_url), self.prefix) with session: with self.assertRaises(AuthFailedError): session.authenticate((FAKE_USER, FAKE_PASSWORD))
def test_max_retries(self): # Given config = Configuration() # When/Then with Session.from_configuration(config) as session: for prefix in ("http://", "https://"): self.assertEqual(session._raw.adapters[prefix].max_retries, 0) # When/Then config.update(max_retries=3) with Session.from_configuration(config) as session: for prefix in ("http://", "https://"): self.assertEqual(session._raw.adapters[prefix].max_retries, 3)
class AuthManagerBase(unittest.TestCase): klass = None def setUp(self): self.prefix = tempfile.mkdtemp() self.config = Configuration() self.config.update(use_webservice=False, indexed_repositories=["http://acme.com"]) self.session = Session(self.klass.from_configuration(self.config), self.prefix) def tearDown(self): shutil.rmtree(self.prefix) self.session.close()
def test_from_configuration(self): # Given responses.add(responses.HEAD, self.config.indices[0][0], status=200, body=json.dumps(R_JSON_AUTH_RESP)) authenticator = OldRepoAuthManager.from_configuration(self.config) session = Session(authenticator, self.prefix) # When with session: session.authenticate((FAKE_USER, FAKE_PASSWORD)) # Then self.assertIsInstance(session._raw.auth, requests.auth.HTTPBasicAuth) self.assertEqual(session._raw.auth.username, FAKE_USER) self.assertEqual(session._raw.auth.password, FAKE_PASSWORD)
def test_from_configuration(self): # Given responses.add(responses.POST, self.token_url, status=200, body=json.dumps({"token": "dummy token"})) authenticator = BroodAuthenticator.from_configuration(self.config) session = Session(authenticator, self.prefix) r_auth = BroodBearerTokenAuth("dummy token") # When with session: session.authenticate((FAKE_USER, FAKE_PASSWORD)) # Then self.assertIsInstance(session._raw.auth, BroodBearerTokenAuth) self.assertEqual(session._raw.auth._token, r_auth._token)
def test_no_acct(self): # Given url = "https://acme.com" auth_url = url + "/accounts/user/info/" config = Configuration() config.update(store_url=url) def callback(request): if auth != ("valid_user", "valid_password"): return (403, {}, "") return (200, {}, json.dumps(R_JSON_AUTH_RESP)) responses.add_callback(responses.GET, auth_url, callback) write_default_config(self.f) with Session.from_configuration(config) as session: config = Configuration() config.update(store_url=url) auth = ("invalid_user", "invalid_password") with self.assertRaises(AuthFailedError): usr = config._checked_change_auth(auth, session, self.f) config = Configuration() auth = ("valid_user", "valid_password") usr = config._checked_change_auth(auth, session, self.f) self.assertTrue(usr.is_authenticated) self.assertEqual(config.auth, UserPasswordAuth("valid_user", "valid_password"))
def test_simple_in_memory(self): output_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 No valid auth information in configuration, cannot authenticate. You are not logged in. To log in, type 'enpkg --userpass'. """).format(pyver=PY_VER, sys_prefix=sys.prefix, version=__version__, platform=platform.platform(), arch=platform.architecture()[0], keyring_backend=_keyring_backend_name()) config = Configuration() prefix = config.prefix repository_cache = os.path.join(prefix, "LOCAL-REPO") r_output = output_template.format(prefix=os.path.normpath(prefix), repository_cache=repository_cache) with mock_print() as m: print_config(config, config.prefix, Session(DummyAuthenticator(), self.prefix)) self.assertMultiLineEqual(m.value, r_output)
def test_ensure_authenticated_config(self): # Given r_message = textwrap.dedent("""\ Could not authenticate as 'nono' Please check your credentials/configuration and try again (original error is: 'Authentication error: Invalid user login.'). You can change your authentication details with 'enpkg --userpass'. """) store_url = "https://acme.com" responses.add(responses.GET, store_url + "/accounts/user/info/", body=json.dumps(R_JSON_NOAUTH_RESP)) config = Configuration() config.update(store_url=store_url, auth=("nono", "le petit robot")) session = Session.from_configuration(config) # When/Then with mock_print() as m: with self.assertRaises(SystemExit) as e: ensure_authenticated_config(config, "", session) self.assertEqual(exception_code(e), -1) self.assertMultiLineEqual(m.value, r_message)
def test_not_available(self): responses.add(responses.GET, "https://acme.com/accounts/user/info/", body=json.dumps(R_JSON_AUTH_FREE_RESP)) config = Configuration() config.update(store_url="https://acme.com") r_output = textwrap.dedent("""\ Name Versions Product Note ================================================================================ another_package 2.0.0-1 commercial not subscribed to dummy 0.9.8-1 commercial {0} 1.0.1-1 commercial {0} Note: some of those packages are not available at your current subscription level ('Canopy / EPD Free'). """.format("")) another_entry = dummy_repository_package_factory("another_package", "2.0.0", 1) another_entry.available = False entries = [dummy_repository_package_factory("dummy", "1.0.1", 1), dummy_repository_package_factory("dummy", "0.9.8", 1), another_entry] with Session.from_configuration(config) as session: with mkdtemp() as d: with mock_print() as m: enpkg = create_prefix_with_eggs(config, d, remote_entries=entries) search(enpkg._remote_repository, enpkg._installed_repository, config, session) 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_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_max_retries_with_etag(self): # Given config = Configuration() # When/Then with Session.from_configuration(config) as session: with session.etag(): for prefix in ("http://", "https://"): max_retries = session._raw.adapters[prefix].max_retries self.assertEqual(max_retries.total, 0) # When/Then config.update(max_retries=3) with Session.from_configuration(config) as session: with session.etag(): for prefix in ("http://", "https://"): max_retries = session._raw.adapters[prefix].max_retries self.assertEqual(max_retries.total, 3)
def test_remote_success(self): write_default_config(self.f) config = Configuration() auth = ("usr", "password") session = Session(DummyAuthenticator(old_auth_user), self.d) with session: usr = config._checked_change_auth(auth, session, self.f) self.assertEqual(usr, UserInfo(True))
def test_agent(self): # Given url = "http://acme.com" responses.add(responses.GET, url) config = Configuration() r_user_agent = "enstaller/{0}".format(enstaller.__version__) # When/Then with Session.from_configuration(config) as session: resp = session._raw_get(url) self.assertTrue( resp.request.headers["user-agent"].startswith(r_user_agent))
def test_agent(self): # Given url = "http://acme.com" responses.add(responses.GET, url) config = Configuration() r_user_agent = "enstaller/{0}".format(enstaller.__version__) # When/Then with Session.from_configuration(config) as session: resp = session._raw_get(url) self.assertTrue(resp.request.headers["user-agent"]. startswith(r_user_agent))
def test_authenticated_from_configuration_wo_auth(self): # Given url = "http://acme.com" responses.add(responses.GET, url) responses.add(responses.GET, url + "/accounts/user/info/", body=json.dumps(R_JSON_AUTH_RESP)) config = Configuration() config.update(store_url=url) # When/Then with self.assertRaises(EnstallerException): with Session.authenticated_from_configuration(config): pass
def test_from_repository_info_empty(self): # Given repository_info = BroodRepositoryInfo("https://api.enthought.com", "enthought/free") config = Configuration(use_webservice=False, auth=("nono", "password")) config._store_kind = STORE_KIND_BROOD session = Session.authenticated_from_configuration(config) # When repository = Repository.from_repository_info(session, repository_info) # Then self.assertEqual(len(repository), 0)
def test_authenticated_from_configuration(self): # Given url = "http://acme.com" responses.add(responses.GET, url) responses.add(responses.GET, url + "/accounts/user/info/", body=json.dumps(R_JSON_AUTH_RESP)) config = Configuration() config.update(store_url=url, auth=("yoyo", "yeye")) # When with Session.authenticated_from_configuration(config) as session: resp = session._raw_get(url) # Then self.assertTrue(resp.status_code, 200)
def test_repository_factory(self): # Given config = Configuration() entries = [ dummy_repository_package_factory("numpy", "1.8.0", 1), dummy_repository_package_factory("scipy", "0.13.3", 1), ] self._mock_index(entries) # When with Session(DummyAuthenticator(), self.tempdir) as session: repository = repository_factory(session, config.indices) # Then repository.find_package("numpy", "1.8.0-1") repository.find_package("scipy", "0.13.3-1") self.assertEqual(repository.find_packages("nose"), [])
def test_simple_old_legacy(self): # Given url = "https://acme.com" config = Configuration() config.update(use_webservice=False, auth=FAKE_AUTH) config.update(indexed_repositories=[url]) responses.add(responses.HEAD, config.indices[0][0], status=200) session = Session.from_configuration(config) session.authenticate(config.auth) # When user_info = UserInfo.from_session(session) # Then self.assertTrue(user_info.is_authenticated)
def test_simple_legacy_canopy(self): # Given url = "https://api.enthought.com" config = Configuration() config.update(store_url=url, auth=FAKE_AUTH) responses.add(responses.GET, url + "/accounts/user/info/", status=200, body=json.dumps(R_JSON_AUTH_RESP)) session = Session.from_configuration(config) session.authenticate(config.auth) # When user_info = UserInfo.from_session(session) # Then self.assertEqual(user_info.first_name, R_JSON_AUTH_RESP["first_name"])
def test_simple_brood_auth(self): # Given url = "https://acme.com" token_url = url + "/api/v0/json/auth/tokens/auth" config = Configuration() config.update(store_url="brood+" + url, auth=FAKE_AUTH) responses.add(responses.POST, token_url, status=200, body=json.dumps({"token": "dummy token"})) session = Session.from_configuration(config) session.authenticate(config.auth) # When user_info = UserInfo.from_session(session) # Then self.assertTrue(user_info.is_authenticated)
def test_handle_stripped_header_incomplete_data(self): # Given def callback(request): self.assertTrue("gzip" in request.headers.get("Accept-Encoding", "")) headers = {"Content-Encoding": ""} incomplete_body = self._gzip_compress(b"{}")[:-1] return (200, headers, incomplete_body) responses.add_callback(responses.GET, "https://acme.com/index.json", callback) config = Configuration() # When/Then session = Session.from_configuration(config) resp = session.fetch("https://acme.com/index.json") with self.assertRaises(requests.exceptions.ContentDecodingError): _fetch_json_with_progress(resp, "acme.com", quiet=False)
def test_from_repository_infos_nonempty(self): # Given repository_infos = ( BroodRepositoryInfo("https://api.enthought.com", "enthought/free"), BroodRepositoryInfo( "https://api.enthought.com", "enthought/commercial" ), ) config = Configuration(use_webservice=False, auth=("nono", "password")) config._store_kind = STORE_KIND_BROOD session = Session.authenticated_from_configuration(config) # When repository = Repository.from_repository_infos(session, repository_infos) # Then self.assertEqual(len(repository), 2) self.assertEqual(len(repository.find_packages("nose")), 2)
def test_handle_stripped_header_incomplete_data(self): # Given def callback(request): self.assertTrue( "gzip" in request.headers.get("Accept-Encoding", "")) headers = {"Content-Encoding": ""} incomplete_body = self._gzip_compress(b"{}")[:-1] return (200, headers, incomplete_body) responses.add_callback(responses.GET, "https://acme.com/index.json", callback) config = Configuration() # When/Then session = Session.from_configuration(config) resp = session.fetch("https://acme.com/index.json") with self.assertRaises(requests.exceptions.ContentDecodingError): _fetch_json_with_progress(resp, "acme.com", quiet=False)
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_handle_stripped_header(self): # Given def callback(request): self.assertTrue("gzip" in request.headers.get("Accept-Encoding", "")) headers = {"Content-Encoding": ""} body = self._gzip_compress(b"{}") return (200, headers, body) responses.add_callback(responses.GET, "https://acme.com/index.json", callback) config = Configuration() # When session = Session.from_configuration(config) resp = session.fetch("https://acme.com/index.json") data = _fetch_json_with_progress(resp, "acme.com", quiet=False) # Then self.assertEqual(data, {})
def test_handle_stripped_header(self): # Given def callback(request): self.assertTrue( "gzip" in request.headers.get("Accept-Encoding", "")) headers = {"Content-Encoding": ""} body = self._gzip_compress(b"{}") return (200, headers, body) responses.add_callback(responses.GET, "https://acme.com/index.json", callback) config = Configuration() # When session = Session.from_configuration(config) resp = session.fetch("https://acme.com/index.json") data = _fetch_json_with_progress(resp, "acme.com", quiet=False) # Then self.assertEqual(data, {})
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)
def main(argv=None): argv = argv or sys.argv[1:] plat = enstaller.plat.custom_plat p = argparse.ArgumentParser() p.add_argument("requirement", help="Requirement string (e.g. 'mayavi')") p.add_argument("--platform", help="Platform to consider (default: %(default)s). 'all' works as well", default=plat) p.add_argument("--auth", help="Authentication (default: enpkg credentials)") namespace = p.parse_args(argv) config = Configuration._from_legacy_locations() config._platform = namespace.platform if namespace.auth is None: auth = config.auth else: auth = tuple(namespace.auth.split(":")) session = Session.from_configuration(config) with session: session.authenticate(auth) if namespace.platform == "all": platforms = ["rh5-32", "rh5-64", "osx-32", "osx-64", "win-32", "win-64"] for platform in platforms: query_platform(session, config.indices, namespace.requirement, platform) else: query_platform(session, config.indices, namespace.requirement, namespace.platform)
def main(argv=None): argv = argv or sys.argv[1:] plat = enstaller.plat.custom_plat p = argparse.ArgumentParser() p.add_argument("requirement", help="Requirement string (e.g. 'mayavi')") p.add_argument("--platform", help="Platform to consider (default: %(default)s). 'all' works as well", default=plat) p.add_argument("--auth", help="Authentication (default: enpkg credentials)") namespace = p.parse_args(argv) config = Configuration._from_legacy_locations() config._platform = namespace.platform if namespace.auth is None: auth = config.auth else: auth = tuple(namespace.auth.split(":")) session = Session.from_configuration(config) with session: session.authenticate(auth) if namespace.platform == "all": platforms = ["rh5-32", "rh5-64", "osx-32", "osx-64", "win-32", "win-64"] for platform in platforms: query_platform(session, config.repositories, namespace.requirement, platform) else: query_platform(session, config.repositories, namespace.requirement, namespace.platform)
def test_not_available(self): responses.add(responses.GET, "https://acme.com/accounts/user/info/", body=json.dumps(R_JSON_AUTH_FREE_RESP)) config = Configuration() config.update(store_url="https://acme.com") r_output = textwrap.dedent("""\ Name Versions Product Note ================================================================================ another_package 2.0.0-1 commercial not subscribed to dummy 0.9.8-1 commercial {0} 1.0.1-1 commercial {0} Note: some of those packages are not available at your current subscription level ('Canopy / EPD Free'). """.format("")) another_entry = dummy_repository_package_factory( "another_package", "2.0.0", 1) another_entry.available = False entries = [ dummy_repository_package_factory("dummy", "1.0.1", 1), dummy_repository_package_factory("dummy", "0.9.8", 1), another_entry ] with Session.from_configuration(config) as session: with mkdtemp() as d: with mock_print() as m: enpkg = create_prefix_with_eggs(config, d, remote_entries=entries) search(enpkg._remote_repository, enpkg._installed_repository, config, session) self.assertMultiLineEqual(m.value, r_output)
def setUp(self): self.d = tempfile.mkdtemp() self.f = os.path.join(self.d, "enstaller4rc") self.session = Session(DummyAuthenticator(), self.d)
def main(argv=None): if argv is None: # pragma: no cover argv = sys.argv[1:] parser, args = _preprocess_options(argv) pat = None if (args.list or args.search) and args.cnames: pat = re.compile(args.cnames[0], re.I) if args.config_path: config_filename = os.path.expanduser(args.config_path) try: config = Configuration.from_yaml_filename(config_filename) except IOError: msg = "Error: File {0!r} could not be read".format(config_filename) print(msg) sys.exit(-1) else: if config.auth is None: print("Authentication missing from {0!r}".format(config_filename)) sys.exit(-1) use_new_format = True else: config = _ensure_config_or_die() config_filename = config.filename use_new_format = False setup_proxy_or_die(config, args.proxy) prefix, prefixes = _compute_prefixes(args, config) config.update(prefix=prefix) if args.user: try: check_prefixes(prefixes) except InvalidPythonPathConfiguration: msg = "Using the --user option, but your PYTHONPATH is not " \ "setup accordingly" warnings.warn(msg) exit_if_root_on_non_owned(args.yes) logger.info("prefixes") for prefix in prefixes: logger.info(' %s%s', prefix, ['', ' (sys)'][prefix == sys.prefix]) if hasattr(args, "insecure"): config.update(verify_ssl=not args.insecure) if hasattr(args, "max_retries"): config.update(max_retries=args.max_retries) with Session.from_configuration(config) as session: if dispatch_commands_without_enpkg(args, config, config_filename, prefixes, prefix, pat, session): return if config.auth is None: configure_authentication_or_exit(config, config_filename, session) ensure_authenticated_config(config, config_filename, session, use_new_format=use_new_format) repository = repository_factory(session, config.repositories, args.quiet) if args.quiet: progress_bar_context = None else: def fetch_progress_factory(*a, **kw): return console_progress_manager_factory(*a, show_speed=True, **kw) progress_bar_context = ProgressBarContext( console_progress_manager_factory, fetch=fetch_progress_factory) enpkg = Enpkg(repository, session, prefixes, progress_bar_context, args.force or args.forceall, max_retries=config.max_retries) dispatch_commands_with_enpkg(args, enpkg, config, prefix, session, parser, pat)