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_simple_scenario(self): egg = DUMMY_EGG r_actions = {1: [], 0: [("remove", os.path.basename(egg))]} config = Configuration() repository = Repository() package = RepositoryPackageMetadata.from_egg(egg) package.python = PY_VER repository.add_package(package) with open(egg, "rb") as fp: responses.add(responses.GET, package.source_url, body=fp.read(), status=200, content_type='application/json') session = Session(DummyAuthenticator(), config.repository_cache) enpkg = Enpkg(repository, session, prefixes=self.prefixes) actions = [("fetch", os.path.basename(egg)), ("install", os.path.basename(egg))] enpkg.execute(actions) name, version = egg_name_to_name_version(egg) enpkg._installed_repository.find_package(name, version) for state in [0, 1]: actions = enpkg.revert_actions(state) self.assertEqual(actions, r_actions[state])
def test_abort(self): """Ensure calling abort does abort the current set of executed actions.""" sentinel = [] def fake_install(*args): time.sleep(5) sentinel.append("oui oui") entries = [ dummy_repository_package_factory("numpy", "1.6.1", 1), dummy_repository_package_factory("numpy", "1.8.0", 2), ] repository = repository_factory(entries) with mock.patch("enstaller.enpkg.FetchAction.execute"): with mock.patch("enstaller.enpkg.InstallAction.execute", fake_install): enpkg = Enpkg(repository, mock.Mock()) actions = enpkg._solver.install_actions("numpy") t = threading.Thread(target=lambda: enpkg.execute(actions)) t.start() enpkg.abort_execution() t.join(timeout=10) self.assertEqual(sentinel, [])
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_revert_missing_unavailable_egg(self): egg = "non_existing_dummy_egg-1.0.0-1.egg" enpkg = Enpkg(Repository(), mocked_session_factory(Configuration().repository_cache), prefixes=self.prefixes) with self.assertRaises(EnpkgError): enpkg.revert_actions(set([egg]))
def test_query_simple_with_local(self): """ Ensure enpkg.query finds both local and remote eggs. """ local_egg = DUMMY_EGG entries = [ dummy_enpkg_entry_factory("dummy", "1.6.1", 1), dummy_enpkg_entry_factory("dummy", "1.8k", 2), ] repo = MetadataOnlyStore(entries) repo.connect() local_entry = EnpkgS3IndexEntry.from_egg(DUMMY_EGG) with mkdtemp() as d: enpkg = Enpkg(repo, prefixes=[d], hook=None, evt_mgr=None, verbose=False, config=Configuration()) enpkg = Enpkg(repo, prefixes=[d], hook=None, evt_mgr=None, verbose=False, config=Configuration()) enpkg.ec.install(os.path.basename(local_egg), os.path.dirname(local_egg)) r = dict(enpkg.query(name="dummy")) self.assertEqual(set(r.keys()), set(entry.s3index_key for entry in entries + [local_entry]))
def test_simple_install(self): egg = DUMMY_EGG base_egg = os.path.basename(egg) fetch_opcode = 0 entries = [ EnpkgS3IndexEntry(product="free", build=1, egg_basename="dummy", version="1.0.1", available=True), ] repo = MetadataOnlyStore(entries) repo.connect() with mock.patch("enstaller.enpkg.Enpkg.fetch") as mocked_fetch: enpkg = Enpkg(repo, prefixes=self.prefixes, hook=None, evt_mgr=None, verbose=False, config=Configuration()) local_repo = JoinedEggCollection([ EggCollection(prefix, False, None) for prefix in self.prefixes]) local_repo.install = mock.MagicMock() enpkg.ec = local_repo actions = enpkg.install_actions("dummy") enpkg.execute(actions) mocked_fetch.assert_called_with(base_egg, force=fetch_opcode) local_repo.install.assert_called_with(base_egg, enpkg.local_dir, None)
def test_invalid_argument(self): repository = Repository() enpkg = Enpkg(repository, mocked_session_factory(Configuration().repository_cache), prefixes=self.prefixes) with self.assertRaises(EnpkgError): enpkg.revert_actions([])
def test_empty_history(self): repo = EggsStore([]) repo.connect() enpkg = Enpkg(repo, prefixes=self.prefixes, hook=None, evt_mgr=None, verbose=False, config=Configuration()) enpkg.revert_actions(0) with self.assertRaises(EnpkgError): enpkg.revert_actions(1)
def test_remove_non_existing(self): entries = [ dummy_enpkg_entry_factory("numpy", "1.6.1", 1), dummy_enpkg_entry_factory("numpy", "1.8.0", 2), ] repo = MetadataOnlyStore(entries) repo.connect() with mkdtemp() as d: enpkg = Enpkg(repo, prefixes=[d], hook=None, evt_mgr=None, verbose=False, config=Configuration()) with self.assertRaises(EnpkgError): enpkg.remove_actions("numpy")
def _create_prefix_with_eggs(config, prefix, installed_entries=None, remote_entries=None): if remote_entries is None: remote_entries = [] if installed_entries is None: installed_entries = [] repo = MetadataOnlyStore(remote_entries) repo.connect() enpkg = Enpkg(repo, prefixes=[prefix], hook=None, evt_mgr=None, verbose=False, config=config) enpkg.ec = JoinedEggCollection([ MetaOnlyEggCollection(installed_entries)]) return enpkg
def test_query_simple(self): entries = [ dummy_enpkg_entry_factory("numpy", "1.6.1", 1), dummy_enpkg_entry_factory("numpy", "1.8k", 2), ] repo = MetadataOnlyStore(entries) repo.connect() with mkdtemp() as d: enpkg = Enpkg(repo, prefixes=[d], hook=None, evt_mgr=None, verbose=False, config=Configuration()) r = dict(enpkg.query(name="numpy")) self.assertEqual(set(r.keys()), set(entry.s3index_key for entry in entries))
def test_simple_fetch(self): egg = "yoyo.egg" fetch_opcode = 0 repo = MetadataOnlyStore([]) repo.connect() with mock.patch("enstaller.enpkg.Enpkg.fetch") as mocked_fetch: enpkg = Enpkg(repo, prefixes=self.prefixes, hook=None, evt_mgr=None, verbose=False, config=Configuration()) enpkg.ec = mock.MagicMock() enpkg.execute([("fetch_{0}".format(fetch_opcode), egg)]) self.assertTrue(mocked_fetch.called) mocked_fetch.assert_called_with(egg, force=fetch_opcode)
def test_info_list_names_invalid_version(self): entries = [ dummy_enpkg_entry_factory("numpy", "1.6.1", 1), dummy_enpkg_entry_factory("numpy", "1.8k", 2), ] repo = MetadataOnlyStore(entries) repo.connect() with mkdtemp() as d: enpkg = Enpkg(repo, prefixes=[d], hook=None, evt_mgr=None, verbose=False, config=Configuration()) queried_entries = enpkg.info_list_name("numpy") self.assertEqual(len(queried_entries), 2) self.assertEqual([q["version"] for q in queried_entries], ["1.6.1", "1.8k"])
def test_simple_install(self): config = Configuration() entries = [ dummy_repository_package_factory("dummy", "1.0.1", 1) ] repository = repository_factory(entries) with mock.patch("enstaller.enpkg.FetchAction.execute") as mocked_fetch: with mock.patch("enstaller.enpkg.InstallAction.execute") as mocked_install: enpkg = Enpkg(repository, mocked_session_factory(config.repository_cache), prefixes=self.prefixes) actions = [("install", "dummy-1.0.1-1.egg")] enpkg.execute(actions) mocked_fetch.assert_called() mocked_install.assert_called_with()
def test_remove(self): repo = MetadataOnlyStore([]) repo.connect() with mkdtemp() as d: makedirs(d) for egg in [DUMMY_EGG]: egginst = EggInst(egg, d) egginst.install() local_repo = JoinedEggCollection([EggCollection(d, False, None)]) enpkg = Enpkg(repo, prefixes=[d], hook=None, evt_mgr=None, verbose=False, config=Configuration()) enpkg.ec = local_repo self.assertTrue(local_repo.find(os.path.basename(DUMMY_EGG))) actions = enpkg.remove_actions("dummy") self.assertEqual(actions, [("remove", os.path.basename(DUMMY_EGG))])
def test_install_simple(self): entries = [ dummy_enpkg_entry_factory("numpy", "1.6.1", 1), dummy_enpkg_entry_factory("numpy", "1.8.0", 2), dummy_enpkg_entry_factory("numpy", "1.7.1", 2), ] r_actions = [ ('fetch_0', 'numpy-1.8.0-2.egg'), ('install', 'numpy-1.8.0-2.egg') ] repo = MetadataOnlyStore(entries) repo.connect() with mkdtemp() as d: enpkg = Enpkg(repo, prefixes=[d], hook=None, evt_mgr=None, verbose=False, config=Configuration()) actions = enpkg.install_actions("numpy") self.assertEqual(actions, r_actions)
def unconnected_enpkg_factory(prefixes=None): """ Create an Enpkg instance which does not require an authenticated repository. """ if prefixes is None: prefixes = [sys.prefix] config = Configuration() repository = Repository() return Enpkg(repository, mocked_session_factory(config.repository_cache), prefixes=prefixes)
def test_chained_override_update(self): """ Test update to package with latest version in lower prefix but an older version in primary prefix. """ l0_egg = NOSE_1_3_0 l1_egg = NOSE_1_2_1 expected_actions = [ ('fetch_0', os.path.basename(l0_egg)), ('remove', os.path.basename(l1_egg)), ('install', os.path.basename(l0_egg)), ] entries = [ dummy_enpkg_entry_factory(*split_eggname(os.path.basename(l0_egg))), ] repo = MetadataOnlyStore(entries) repo.connect() with mkdtemp() as d: l0 = os.path.join(d, 'l0') l1 = os.path.join(d, 'l1') makedirs(l0) makedirs(l1) # Install latest version in l0 EggInst(l0_egg, l0).install() # Install older version in l1 EggInst(l1_egg, l1).install() local_repo = JoinedEggCollection([EggCollection(l1, False, None), EggCollection(l0, False, None)]) enpkg = Enpkg(repo, prefixes=[l1, l0], hook=None, evt_mgr=None, verbose=False, config=Configuration()) enpkg.ec = local_repo actions = enpkg.install_actions("nose") self.assertListEqual(actions, expected_actions)
def test_install_not_available(self): # Given config = Configuration() config.update(auth=FAKE_AUTH) nose = dummy_repository_package_factory("nose", "1.3.0", 1) nose.available = False repository = Repository() repository.add_package(nose) enpkg = Enpkg(repository, mocked_session_factory(config.repository_cache), [self.prefix]) enpkg.execute = mock.Mock() # When/Then with mock.patch("enstaller.config.subscription_message") as \ subscription_message: with self.assertRaises(SystemExit) as e: install_req(enpkg, config, "nose", FakeOptions()) subscription_message.assert_called() self.assertEqual(e.exception.code, 1)
def remove(): """ Remove the given requirement. Parameter is expected to be a JSON UTF8 encoded bytestring passed through stdin. """ json_string = _read_stdin_as_bytes() config, requirement = install_parse_json_string(json_string) session = Session.authenticated_from_configuration(config) repository = repository_factory(session, config.repositories) progress_bar_context = ProgressBarContext(console_progress_manager_factory, fetch=fetch_progress_factory) enpkg = Enpkg(repository, session, [sys.prefix], progress_bar_context, False) solver = enpkg._solver_factory() try: request = Request() request.remove(requirement) enpkg.execute(solver.resolve(request)) except NotInstalledPackage as e: print(str(e))
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 create_prefix_with_eggs(config, prefix, installed_entries=None, remote_entries=None): if remote_entries is None: remote_entries = [] if installed_entries is None: installed_entries = [] repository = repository_factory(remote_entries) enpkg = Enpkg(repository, mocked_session_factory(config.repository_cache), prefixes=[prefix]) for package in installed_entries: package.store_location = prefix enpkg._top_installed_repository.add_package(package) enpkg._installed_repository.add_package(package) return enpkg
def test_simple_scenario(self): egg = DUMMY_EGG r_actions = {1: [], 0: [("remove", os.path.basename(egg))]} repo = EggsStore([egg]) repo.connect() enpkg = Enpkg(repo, prefixes=self.prefixes, hook=None, evt_mgr=None, verbose=False, config=Configuration()) actions = enpkg.install_actions("dummy") enpkg.execute(actions) self.assertIsNotNone(enpkg.find(os.path.basename(egg))) for state in [0, 1]: actions = enpkg.revert_actions(state) self.assertEqual(actions, r_actions[state])
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 = 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) 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_sudo_on_venv(prefix) 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.indices, 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)
def main(): try: user_base = site.USER_BASE except AttributeError: user_base = abs_expanduser('~/.local') p = ArgumentParser(description=__doc__) p.add_argument('cnames', metavar='NAME', nargs='*', help='package(s) to work on') p.add_argument("--add-url", metavar='URL', help="add a repository URL to the configuration file") p.add_argument("--config", action="store_true", help="display the configuration and exit") p.add_argument('-f', "--force", action="store_true", help="force install the main package " "(not its dependencies, see --forceall)") p.add_argument("--forceall", action="store_true", help="force install of all packages " "(i.e. including dependencies)") p.add_argument("--hook", action="store_true", help="don't install into site-packages (experimental)") p.add_argument("--imports", action="store_true", help="show which packages can be imported") p.add_argument('-i', "--info", action="store_true", help="show information about a package") p.add_argument("--log", action="store_true", help="print revision log") p.add_argument('-l', "--list", action="store_true", help="list the packages currently installed on the system") p.add_argument('-n', "--dry-run", action="store_true", help="show what would have been downloaded/removed/installed") p.add_argument('-N', "--no-deps", action="store_true", help="neither download nor install dependencies") p.add_argument("--env", action="store_true", help="based on the configuration, display how to set " "environment variables") p.add_argument("--prefix", metavar='PATH', help="install prefix (disregarding any settings in " "the config file)") p.add_argument("--proxy", metavar='PROXYSTR', help="use a proxy for downloads." " <proxy protocol>://[<proxy username>" "[:<proxy password>@]]<proxy server>:<proxy port>") p.add_argument("--remove", action="store_true", help="remove a package") p.add_argument("--remove-enstaller", action="store_true", help="remove enstaller (will break enpkg)") p.add_argument("--revert", metavar="REV#", help="revert to a previous set of packages (does not revert " "enstaller itself)") p.add_argument('-s', "--search", action="store_true", help="search the online repo index " "and display versions available") p.add_argument("--sys-config", action="store_true", help="use <sys.prefix>/.enstaller4rc (even when " "~/.enstaller4rc exists)") p.add_argument("--sys-prefix", action="store_true", help="use sys.prefix as the install prefix") p.add_argument("--update-all", action="store_true", help="update all installed packages") p.add_argument("--user", action="store_true", help="install into user prefix, i.e. --prefix=%r" % user_base) p.add_argument("--userpass", action="store_true", help="prompt for Enthought authentication, and save in " "configuration file .enstaller4rc") p.add_argument('-v', "--verbose", action="store_true") p.add_argument('--version', action="version", version='enstaller version: ' + __version__) p.add_argument("--whats-new", action="store_true", help="display available updates for installed packages") args = p.parse_args() # Check for incompatible actions and options # Action options which take no package name pattern: simple_standalone_actions = (args.config, args.env, args.userpass, args.revert, args.log, args.whats_new, args.update_all, args.remove_enstaller, args.add_url) # Action options which can take a package name pattern: complex_standalone_actions = (args.list, args.imports, args.search, args.info, args.remove) count_simple_actions = sum(bool(opt) for opt in simple_standalone_actions) count_complex_actions = sum(bool(opt) for opt in complex_standalone_actions) if count_simple_actions + count_complex_actions > 1: p.error('Multiple action options specified') if count_simple_actions > 0 and len(args.cnames) > 0: p.error("Option takes no arguments") if args.user: args.prefix = user_base if args.prefix and args.sys_prefix: p.error("Options --prefix and --sys-prefix exclude each other") if args.force and args.forceall: p.error("Options --force and --forceall exclude each other") pat = None if (args.list or args.search) and args.cnames: pat = re.compile(args.cnames[0], re.I) # make prefix if args.sys_prefix: prefix = sys.prefix elif args.prefix: prefix = args.prefix else: prefix = config.get('prefix', sys.prefix) # now make prefixes if prefix == sys.prefix: prefixes = [sys.prefix] else: prefixes = [prefix, sys.prefix] exit_if_sudo_on_venv(prefix) if args.verbose: print "Prefixes:" for prefix in prefixes: print ' %s%s' % (prefix, ['', ' (sys)'][prefix == sys.prefix]) print if args.env: # --env env_option(prefixes) return if args.log: # --log if args.hook: raise NotImplementedError from history import History h = History(prefix) h.update() h.print_log() return if args.sys_config: # --sys-config config.get_path = lambda: config.system_config_path if args.list: # --list list_option(prefixes, args.hook, pat) return if args.proxy: # --proxy setup_proxy(args.proxy) elif config.get('proxy'): setup_proxy(config.get('proxy')) else: setup_proxy() if 0: # for testing event manager only from encore.events.api import EventManager from encore.terminal.api import ProgressDisplay evt_mgr = EventManager() display = ProgressDisplay(evt_mgr) else: evt_mgr = None if config.get('use_webservice'): remote = None # Enpkg will create the default else: urls = [fill_url(u) for u in config.get('IndexedRepos')] remote = create_joined_store(urls) enpkg = Enpkg(remote, prefixes=prefixes, hook=args.hook, evt_mgr=evt_mgr, verbose=args.verbose) if args.config: # --config config.print_config(enpkg.remote, prefixes[0]) return if args.userpass: # --userpass username, password = config.input_auth() config.checked_change_auth(username, password, enpkg.remote) return if args.dry_run: def print_actions(actions): for item in actions: print '%-8s %s' % item enpkg.execute = print_actions if args.imports: # --imports assert not args.hook imports_option(enpkg, pat) return if args.add_url: # --add-url add_url(args.add_url, args.verbose) return if args.revert: # --revert if isfile(args.revert): arg = parse_list(args.revert) else: arg = args.revert try: actions = enpkg.revert_actions(arg) if not actions: print "Nothing to do" return enpkg.execute(actions) except EnpkgError as e: print e.message return # Try to auto-update enstaller if update_enstaller(enpkg, args): print "Enstaller has been updated.", \ "Please re-run your previous command." return if args.search: # --search search(enpkg, pat) return if args.info: # --info if len(args.cnames) != 1: p.error("Option requires one argument (name of package)") info_option(enpkg, args.cnames[0]) return if args.whats_new: # --whats-new whats_new(enpkg) return if args.update_all: # --update-all update_all(enpkg, args) return if len(args.cnames) == 0 and not args.remove_enstaller: p.error("Requirement(s) missing") elif len(args.cnames) == 2: pat = re.compile(r'\d+\.\d+') if pat.match(args.cnames[1]): args.cnames = ['-'.join(args.cnames)] reqs = [] for arg in args.cnames: if '-' in arg: name, version = arg.split('-', 1) reqs.append(Req(name + ' ' + version)) else: reqs.append(Req(arg)) if args.verbose: print "Requirements:" for req in reqs: print ' %r' % req print print "prefix:", prefix REMOVE_ENSTALLER_WARNING = ("Removing enstaller package will break enpkg " "and is not recommended.") if args.remove: if any(req.name == 'enstaller' for req in reqs): print REMOVE_ENSTALLER_WARNING print "If you are sure you wish to remove enstaller, use:" print " enpkg --remove-enstaller" return if args.remove_enstaller: print REMOVE_ENSTALLER_WARNING yn = raw_input("Really remove enstaller? (y/[n]) ") if yn.lower() in set(['y', 'yes']): args.remove = True reqs = [Req('enstaller')] if any(req.name == 'epd' for req in reqs): if args.remove: p.error("Can't remove 'epd'") elif len(reqs) > 1: p.error("Can't combine 'enpkg epd' with other packages.") return elif not epd_install_confirm(): return for req in reqs: if args.remove: # --remove try: enpkg.execute(enpkg.remove_actions(req)) except EnpkgError as e: print e.message else: install_req(enpkg, req, args) # install (default)
def main(argv=None): if argv is None: argv = sys.argv[1:] try: user_base = site.USER_BASE except AttributeError: user_base = abs_expanduser('~/.local') p = ArgumentParser(description=__doc__) p.add_argument('cnames', metavar='NAME', nargs='*', help='package(s) to work on') p.add_argument("--add-url", metavar='URL', help="add a repository URL to the configuration file") p.add_argument("--config", action="store_true", help="display the configuration and exit") p.add_argument('-f', "--force", action="store_true", help="force install the main package " "(not its dependencies, see --forceall)") p.add_argument("--forceall", action="store_true", help="force install of all packages " "(i.e. including dependencies)") p.add_argument("--freeze", help=argparse.SUPPRESS, action="store_true") p.add_argument("--hook", action="store_true", help="don't install into site-packages (experimental)") p.add_argument("--imports", action="store_true", help="show which packages can be imported") p.add_argument('-i', "--info", action="store_true", help="show information about a package") p.add_argument("--log", action="store_true", help="print revision log") p.add_argument('-l', "--list", action="store_true", help="list the packages currently installed on the system") p.add_argument('-n', "--dry-run", action="store_true", help="show what would have been downloaded/removed/installed") p.add_argument('-N', "--no-deps", action="store_true", help="neither download nor install dependencies") p.add_argument("--env", action="store_true", help="based on the configuration, display how to set " "environment variables") p.add_argument("--prefix", metavar='PATH', help="install prefix (disregarding any settings in " "the config file)") p.add_argument("--proxy", metavar='PROXYSTR', help="use a proxy for downloads." " <proxy protocol>://[<proxy username>" "[:<proxy password>@]]<proxy server>:<proxy port>") p.add_argument("--remove", action="store_true", help="remove a package") p.add_argument("--remove-enstaller", action="store_true", help="remove enstaller (will break enpkg)") p.add_argument("--requirements", help=argparse.SUPPRESS) p.add_argument("--revert", metavar="REV#", help="revert to a previous set of packages (does not revert " "enstaller itself)") p.add_argument('-s', "--search", action="store_true", help="search the online repo index " "and display versions available") p.add_argument("--sys-config", action="store_true", help="use <sys.prefix>/.enstaller4rc (even when " "~/.enstaller4rc exists)") p.add_argument("--sys-prefix", action="store_true", help="use sys.prefix as the install prefix") p.add_argument("--update-all", action="store_true", help="update all installed packages") p.add_argument("--user", action="store_true", help="install into user prefix, i.e. --prefix=%r" % user_base) p.add_argument("--userpass", action="store_true", help="prompt for Enthought authentication, and save in " "configuration file .enstaller4rc") p.add_argument('-v', "--verbose", action="store_true") p.add_argument('--version', action="version", version='enstaller version: ' + __version__) p.add_argument("--whats-new", action="store_true", help="display available updates for installed packages") args = p.parse_args(argv) config_filename = get_config_filename(args.sys_config) if not os.path.isfile(config_filename): write_default_config(config_filename) config = Configuration.from_file(config_filename) # Check for incompatible actions and options # Action options which take no package name pattern: simple_standalone_actions = (args.config, args.env, args.userpass, args.revert, args.log, args.whats_new, args.update_all, args.remove_enstaller, args.add_url, args.freeze, args.requirements) # Action options which can take a package name pattern: complex_standalone_actions = (args.list, args.imports, args.search, args.info, args.remove) count_simple_actions = sum(bool(opt) for opt in simple_standalone_actions) count_complex_actions = sum(bool(opt) for opt in complex_standalone_actions) if count_simple_actions + count_complex_actions > 1: p.error('Multiple action options specified') if count_simple_actions > 0 and len(args.cnames) > 0: p.error("Option takes no arguments") if args.user: args.prefix = user_base if args.prefix and args.sys_prefix: p.error("Options --prefix and --sys-prefix exclude each other") if args.force and args.forceall: p.error("Options --force and --forceall exclude each other") pat = None if (args.list or args.search) and args.cnames: pat = re.compile(args.cnames[0], re.I) # make prefix if args.sys_prefix: prefix = sys.prefix elif args.prefix: prefix = args.prefix else: prefix = config.prefix # now make prefixes if prefix == sys.prefix: prefixes = [sys.prefix] else: prefixes = [prefix, sys.prefix] if args.user: try: check_prefixes(prefixes) except InvalidPythonPathConfiguration: warnings.warn("Using the --user option, but your PYTHONPATH is not setup " \ "accordingly") exit_if_sudo_on_venv(prefix) if args.verbose: print("Prefixes:") for prefix in prefixes: print(' %s%s' % (prefix, ['', ' (sys)'][prefix == sys.prefix])) print() if args.env: # --env env_option(prefixes) return if args.log: # --log if args.hook: raise NotImplementedError from history import History h = History(prefix) h.update() h.print_log() return if args.freeze: from .eggcollect import EggCollection, JoinedEggCollection collection = JoinedEggCollection( [EggCollection(prefix, False, None) for prefix in prefixes] ) full_names = [ "{0} {1}-{2}".format(req["name"], req["version"], req["build"]) for name, req in collection.query(type="egg") ] for full_name in sorted(full_names): print(full_name) return if args.list: # --list list_option(prefixes, args.hook, pat) return if args.proxy: # --proxy setup_proxy(args.proxy) elif config.proxy: setup_proxy(config.proxy) else: setup_proxy() evt_mgr = None if config.use_webservice: remote = None # Enpkg will create the default else: urls = [fill_url(u) for u in config.IndexedRepos] remote = create_joined_store(config, urls) enpkg = Enpkg(remote, prefixes=prefixes, hook=args.hook, evt_mgr=evt_mgr, verbose=args.verbose, config=config) if args.config: # --config print_config(config, enpkg.remote, prefixes[0]) return if args.add_url: # --add-url add_url(config_filename, enpkg.config, args.add_url, args.verbose) return if args.userpass: # --userpass n_trials = 3 for i in range(n_trials): username, password = input_auth() if username: break else: print("Please enter a non empty username ({0} trial(s) left)". \ format(n_trials - i - 1)) else: print("No valid username entered (no modification was written).") sys.exit(-1) config.set_auth(username, password) try: config._checked_change_auth(config_filename) except AuthFailedError as e: msg = ("Could not authenticate. Please check your credentials " "and try again.\nNo modification was written.") print(msg) sys.exit(-1) return if not config.is_auth_configured: print(PLEASE_AUTH_MESSAGE) sys.exit(-1) try: config.get_auth() except InvalidConfiguration: print(PLEASE_AUTH_MESSAGE) sys.exit(-1) else: try: authenticate(config, enpkg.remote) except AuthFailedError as e: login, _ = config.get_auth() print("Could not authenticate with user '{0}'.".format(login)) print("You can change your authentication details with 'enpkg --userpass'") sys.exit(-1) if args.dry_run: def print_actions(actions): for item in actions: print('%-8s %s' % item) enpkg.execute = print_actions if args.imports: # --imports assert not args.hook imports_option(enpkg, pat) return if args.revert: # --revert if isfile(args.revert): arg = parse_list(args.revert) else: arg = args.revert try: actions = enpkg.revert_actions(arg) if not actions: print("Nothing to do") return enpkg.execute(actions) except EnpkgError as e: print(e.message) return # Try to auto-update enstaller if update_enstaller(enpkg, args): print("Enstaller has been updated.\n" "Please re-run your previous command.") return if args.search: # --search search(enpkg, pat) return if args.info: # --info if len(args.cnames) != 1: p.error("Option requires one argument (name of package)") info_option(enpkg, args.cnames[0]) return if args.whats_new: # --whats-new whats_new(enpkg) return if args.update_all: # --update-all update_all(enpkg, args) return if args.requirements: with open(args.requirements, "r") as fp: for req in fp: args.no_deps = True install_req(enpkg, req, args) return if len(args.cnames) == 0 and not args.remove_enstaller: p.error("Requirement(s) missing") elif len(args.cnames) == 2: pat = re.compile(r'\d+\.\d+') if pat.match(args.cnames[1]): args.cnames = ['-'.join(args.cnames)] reqs = [] for arg in args.cnames: if '-' in arg: name, version = arg.split('-', 1) reqs.append(Req(name + ' ' + version)) else: reqs.append(Req(arg)) # This code assumes we have already upgraded enstaller if needed if needs_to_downgrade_enstaller(enpkg, reqs): warnings.warn("Enstaller in requirement list: enstaller will be downgraded !") else: print("Enstaller is already up to date, not upgrading.") reqs = [req for req in reqs if req.name != "enstaller"] if args.verbose: print("Requirements:") for req in reqs: print(' %r' % req) print() print("prefix:", prefix) REMOVE_ENSTALLER_WARNING = ("Removing enstaller package will break enpkg " "and is not recommended.") if args.remove: if any(req.name == 'enstaller' for req in reqs): print(REMOVE_ENSTALLER_WARNING) print("If you are sure you wish to remove enstaller, use:") print(" enpkg --remove-enstaller") return if args.remove_enstaller: print(REMOVE_ENSTALLER_WARNING) yn = raw_input("Really remove enstaller? (y/[n]) ") if yn.lower() in set(['y', 'yes']): args.remove = True reqs = [Req('enstaller')] if any(req.name == 'epd' for req in reqs): if args.remove: p.error("Can't remove 'epd'") elif len(reqs) > 1: p.error("Can't combine 'enpkg epd' with other packages.") return elif not epd_install_confirm(): return for req in reqs: if args.remove: # --remove try: enpkg.execute(enpkg.remove_actions(req)) except EnpkgError as e: print(e.message) else: install_req(enpkg, req, args) # install (default)