def _user_private_packages_ready(self, worker, output, error): if error: logger.error(error) else: logger.debug('') packages = worker.packages apps = worker.apps worker = self.api.pip_list(prefix=self.prefix) worker.sig_finished.connect(self._pip_list_ready) worker.packages = packages worker.apps = apps # private_packages = {} # if output: # all_private_packages = output # for item in all_private_packages: # name = item.get('name', '') # public = item.get('public', True) # package_types = item.get('package_types', []) # latest_version = item.get('latest_version', '') # if name and not public and 'conda' in package_types: # private_packages[name] = {'versions': item.get('versions', []), # 'app_entry': {}, # 'type': {}, # 'size': {}, # 'latest_version': latest_version, # } worker.private_packages = output
def _setup_packages(self, worker, data, error): """ """ if error: logger.error(error) else: logger.debug('') combobox_index = self.combobox_filter.currentIndex() status = C.PACKAGE_STATUS[combobox_index] packages = worker.packages # Remove blacklisted packages for package in self.package_blacklist: if package in packages: packages.pop(package) for i, row in enumerate(data): if package == data[i][C.COL_NAME]: data.pop(i) self.table.setup_model(packages, data, self._metadata_links) self.combobox_filter.setCurrentIndex(combobox_index) self.filter_package(status) if self._current_model_index: self.table.setCurrentIndex(self._current_model_index) self.table.verticalScrollBar().setValue(self._current_table_scroll) if error: self.update_status(error, False) self.sig_packages_ready.emit() self.table.setFocus()
def multi_packages(self, logins=None, platform=None, package_type=None, type_=None, access=None): """ Get all the private packages for a given set of usernames (logins) """ logger.debug('') method = self._multi_packages new_client = True try: # Only the newer versions have extra keywords like `access` self._anaconda_client_api.user_packages(access='private') except Exception: new_client = False return self._create_worker(method, logins=logins, platform=platform, package_type=package_type, type_=type_, access=access, new_client=new_client)
def remove(self, name=None, prefix=None, pkgs=None, all_=False): """ Remove a package (from an environment) by name. Returns { success: bool, (this is always true), (other information) } """ logger.debug(str((prefix, pkgs))) cmd_list = ['remove', '--json', '--quiet', '--yes'] if not pkgs and not all_: raise TypeError("Must specify at least one package to remove, or " "all=True.") if name: cmd_list.extend(['--name', name]) elif prefix: cmd_list.extend(['--prefix', prefix]) else: raise TypeError('must specify either an environment name or a ' 'path for package removal') if all_: cmd_list.extend(['--all']) else: cmd_list.extend(pkgs) return self._call_and_parse(cmd_list)
def logout(self): """ Logout from anaconda cloud. """ logger.debug('Logout') method = self._anaconda_client_api.remove_authentication return self._create_worker(method)
def download(self, url, path): """Download url and save data to path.""" # original_url = url # print(url) qurl = QUrl(url) url = to_text_string(qurl.toEncoded(), encoding='utf-8') logger.debug(str((url, path))) if url in self._workers: while not self._workers[url].finished: return self._workers[url] worker = DownloadWorker(url, path) # Check download folder exists folder = os.path.dirname(os.path.abspath(path)) if not os.path.isdir(folder): os.makedirs(folder) request = QNetworkRequest(qurl) self._head_requests[url] = request self._paths[url] = path self._workers[url] = worker self._manager.head(request) self._timer.start() return worker
def is_valid_api_url(self, url, non_blocking=True): logger.debug(str((url))) if non_blocking: method = self._is_valid_api_url return self._create_worker(method, url) else: return self._is_valid_api_url(url=url)
def start(self): """ Start the worker process. """ error, output = None, None try: time.sleep(0.1) output = self.method(*self.args, **self.kwargs) except Exception as err: logger.debug( str((self.method.__module__, self.method.__name__, err))) error = str(err) error = error.replace('(', '') error = error.replace(')', '') # try: # error = err[0] # except Exception: # try: # error = err.message # except Exception as err2: # error = '' self.sig_finished.emit(self, output, str(error)) self._is_finished = True
def prepare_model_data(self, packages, linked, pip=[], private_packages={}): """ """ logger.debug('') return self._prepare_model_data(packages, linked, pip=pip, private_packages=private_packages)
def packages(self, login=None, platform=None, package_type=None, type_=None, access=None): """ :param type_: only find packages that have this conda `type` (i.e. 'app') :param access: only find packages that have this access level (e.g. 'private', 'authenticated', 'public') """ # data = self._anaconda_client_api.user_packages( # login=login, # platform=platform, # package_type=package_type, # type_=type_, # access=access) logger.debug('') method = self._anaconda_client_api.user_packages return self._create_worker(method, login=login, platform=platform, package_type=package_type, type_=type_, access=access)
def login(self, username, password, application, application_url): """ Login to anaconda cloud. """ logger.debug(str((username, application, application_url))) method = self._anaconda_client_api.authenticate return self._create_worker(method, username, password, application, application_url)
def info(self, abspath=True): """ Return a dictionary with configuration information. No guarantee is made about which keys exist. Therefore this function should only be used for testing and debugging. """ logger.debug(str('')) return self._call_and_parse(['info', '--json'], abspath=abspath)
def is_valid_api_url(self, url, non_blocking=True): """Check if anaconda api url is valid.""" logger.debug(str((url))) if non_blocking: method = self._is_valid_api_url return self._create_worker(method, url) else: return self._is_valid_api_url(url=url)
def is_valid_channel(self, channel, conda_url='https://conda.anaconda.org', non_blocking=True): logger.debug(str((channel, conda_url))) if non_blocking: method = self._is_valid_channel return self._create_worker(method, channel, conda_url) else: return self._is_valid_channel(channel, conda_url=conda_url)
def start(self): """Start process.""" logger.debug(str(' '.join(self._cmd_list))) if not self._fired: self._partial_ouput = None self._process.start(self._cmd_list[0], self._cmd_list[1:]) self._timer.start() else: raise CondaProcessWorker('A Conda ProcessWorker can only run once ' 'per method call.')
def load_repodata(self, filepaths, extra_data={}, metadata={}): """ Load all the available pacakges information for downloaded repodata files (repo.continuum.io), additional data provided (anaconda cloud), and additional metadata and merge into a single set of packages and apps. """ logger.debug(str((filepaths))) method = self._load_repodata return self._create_worker(method, filepaths, extra_data=extra_data, metadata=metadata)
def set_domain(self, domain='https://api.anaconda.org'): """Reset current api domain.""" logger.debug(str((domain))) config = binstar_client.utils.get_config() config['url'] = domain binstar_client.utils.set_config(config) self._anaconda_client_api = binstar_client.utils.get_server_api( token=None, log_level=logging.NOTSET) return self.user()
def pip_remove(self, name=None, prefix=None, pkgs=None): """Remove a pip package in given environment by `name` or `prefix`.""" logger.debug(str((prefix, pkgs))) if isinstance(pkgs, (list, tuple)): pkg = ' '.join(pkgs) else: pkg = pkgs extra_args = ['uninstall', '--yes', pkg] return self._call_pip(name=name, prefix=prefix, extra_args=extra_args)
def update_channels(self, channels, active_channels): """ """ logger.debug(str((channels, active_channels))) if sorted(self._active_channels) != sorted(active_channels) or \ sorted(self._channels) != sorted(channels): self._channels = channels self._active_channels = active_channels self.sig_channels_updated.emit(tuple(channels), tuple(active_channels)) self.setup(check_updates=True)
def load_repodata(self, filepaths, extra_data=None, metadata=None): """ Load all the available pacakges information for downloaded repodata. Files include repo.continuum.io, additional data provided (anaconda cloud), and additional metadata and merge into a single set of packages and apps. """ logger.debug(str((filepaths))) method = self._load_repodata return self._create_worker(method, filepaths, extra_data=extra_data, metadata=metadata)
def set_environment(self, name=None, prefix=None): """ This does not update the package manager! """ logger.debug(str((name, prefix))) if prefix and self.api.conda_environment_exists(prefix=prefix): self.prefix = prefix elif name and self.api.conda_environment_exists(name=name): self.prefix = self.get_prefix_envname(name) else: self.prefix = self.root_prefix
def get_envs(self, log=True): """Return environment list of absolute path to their prefixes.""" if log: logger.debug('') # return self._call_and_parse(['info', '--json'], # callback=lambda o, e: o['envs']) envs = os.listdir(os.sep.join([self.ROOT_PREFIX, 'envs'])) envs = [os.sep.join([self.ROOT_PREFIX, 'envs', i]) for i in envs] valid_envs = [e for e in envs if os.path.isdir(e) and self.environment_exists(prefix=e)] return valid_envs
def linked(prefix): """Return set of canonical names of linked packages in `prefix`.""" logger.debug(str(prefix)) if not isdir(prefix): return set() meta_dir = join(prefix, 'conda-meta') if not isdir(meta_dir): # We might have nothing in linked (and no conda-meta directory) return set() return set(fn[:-5] for fn in os.listdir(meta_dir) if fn.endswith('.json'))
def install(self, name=None, prefix=None, pkgs=None, dep=True, channels=None, token=None): """ Install packages into an environment either by name or path with a specified set of packages. If token is specified, the channels different from the defaults will get the token appended. """ logger.debug(str((prefix, pkgs, channels))) # TODO: Fix temporal hack if not pkgs or not isinstance(pkgs, (list, tuple, str)): raise TypeError('must specify a list of one or more packages to ' 'install into existing environment') cmd_list = ['install', '--yes', '--json', '--force-pscheck'] if name: cmd_list.extend(['--name', name]) elif prefix: cmd_list.extend(['--prefix', prefix]) else: # Just install into the current environment, whatever that is pass # TODO: Check if correct if channels: cmd_list.extend(['--override-channels']) for channel in channels: cmd_list.extend(['--channel']) channel = self.parse_token_channel(channel, token) cmd_list.extend([channel]) # TODO: Fix temporal hack if isinstance(pkgs, (list, tuple)): cmd_list.extend(pkgs) elif isinstance(pkgs, str): cmd_list.extend(['--file', pkgs]) if not dep: cmd_list.extend(['--no-deps']) return self._call_and_parse(cmd_list)
def get_envs(self): """ Return all of the (named) environment (this does not include the root environment), as a list of absolute path to their prefixes. """ logger.debug('') # return self._call_and_parse(['info', '--json'], # callback=lambda o, e: o['envs']) envs = os.listdir(os.sep.join([self.ROOT_PREFIX, 'envs'])) envs = [os.sep.join([self.ROOT_PREFIX, 'envs', i]) for i in envs] valid_envs = [e for e in envs if os.path.isdir(e) and self.environment_exists(prefix=e)] return valid_envs
def _load_bundled_metadata(self): """ """ logger.debug('') parser = cp.ConfigParser() db_file = CondaPackagesWidget.DATABASE_FILE with open(osp.join(self.DATA_PATH, db_file)) as f: parser.readfp(f) for name in parser.sections(): metadata = {} for key, data in parser.items(name): metadata[key] = data self._metadata_links[name] = metadata
def start(self): """Start process worker for given method args and kwargs.""" error = None output = None try: output = self.method(*self.args, **self.kwargs) except Exception as err: error = err logger.debug(str((self.method.__name__, self.method.__module__, error))) self.sig_finished.emit(self, output, error) self._is_finished = True
def get_envs(self, log=True): """Return environment list of absolute path to their prefixes.""" if log: logger.debug('') # return self._call_and_parse(['info', '--json'], # callback=lambda o, e: o['envs']) envs = os.listdir(os.sep.join([self.ROOT_PREFIX, 'envs'])) envs = [os.sep.join([self.ROOT_PREFIX, 'envs', i]) for i in envs] valid_envs = [ e for e in envs if os.path.isdir(e) and self.environment_exists(prefix=e) ] return valid_envs
def linked(self, prefix): """ Return the (set of canonical names) of linked packages in `prefix`. """ logger.debug(str(prefix)) if not isdir(prefix): raise Exception('no such directory: {0}'.format(prefix)) meta_dir = join(prefix, 'conda-meta') if not isdir(meta_dir): # We might have nothing in linked (and no conda-meta directory) return set() return set(fn[:-5] for fn in os.listdir(meta_dir) if fn.endswith('.json'))
def create(self, name=None, prefix=None, pkgs=None, channels=None): """ Create an environment either by name or path with a specified set of packages. """ logger.debug(str((prefix, pkgs, channels))) # TODO: Fix temporal hack if not pkgs or not isinstance(pkgs, (list, tuple, str)): raise TypeError('must specify a list of one or more packages to ' 'install into new environment') cmd_list = ['create', '--yes', '--quiet', '--json', '--mkdir'] if name: ref = name search = [ os.path.join(d, name) for d in self.info().communicate()[0]['envs_dirs'] ] cmd_list.extend(['--name', name]) elif prefix: ref = prefix search = [prefix] cmd_list.extend(['--prefix', prefix]) else: raise TypeError('must specify either an environment name or a ' 'path for new environment') if any(os.path.exists(prefix) for prefix in search): raise CondaEnvExistsError('Conda environment {0} already ' 'exists'.format(ref)) # TODO: Fix temporal hack if isinstance(pkgs, (list, tuple)): cmd_list.extend(pkgs) elif isinstance(pkgs, str): cmd_list.extend(['--file', pkgs]) # TODO: Check if correct if channels: cmd_list.extend(['--override-channels']) for channel in channels: cmd_list.extend(['--channel']) cmd_list.extend([channel]) return self._call_and_parse(cmd_list)
def _prepare_model_data(self, worker=None, output=None, error=None): """ """ if error: logger.error(error) else: logger.debug('') packages, apps = output # worker = self.api.pip_list(prefix=self.prefix) # worker.sig_finished.connect(self._pip_list_ready) logins = self.get_logged_user_list_channels() worker = self.api.client_multi_packages(logins=logins, access='private') worker.sig_finished.connect(self._user_private_packages_ready) worker.packages = packages worker.apps = apps
def create_from_yaml(self, name, yamlfile): """ Create new environment using conda-env via a yaml specification file. Unlike other methods, this calls conda-env, and requires a named environment and uses channels as defined in rcfiles. Parameters ---------- name : string Environment name yamlfile : string Path to yaml file with package spec (as created by conda env export """ logger.debug(str((name, yamlfile))) cmd_list = ['env', 'create', '-n', name, '-f', yamlfile, '--json'] return self._call_and_parse(cmd_list)
def environment_exists(self, name=None, prefix=None, abspath=True): """ Check if an environment exists by 'name' or by 'prefix'. If query is by 'name' only the default conda environments directory is searched. """ logger.debug(str((name, prefix))) if name and prefix: raise TypeError("Exactly one of 'name' or 'prefix' is required.") if name: prefix = self.get_prefix_envname(name) if prefix is None: prefix = self.ROOT_PREFIX return os.path.isdir(os.path.join(prefix, 'conda-meta'))
def packages(self, login=None, platform=None, package_type=None, type_=None, access=None): """Return all the available packages for a given user. Parameters ---------- type_: Optional[str] Only find packages that have this conda `type`, (i.e. 'app'). access : Optional[str] Only find packages that have this access level (e.g. 'private', 'authenticated', 'public'). """ logger.debug('') method = self._anaconda_client_api.user_packages return self._create_worker(method, login=login, platform=platform, package_type=package_type, type_=type_, access=access)
def cancel_process(self): """ Allow user to cancel an ongoing process. """ logger.debug(str('process canceled by user.')) if self.busy: dlg = self.cancel_dialog() reply = dlg.exec_() if reply: self.update_status(hide=False, message='Process cancelled') self.api.conda_terminate() self.api.download_requests_terminate() self.api.conda_clear_lock() self.table.clear_actions() self.sig_process_cancelled.emit() else: QDialog.reject(self)
def create(self, name=None, prefix=None, pkgs=None, channels=None): """ Create an environment either by name or path with a specified set of packages. """ logger.debug(str((prefix, pkgs, channels))) # TODO: Fix temporal hack if not pkgs or not isinstance(pkgs, (list, tuple, str)): raise TypeError('must specify a list of one or more packages to ' 'install into new environment') cmd_list = ['create', '--yes', '--quiet', '--json', '--mkdir'] if name: ref = name search = [os.path.join(d, name) for d in self.info().communicate()[0]['envs_dirs']] cmd_list.extend(['--name', name]) elif prefix: ref = prefix search = [prefix] cmd_list.extend(['--prefix', prefix]) else: raise TypeError('must specify either an environment name or a ' 'path for new environment') if any(os.path.exists(prefix) for prefix in search): raise CondaEnvExistsError('Conda environment {0} already ' 'exists'.format(ref)) # TODO: Fix temporal hack if isinstance(pkgs, (list, tuple)): cmd_list.extend(pkgs) elif isinstance(pkgs, str): cmd_list.extend(['--file', pkgs]) # TODO: Check if correct if channels: cmd_list.extend(['--override-channels']) for channel in channels: cmd_list.extend(['--channel']) cmd_list.extend([channel]) return self._call_and_parse(cmd_list)
def _metadata_updated(self, worker, path, error): """ """ if error: logger.error(error) else: logger.debug('') if path and osp.isfile(path): with open(path, 'r') as f: data = f.read() try: self._metadata = json.loads(data) except Exception: self._metadata = {} else: self._metadata = {} self.api.update_repodata(self._channels)