def get_included_files(self, grpc_path='grpc://localhost:12321', recursive=True, include_args={}, include_pattern=[], search_in_ext=[]): ''' :param str grpc_path: the root path to search for included files :param bool recursive: True for recursive search :param include_args: dictionary with arguments to override while include. :type include_args: {str: str} :param include_pattern: the list with regular expression patterns to find include files. :type include_pattern: [str] :param search_in_ext: file extensions to search in :type search_in_ext: [str] :return: Returns an iterator for tuple with root path, line number, path of included file, file exists or not, file size and dictionary with defined arguments. :rtype: iterator (str, int, str, bool, int, {str: str}) ''' dorequest = False try: for entry in self._cache_file_includes[grpc_path]: do_return = True if not recursive and entry.rec_depth != 0: do_return = False if do_return: rospy.logdebug("get_included_files from cache: %s, include_args: %s" % (entry.inc_path, entry.args)) yield entry except KeyError: dorequest = True if dorequest: current_path = grpc_path try: uri, path = nmdurl.split(current_path) lm, channel = self.get_launch_manager(uri) rospy.logdebug("get_included_files for %s, recursive: %s, include_args: %s, pattern: %s, search_in_ext: %s" % (grpc_path, recursive, include_args, include_pattern, search_in_ext)) reply = lm.get_included_files(path, recursive, include_args, include_pattern, search_in_ext) url, _ = nmdurl.split(grpc_path, with_scheme=True) # initialize requested path in cache if recursive: if grpc_path not in self._cache_file_includes: self._cache_file_includes[grpc_path] = [] for inc_file in reply: entry = inc_file entry.path_or_str = nmdurl.join(url, inc_file.path_or_str) entry.inc_path = nmdurl.join(url, inc_file.inc_path) # initialize and add returned root path to cache, only on recursive if recursive: if current_path not in self._cache_file_includes: self._cache_file_includes[current_path] = [] self._cache_file_includes[current_path].append(entry) yield entry except grpc._channel._Rendezvous as grpc_error: self.clear_cache(grpc_path) self.clear_cache(current_path) if grpc_error.code() == grpc.StatusCode.DEADLINE_EXCEEDED: raise exceptions.GrpcTimeout(grpc_path, grpc_error) raise finally: self.close_channel(channel, uri)
def _get_mtimes_threaded(self, grpc_path='grpc://localhost:12321'): uri, path = nmdurl.split(grpc_path) rospy.logdebug("[thread] get mtimes from %s" % uri) try: lm, channel = self.get_launch_manager(uri) rpath, mtime, included_files = lm.get_mtimes(path) url, _ = nmdurl.split(grpc_path, with_scheme=True) self.mtimes.emit(nmdurl.join(url, rpath), mtime, {nmdurl.join(url, pobj.path): pobj.mtime for pobj in included_files}) except Exception: pass finally: self.close_channel(channel, uri) if hasattr(self, '_threads'): self._threads.finished("gmt_%s" % grpc_path)
def get_profile_file(self): ''' Opens file manager dialog to save to select a new file for node manager profile. :return: path to profile file :rtype: str ''' # save the profile (path, _) = QFileDialog.getSaveFileName( self, "New profile file", nm.settings().current_dialog_path, "node manager profile files (*.nmprofile);;All files (*)" ) # _:=filter if path: if not path.endswith('.nmprofile'): path = "%s.nmprofile" % path nm.settings().current_dialog_path = os.path.dirname(path) try: # we need a grpc url for local node manager daemon nmd_url = nmdurl.nmduri() (pkg, _) = package_name( nmdurl.join(nmd_url, os.path.dirname(path))) # _:=pkg_path if pkg is None: ret = MessageBox.warning( self, "New File Error", 'The new file is not in a ROS package', buttons=MessageBox.Ok | MessageBox.Cancel) if ret == MessageBox.Cancel: return None return path except EnvironmentError as e: MessageBox.warning(self, "New File Error", 'Error while create a new file', utf8(e)) return None
def add_new_item(self, name='new', path_id=PathItem.LAUNCH_FILE): ''' Inserts the given item in the list model. :param int path_id: the id (constants of PathItem) of the item, which represents whether it is a file, package or stack :param str name: the displayed name ''' root = self.invisibleRootItem() new_name = self._autorename(name) # add sorted a new entry try: path_item = PathItem.create_row_items(nmdurl.join( self._current_path, new_name), path_id, 0, 0, new_name, isnew=True) if root.rowCount() > 1: root.insertRow(1, path_item) else: root.appendRow(path_item) self.pyqt_workaround[path_item[0].name] = path_item[ 0] # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass return path_item except Exception: import traceback rospy.logwarn("Error while add new item: %s" % traceback.format_exc()) return []
def get_included_files_set(self, grpc_path='grpc://localhost:12321', recursive=True, include_pattern=[], search_in_ext=[]): ''' :param str root: the root path to search for included files :param bool recursive: True for recursive search :param include_pattern: the list with regular expression patterns to find include files. :type include_pattern: [str] :param search_in_ext: file extensions to search in :type search_in_ext: [str] :return: Returns a list of included files. :rtype: [str] ''' result = [] try: result = self._cache_file_unique_includes[grpc_path] except KeyError: rospy.logdebug("get_included_files_set for %s, recursive: %s" % (grpc_path, recursive)) uri, path = nmdurl.split(grpc_path, with_scheme=False) lm, channel = self.get_launch_manager(uri) url, path = nmdurl.split(grpc_path, with_scheme=True) reply = lm.get_included_files_set(path, recursive, {}, include_pattern, search_in_ext) for fname in reply: result.append(nmdurl.join(url, fname)) self._cache_file_unique_includes[grpc_path] = result self.close_channel(channel, uri) return result
def _list_packages(self, grpc_url_or_path='grpc://localhost:12321', clear_ros_cache=False): uri, path = nmdurl.split(grpc_url_or_path) grpc_url = "grpc://%s" % uri result = {} try: if not clear_ros_cache: result = self._cache_packages[grpc_url] else: self._cache_packages[''] # only to cause an exception except KeyError: rospy.logdebug("[thread] get packages %s" % grpc_url) fm, channel = self.get_file_manager(uri) try: result = fm.list_packages(clear_ros_cache) fixed_result = { nmdurl.join(grpc_url, path): name for path, name in result.items() } self._cache_packages[grpc_url] = fixed_result self.packages.emit(grpc_url, fixed_result) self.packages_available.emit(grpc_url) except Exception as err: self.error.emit("_list_packages", "grpc://%s" % uri, path, err) finally: self.close_channel(channel, uri) if hasattr(self, '_threads'): self._threads.finished("gmt_%s_%d" % (grpc_url_or_path, clear_ros_cache))
def _listed_path(self, url, path, result): if not self.is_current_nmd(url): return root = self.invisibleRootItem() while root.rowCount(): root.removeRow(0) self.pyqt_workaround.clear() # test for ROS root paths and add these if it is in ROS_PACKAGE_PATH isroot = path in ['', os.path.sep] if isroot: self.ros_root_paths[url] = [] # append path items to the list model result_list = [] for path_item in result: if isroot and path_item.type in [FileItem.DIR, FileItem.PACKAGE]: self.ros_root_paths[url].append(path_item.path) item = os.path.normpath(os.path.join(path, path_item.path)) gpath = nmdurl.join(url, item) path_id = PathItem.NOT_FOUND if FileItem.FILE == path_item.type: _, ext = os.path.splitext(path_item.path) if ext in nm.settings( ).launch_view_file_ext or path_item.path.find('.launch.') > 0: path_id = PathItem.FILE elif FileItem.DIR == path_item.type: path_id = PathItem.FOLDER elif FileItem.SYMLINK == path_item.type: pass elif FileItem.PACKAGE == path_item.type: path_id = PathItem.PACKAGE if path_id != PathItem.NOT_FOUND and not os.path.basename( path_item.path).startswith('.'): # TODO: create filter for files result_list.append( (gpath, path_id, path_item.mtime, path_item.size, os.path.basename(path_item.path))) root_path = nmdurl.join(url, path) self._set_new_list(root_path, result_list) isroot = self._is_root(self._current_path) if isroot and not nmdurl.equal_uri(self._current_master, masteruri_from_master()): self._add_path(nmdurl.nmduri(self._current_master), PathItem.REMOTE_DAEMON, 0, 0, get_hostname(self._current_master_name)) self.pathlist_handled.emit(root_path)
def expand_item(self, path, path_id, clear_cache=False): ''' Returns for the given item and path the file path if this is a file. Otherwise the folder will be expanded and None will be returned. :param str path: the real path of the item :param int path_id: the id of the path :param bool clear_cache: clear cache before reload :return: path of the launch file or None :rtype: str :raise Exception: if no path to given item was found ''' if path_id in [PathItem.NOTHING]: return None has_shift_mod = Qt.ShiftModifier & QApplication.keyboardModifiers() if path_id in [ PathItem.LAUNCH_FILE, PathItem.CFG_FILE, PathItem.PROFILE, PathItem.FILE, PathItem.RECENT_FILE, PathItem.LAUNCH_FILE ]: if not has_shift_mod: return path root = self.invisibleRootItem() while root.rowCount(): root.removeRow(0) self.pyqt_workaround.clear() if has_shift_mod: if path_id in [ PathItem.LAUNCH_FILE, PathItem.CFG_FILE, PathItem.PROFILE, PathItem.FILE, PathItem.RECENT_FILE, PathItem.LAUNCH_FILE ]: self._current_path = os.path.dirname(path) else: self._current_path = nmdurl.nmduri() else: if path_id in [PathItem.ROOT]: surl, spath = nmdurl.split(path, with_scheme=True) if self._is_root(path) or spath in ['', os.path.sep]: self._current_path = nmdurl.nmduri() elif self._is_ros_root(path): self._current_path = surl else: dir_path = os.path.dirname(spath) self._current_path = nmdurl.join(surl, dir_path) elif self._current_path != path: self._current_path = path self._add_path(self._current_path, PathItem.ROOT, 0, 0, 'loading...') nm.nmd().file.list_path_threaded(self._current_path, clear_cache) # TODO: add functionality to go deep automatically # else: # key_mod = QApplication.keyboardModifiers() # onestep = False # if key_mod & Qt.ControlModifier: # onestep = True # root_path, items = self._moveDown(path, onestep) # self._setNewList((root_path, items)) return None
def get_package_binaries(self, pkgname, grpc_url='grpc://localhost:12321'): uri, _path = nmdurl.split(grpc_url) rospy.logdebug("get_package_binaries for '%s' from '%s'" % (pkgname, uri)) fm = self.get_file_manager(uri) response = fm.get_package_binaries(pkgname) url, _ = nmdurl.split(grpc_url, with_scheme=True) result = {} for item in response: result[nmdurl.join(url, item.path)] = item.mtime return result
def set_path(self, path, path_id=PathItem.FOLDER): ''' Shows the new path in the launch configuration view. Only if the new path is in ros package paths :param str path: new path ''' # TODO toset = path if not path.startswith('grpc://'): toset = nmdurl.join(self.current_grpc, path) self.expand_item(toset, path_id)
def set_package_filter(self, text): if text: if text.startswith(os.path.sep): self._current_search = nmdurl.join( self.launchlist_model.current_grpc, text) self.launchlist_model.set_path(text) else: # search for a package self.launchlist_model.show_packages(text) self.ui_search_line.set_process_active(False) else: self.launchlist_model.reload_current_path()
def load_launch(self, grpc_path, masteruri='', host='', package='', launch='', args={}): ''' Loads given file on remote grpc-server. :return: Path of loaded file :rtype: str ''' uri, path = nmdurl.split(grpc_path) lm, channel = self.get_launch_manager(uri) myargs = args request_args = True nexttry = True ok = False launch_file = '' args_res = {} while nexttry: try: rospy.logdebug("load launch file on gRPC server: %s" % (grpc_path)) launch_file, args_res = lm.load_launch(package, launch, path=path, args=myargs, request_args=request_args, masteruri=masteruri, host=host) nexttry = False ok = True except exceptions.LaunchSelectionRequest as lsr: # TODO: selection dialog rospy.logwarn("%s\n ...load the last one!" % lsr) path = lsr.choices[-1] except exceptions.ParamSelectionRequest as psr: rospy.loginfo("Params requered for: %s" % ["%s:=%s" % (name, value) for name, value in psr.choices.items()]) request_args = False myargs = psr.choices # request the args: the dialog must run in the main thread of Qt params = {} for name, value in psr.choices.items(): params[name] = {':value': value, ':type': 'string'} raise LaunchArgsSelectionRequest(grpc_path, params, 'Needs input for args') except exceptions.AlreadyOpenException as aoe: rospy.logwarn(aoe) nexttry = False ok = True launch_file = aoe.path except grpc._channel._Rendezvous as grpc_error: if grpc_error.code() == grpc.StatusCode.DEADLINE_EXCEEDED: raise exceptions.GrpcTimeout(grpc_path, grpc_error) raise finally: self.close_channel(channel, uri) launch_file = nmdurl.join("grpc://%s" % uri, launch_file) rospy.logdebug(" load launch file result - %s: %s" % ('OK' if ok else "ERR", launch_file)) with self._args_lock: rospy.logdebug("add args after load %s: %s" % (launch_file, args_res)) self._launch_args[launch_file] = args_res return launch_file, args_res
def get_interpreted_path(self, grpc_url_or_path='grpc://localhost:12321', text=[]): ''' :param str grpc_url_or_path: the url for node manager daemon :param [str] text: list of string with text to interpret to a path :return: Returns an iterator for tuples with interpreted path and file exists or not :rtype: tuple(str, bool) ''' uri, _ = nmdurl.split(grpc_url_or_path) lm, channel = self.get_launch_manager(uri) rospy.logdebug("get_interpreted_path in text %s" % text) reply = lm.get_interpreted_path(text) url, _ = nmdurl.split(grpc_url_or_path, with_scheme=True) for path, exists in reply: yield (nmdurl.join(url, path), exists) self.close_channel(channel, uri)
def _get_nodes_threaded(self, grpc_path='grpc://localhost:12321', masteruri=''): uri, _ = nmdurl.split(grpc_path) rospy.logdebug("[thread] get nodes from %s" % uri) lm, channel = self.get_launch_manager(uri) try: launch_descriptions = lm.get_nodes(True, masteruri=masteruri) clean_url = nmdurl.nmduri_from_path(grpc_path) for ld in launch_descriptions: ld.path = nmdurl.join(clean_url, ld.path) self.launch_nodes.emit(clean_url, launch_descriptions) except Exception as err: self.error.emit("_get_nodes", grpc_path, masteruri, err) finally: self.close_channel(channel, uri) if hasattr(self, '_threads'): self._threads.finished("gn_%s_%s" % (grpc_path, masteruri))
def _nmd_error(self, method, url, path, error): if method != 'list_path' or not self.is_current_nmd(url): return root = self.invisibleRootItem() while root.rowCount(): root.removeRow(0) self.pyqt_workaround.clear() self._add_path(self._current_path, PathItem.ROOT, 0, 0, '') detail_msg = utf8(error) if hasattr(error, 'details'): detail_msg = utf8(error.details()) path_item = PathItem.create_row_items( utf8("%s, please start node manager daemon" % detail_msg), PathItem.NOTHING, 0, 0, 'connecting to daemon...') root.appendRow(path_item) self.pyqt_workaround[path_item[0].name] = path_item[0] self.error_on_path.emit(nmdurl.join(url, path), error)
def _check_for_changed_files_threaded(self, grpc_url, path_dict): rospy.logdebug( "[thread] check_for_changed_files_threaded: with %d files on %s" % (len(path_dict), grpc_url)) uri, _path = nmdurl.split(grpc_url, with_scheme=False) fm = self.get_file_manager(uri) try: response = fm.changed_files(path_dict) for item in response: self.changed_file.emit(nmdurl.join(grpc_url, item.path), item.mtime) except Exception as e: self.error.emit("changed_files", "grpc://%s" % uri, "", e) # rospy.logwarn("check_for_changed_files_threaded: %s" % e) url, _path = nmdurl.split(grpc_url, with_scheme=True) if hasattr(self, '_threads'): self._threads.finished("cft_%s" % url)
def _get_loaded_files_threaded(self, grpc_path='grpc://localhost:12321'): uri, path = nmdurl.split(grpc_path) rospy.logdebug("[thread] get loaded_files from %s" % uri) try: lm, channel = self.get_launch_manager(uri) result = lm.get_loaded_files() url, _ = nmdurl.split(grpc_path, with_scheme=True) for _package, path, args, _masteruri, _host in result: with self._args_lock: gpath = nmdurl.join(url, path) rospy.logdebug("[thread] add args for %s: %s" % (gpath, args)) self._launch_args[gpath] = args except Exception: import traceback print(traceback.format_exc()) finally: self.close_channel(channel, uri) if hasattr(self, '_threads'): self._threads.finished("glft_%s" % grpc_path)
def add_new_launch(self): ''' Inserts the given item in the list model. :param str path: the path of the item combined with the url of the node manager daemon :param int path_id: the id (constants of PathItem) of the item, which represents whether it is a file, package or stack :param int mtime: modification time :param int size: file size :param str name: the displayed name ''' root = self.invisibleRootItem() new_name = 'new.launch' cc = 0 while self._exists(new_name): cc += 1 new_name = 'new_%d.launch' % cc # add sorted a new entry try: path_item = PathItem.create_row_items(nmdurl.join( self._current_path, new_name), PathItem.LAUNCH_FILE, 0, 0, new_name, isnew=True) if root.rowCount() > 1: root.insertRow(1, path_item) else: root.appendRow(path_item) self.pyqt_workaround[path_item[0].name] = path_item[ 0] # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass return path_item except Exception: import traceback print(traceback.format_exc(2)) return []