def test_isdotfile(self): for path in [".foo", ".svn", "foo/.svn", "foo/bar/.svn", "/foo/.bar"]: self.assertTrue(isdotfile(path)) for path in [ "asfoo", "df.svn", "foo/er.svn", "foo/bar/test.txt", "/foo/bar" ]: self.assertFalse(isdotfile(path))
def wrap_filename(self, fname): fname = _unicode(fname) if not self.terminal_colors: return fname if '://' in fname: return fname if '.' in fname: name, ext = splitext(fname) fname = u'%s\x1b[36m%s\x1b[0m' % (name, ext) if isdotfile(fname): fname = u'\x1b[2m%s\x1b[0m' % fname return fname
def wrap_filename(self, fname): fname = _unicode(fname) if not self.terminal_colors: return fname if "://" in fname: return fname # if '.' in fname: # name, ext = splitext(fname) # fname = u'%s\x1b[36m%s\x1b[0m' % (name, ext) if isdotfile(fname): fname = "\x1b[33m%s\x1b[0m" % fname return fname
def do_run(self, options, args): output = self.output if not args: args = [u'.'] dir_paths = [] file_paths = [] fs_used = set() for fs_url in args: fs, path = self.open_fs(fs_url) fs_used.add(fs) path = path or '.' wildcard = None if iswildcard(path): path, wildcard = pathsplit(path) if path != '.' and fs.isfile(path): if not options.dirsonly: file_paths.append(path) else: if not options.filesonly: dir_paths += fs.listdir(path, wildcard=wildcard, full=options.fullpath or options.url, dirs_only=True) if not options.dirsonly: file_paths += fs.listdir(path, wildcard=wildcard, full=options.fullpath or options.url, files_only=True) for fs in fs_used: try: fs.close() except FSError: pass if options.syspath: # Path without a syspath, just won't be displayed dir_paths = filter( None, [fs.getsyspath(path, allow_none=True) for path in dir_paths]) file_paths = filter( None, [fs.getsyspath(path, allow_none=True) for path in file_paths]) if options.url: # Path without a syspath, just won't be displayed dir_paths = filter( None, [fs.getpathurl(path, allow_none=True) for path in dir_paths]) file_paths = filter( None, [fs.getpathurl(path, allow_none=True) for path in file_paths]) dirs = frozenset(dir_paths) paths = sorted(dir_paths + file_paths, key=lambda p: p.lower()) if not options.all: paths = [path for path in paths if not isdotfile(path)] if not paths: return def columnize(paths, num_columns): col_height = (len(paths) + num_columns - 1) / num_columns columns = [[] for _ in xrange(num_columns)] col_no = 0 col_pos = 0 for path in paths: columns[col_no].append(path) col_pos += 1 if col_pos >= col_height: col_no += 1 col_pos = 0 padded_columns = [] wrap_filename = self.wrap_filename wrap_dirname = self.wrap_dirname def wrap(path): if path in dirs: return wrap_dirname(path.ljust(max_width)) else: return wrap_filename(path.ljust(max_width)) for column in columns: if column: max_width = max([len(path) for path in column]) else: max_width = 1 max_width = min(max_width, terminal_width) padded_columns.append([wrap(path) for path in column]) return padded_columns def condense_columns(columns): max_column_height = max([len(col) for col in columns]) lines = [[] for _ in xrange(max_column_height)] for column in columns: for line, path in zip(lines, column): line.append(path) return '\n'.join(u' '.join(line) for line in lines) if options.long: for path in paths: if path in dirs: output((self.wrap_dirname(path), '\n')) else: output((self.wrap_filename(path), '\n')) else: terminal_width = self.terminal_width path_widths = [len(path) for path in paths] smallest_paths = min(path_widths) num_paths = len(paths) num_cols = min(terminal_width / (smallest_paths + 2), num_paths) while num_cols: col_height = (num_paths + num_cols - 1) / num_cols line_width = 0 for col_no in xrange(num_cols): try: col_width = max( path_widths[col_no * col_height:(col_no + 1) * col_height]) except ValueError: continue line_width += col_width if line_width > terminal_width: break line_width += 2 else: if line_width - 1 <= terminal_width: break num_cols -= 1 num_cols = max(1, num_cols) columns = columnize(paths, num_cols) output((condense_columns(columns), '\n'))
def expand(self, item_id): item_data = self.tree.GetItemData(item_id).GetData() path = item_data["path"] if not self.fs.isdir(path): return if item_data['expanded']: return try: paths = ([ (True, p) for p in self.fs.listdir(path, absolute=True, dirs_only=True) ] + [(False, p) for p in self.fs.listdir(path, absolute=True, files_only=True) ]) except FSError as e: msg = "Failed to get directory listing for %s\n\nThe following error was reported:\n\n%s" % ( path, e) wx.MessageDialog(self, msg, "Error listing directory", wx.OK).ShowModal() paths = [] #paths = [(self.fs.isdir(p), p) for p in self.fs.listdir(path, absolute=True)] if self.hide_dotfiles: paths = [p for p in paths if not isdotfile(p[1])] if not paths: #self.tree.SetItemHasChildren(item_id, False) #self.tree.Collapse(item_id) return paths.sort(key=lambda p: (not p[0], p[1].lower())) for is_dir, new_path in paths: name = pathsplit(new_path)[-1] new_item = self.tree.AppendItem(item_id, name, data=wx.TreeItemData({ 'path': new_path, 'expanded': False })) info = self.fs.getinfo(new_path) if is_dir: self.tree.SetItemHasChildren(new_item) self.tree.SetItemImage(new_item, self.fldridx, 0, wx.TreeItemIcon_Normal) self.tree.SetItemImage(new_item, self.fldropenidx, 0, wx.TreeItemIcon_Expanded) self.tree.SetItemText(new_item, "", 2) ct = info.get('created_time', None) if ct is not None: self.tree.SetItemText(new_item, ct.ctime(), 3) else: self.tree.SetItemText(new_item, 'unknown', 3) else: self.tree.SetItemImage(new_item, self.fileidx, 0, wx.TreeItemIcon_Normal) self.tree.SetItemText(new_item, str(info.get('size', '?')) + " bytes", 2) ct = info.get('created_time', None) if ct is not None: self.tree.SetItemText(new_item, ct.ctime(), 3) else: self.tree.SetItemText(new_item, 'unknown', 3) self.tree.SetItemText(new_item, self.fs.desc(new_path), 1) item_data['expanded'] = True self.tree.Expand(item_id)
def do_run(self, options, args): output = self.output if not args: args = [u'.'] dir_paths = [] file_paths = [] fs_used = set() for fs_url in args: fs, path = self.open_fs(fs_url) fs_used.add(fs) path = path or '.' wildcard = None if iswildcard(path): path, wildcard = pathsplit(path) if path != '.' and fs.isfile(path): if not options.dirsonly: file_paths.append(path) else: if not options.filesonly: dir_paths += fs.listdir(path, wildcard=wildcard, full=options.fullpath or options.url, dirs_only=True) if not options.dirsonly: file_paths += fs.listdir(path, wildcard=wildcard, full=options.fullpath or options.url, files_only=True) for fs in fs_used: try: fs.close() except FSError: pass if options.syspath: # Path without a syspath, just won't be displayed dir_paths = filter(None, [fs.getsyspath(path, allow_none=True) for path in dir_paths]) file_paths = filter(None, [fs.getsyspath(path, allow_none=True) for path in file_paths]) if options.url: # Path without a syspath, just won't be displayed dir_paths = filter(None, [fs.getpathurl(path, allow_none=True) for path in dir_paths]) file_paths = filter(None, [fs.getpathurl(path, allow_none=True) for path in file_paths]) dirs = frozenset(dir_paths) paths = sorted(dir_paths + file_paths, key=lambda p: p.lower()) if not options.all: paths = [path for path in paths if not isdotfile(path)] if not paths: return def columnize(paths, num_columns): col_height = (len(paths) + num_columns - 1) / num_columns columns = [[] for _ in xrange(num_columns)] col_no = 0 col_pos = 0 for path in paths: columns[col_no].append(path) col_pos += 1 if col_pos >= col_height: col_no += 1 col_pos = 0 padded_columns = [] wrap_filename = self.wrap_filename wrap_dirname = self.wrap_dirname def wrap(path): if path in dirs: return wrap_dirname(path.ljust(max_width)) else: return wrap_filename(path.ljust(max_width)) for column in columns: if column: max_width = max([len(path) for path in column]) else: max_width = 1 max_width = min(max_width, terminal_width) padded_columns.append([wrap(path) for path in column]) return padded_columns def condense_columns(columns): max_column_height = max([len(col) for col in columns]) lines = [[] for _ in xrange(max_column_height)] for column in columns: for line, path in zip(lines, column): line.append(path) return '\n'.join(u' '.join(line) for line in lines) if options.long: for path in paths: if path in dirs: output((self.wrap_dirname(path), '\n')) else: output((self.wrap_filename(path), '\n')) else: terminal_width = self.terminal_width path_widths = [len(path) for path in paths] smallest_paths = min(path_widths) num_paths = len(paths) num_cols = min(terminal_width // (smallest_paths + 2), num_paths) while num_cols: col_height = (num_paths + num_cols - 1) // num_cols line_width = 0 for col_no in xrange(num_cols): try: col_width = max(path_widths[col_no * col_height: (col_no + 1) * col_height]) except ValueError: continue line_width += col_width if line_width > terminal_width: break line_width += 2 else: if line_width - 1 <= terminal_width: break num_cols -= 1 num_cols = max(1, num_cols) columns = columnize(paths, num_cols) output((condense_columns(columns), '\n'))
class BrowseFrame(wx.Frame): def __init__(self, fs, hide_dotfiles=False): wx.Frame.__init__(self, None, size=(1000, 600)) self.fs = fs self.hide_dotfiles = hide_dotfiles self.SetTitle("FS Browser - " + unicode(fs)) self.tree = wx.gizmos.TreeListCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT) self.tree.AddColumn("File System") self.tree.AddColumn("Description") self.tree.AddColumn("Size") self.tree.AddColumn("Created") self.tree.SetColumnWidth(0, 300) self.tree.SetColumnWidth(1, 250) self.tree.SetColumnWidth(2, 150) self.tree.SetColumnWidth(3, 250) self.root_id = self.tree.AddRoot('root', data=wx.TreeItemData({ 'path': "/", 'expanded': False })) rid = self.tree.GetItemData(self.root_id) isz = (16, 16) il = wx.ImageList(isz[0], isz[1]) self.fldridx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)) self.fldropenidx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)) self.fileidx = il.Add( wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)) self.tree.SetImageList(il) self.il = il self.tree.SetItemImage(self.root_id, self.fldridx, wx.TreeItemIcon_Normal) self.tree.SetItemImage(self.root_id, self.fldropenidx, wx.TreeItemIcon_Expanded) self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding) self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated) wx.CallAfter(self.OnInit) def OnInit(self): self.expand(self.root_id) def expand(self, item_id): item_data = self.tree.GetItemData(item_id).GetData() path = item_data["path"] if not self.fs.isdir(path): return if item_data['expanded']: return try: paths = ([ (True, p) for p in self.fs.listdir(path, absolute=True, dirs_only=True) ] + [(False, p) for p in self.fs.listdir(path, absolute=True, files_only=True) ]) except FSError, e: msg = "Failed to get directory listing for %s\n\nThe following error was reported:\n\n%s" % ( path, e) wx.MessageDialog(self, msg, "Error listing directory", wx.OK).ShowModal() paths = [] #paths = [(self.fs.isdir(p), p) for p in self.fs.listdir(path, absolute=True)] if self.hide_dotfiles: paths = [p for p in paths if not isdotfile(p[1])] if not paths: #self.tree.SetItemHasChildren(item_id, False) #self.tree.Collapse(item_id) return paths.sort(key=lambda p: (not p[0], p[1].lower())) for is_dir, new_path in paths: name = pathsplit(new_path)[-1] new_item = self.tree.AppendItem(item_id, name, data=wx.TreeItemData({ 'path': new_path, 'expanded': False })) info = self.fs.getinfo(new_path) if is_dir: self.tree.SetItemHasChildren(new_item) self.tree.SetItemImage(new_item, self.fldridx, 0, wx.TreeItemIcon_Normal) self.tree.SetItemImage(new_item, self.fldropenidx, 0, wx.TreeItemIcon_Expanded) self.tree.SetItemText(new_item, "", 2) ct = info.get('created_time', None) if ct is not None: self.tree.SetItemText(new_item, ct.ctime(), 3) else: self.tree.SetItemText(new_item, 'unknown', 3) else: self.tree.SetItemImage(new_item, self.fileidx, 0, wx.TreeItemIcon_Normal) self.tree.SetItemText(new_item, str(info.get('size', '?')) + " bytes", 2) ct = info.get('created_time', None) if ct is not None: self.tree.SetItemText(new_item, ct.ctime(), 3) else: self.tree.SetItemText(new_item, 'unknown', 3) self.tree.SetItemText(new_item, self.fs.desc(new_path), 1) item_data['expanded'] = True self.tree.Expand(item_id)