ipy_fsops.py
254 lines
| 6.7 KiB
| text/x-python
|
PythonLexer
vivainio
|
r851 | """ File system operations | ||
Contains: Simple variants of normal unix shell commands (icp, imv, irm, | ||||
imkdir, igrep). | ||||
Some "otherwise handy" utils ('collect' for gathering files to | ||||
~/_ipython/collect, 'inote' for collecting single note lines to | ||||
~/_ipython/note.txt) | ||||
Mostly of use for bare windows installations where cygwin/equivalent is not | ||||
installed and you would otherwise need to deal with dos versions of the | ||||
commands (that e.g. don't understand / as path separator). These can | ||||
do some useful tricks on their own, though (like use 'mglob' patterns). | ||||
Not to be confused with ipipe commands (ils etc.) that also start with i. | ||||
Julian Taylor
|
r7275 | |||
QUARANTINE, NEEDS UPDATING TO THE NEW IPYTHON API TO WORK | ||||
this depends on mglob that used to be in externals, | ||||
if this code is updated to run again with current IPython, you may need to | ||||
reintroduce that file back. In doing so, look for the possibility of achieving | ||||
the same effect only with the standard library (which may have improved by now, | ||||
since we currently depend on Python 2.6). | ||||
vivainio
|
r851 | """ | ||
Brian Granger
|
r2027 | from IPython.core import ipapi | ||
Brian Granger
|
r2205 | from IPython.core.error import TryNext | ||
Brian Granger
|
r2027 | ip = ipapi.get() | ||
vivainio
|
r851 | |||
import shutil,os,shlex | ||||
from IPython.external import mglob | ||||
vivainio
|
r964 | from IPython.external.path import path | ||
Brian Granger
|
r2205 | from IPython.core.error import UsageError | ||
Brian Granger
|
r2022 | import IPython.utils.generics | ||
vivainio
|
r851 | |||
def parse_args(args): | ||||
""" Given arg string 'CMD files... target', return ([files], target) """ | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | tup = args.split(None, 1) | ||
if len(tup) == 1: | ||||
vivainio
|
r860 | raise UsageError("Expected arguments for " + tup[0]) | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | tup2 = shlex.split(tup[1]) | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | flist, trg = mglob.expand(tup2[0:-1]), tup2[-1] | ||
if not flist: | ||||
vivainio
|
r860 | raise UsageError("No files found:" + str(tup2[0:-1])) | ||
vivainio
|
r851 | return flist, trg | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | def icp(ip,arg): | ||
""" icp files... targetdir | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Copy all files to target, creating dirs for target if necessary | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | icp srcdir dstdir | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Copy srcdir to distdir | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | """ | ||
import distutils.dir_util | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | fs, targetdir = parse_args(arg) | ||
vivainio
|
r860 | if not os.path.isdir(targetdir) and len(fs) > 1: | ||
vivainio
|
r851 | distutils.dir_util.mkpath(targetdir,verbose =1) | ||
for f in fs: | ||||
vivainio
|
r860 | if os.path.isdir(f): | ||
shutil.copytree(f, targetdir) | ||||
else: | ||||
shutil.copy2(f,targetdir) | ||||
vivainio
|
r851 | return fs | ||
Brian Granger
|
r2205 | ip.define_alias("icp",icp) | ||
vivainio
|
r851 | |||
def imv(ip,arg): | ||||
""" imv src tgt | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Move source to target. | ||
""" | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | fs, target = parse_args(arg) | ||
if len(fs) > 1: | ||||
assert os.path.isdir(target) | ||||
Bernardo B. Marques
|
r4872 | for f in fs: | ||
vivainio
|
r851 | shutil.move(f, target) | ||
return fs | ||||
Bernardo B. Marques
|
r4872 | ip.define_alias("imv",imv) | ||
vivainio
|
r851 | |||
def irm(ip,arg): | ||||
""" irm path[s]... | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Remove file[s] or dir[s] path. Dirs are deleted recursively. | ||
""" | ||||
vivainio
|
r860 | try: | ||
paths = mglob.expand(arg.split(None,1)[1]) | ||||
except IndexError: | ||||
raise UsageError("%irm paths...") | ||||
vivainio
|
r851 | import distutils.dir_util | ||
for p in paths: | ||||
print "rm",p | ||||
if os.path.isdir(p): | ||||
distutils.dir_util.remove_tree(p, verbose = 1) | ||||
else: | ||||
os.remove(p) | ||||
Brian Granger
|
r2205 | ip.define_alias("irm",irm) | ||
vivainio
|
r851 | |||
def imkdir(ip,arg): | ||||
""" imkdir path | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Creates dir path, and all dirs on the road | ||
""" | ||||
import distutils.dir_util | ||||
targetdir = arg.split(None,1)[1] | ||||
Bernardo B. Marques
|
r4872 | distutils.dir_util.mkpath(targetdir,verbose =1) | ||
vivainio
|
r851 | |||
Bernardo B. Marques
|
r4872 | ip.define_alias("imkdir",imkdir) | ||
vivainio
|
r851 | |||
def igrep(ip,arg): | ||||
""" igrep PAT files... | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Very dumb file scan, case-insensitive. | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | e.g. | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | igrep "test this" rec:*.py | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | """ | ||
elems = shlex.split(arg) | ||||
dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:]) | ||||
res = [] | ||||
for f in fs: | ||||
found = False | ||||
for l in open(f): | ||||
if pat.lower() in l.lower(): | ||||
if not found: | ||||
print "[[",f,"]]" | ||||
found = True | ||||
res.append(f) | ||||
print l.rstrip() | ||||
return res | ||||
Bernardo B. Marques
|
r4872 | ip.define_alias("igrep",igrep) | ||
vivainio
|
r851 | |||
def collect(ip,arg): | ||||
""" collect foo/a.txt rec:bar=*.py | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar, | ||
likewise | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Without args, try to open ~/_ipython/collect dir (in win32 at least). | ||
""" | ||||
vivainio
|
r964 | from IPython.external.path import path | ||
Brian Granger
|
r2322 | basedir = path(ip.ipython_dir + '/collect') | ||
Bernardo B. Marques
|
r4872 | try: | ||
vivainio
|
r851 | fs = mglob.expand(arg.split(None,1)[1]) | ||
except IndexError: | ||||
os.startfile(basedir) | ||||
return | ||||
for f in fs: | ||||
f = path(f) | ||||
trg = basedir / f.splitdrive()[1].lstrip('/\\') | ||||
if f.isdir(): | ||||
print "mkdir",trg | ||||
trg.makedirs() | ||||
continue | ||||
dname = trg.dirname() | ||||
if not dname.isdir(): | ||||
dname.makedirs() | ||||
print f,"=>",trg | ||||
shutil.copy2(f,trg) | ||||
Bernardo B. Marques
|
r4872 | ip.define_alias("collect",collect) | ||
vivainio
|
r851 | |||
def inote(ip,arg): | ||||
""" inote Hello world | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Adds timestamp and Hello world to ~/_ipython/notes.txt | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | Without args, opens notes.txt for editing. | ||
""" | ||||
import time | ||||
Brian Granger
|
r2322 | fname = ip.ipython_dir + '/notes.txt' | ||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r851 | try: | ||
entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n' | ||||
Bernardo B. Marques
|
r4872 | f= open(fname, 'a').write(entry) | ||
vivainio
|
r851 | except IndexError: | ||
Bernardo B. Marques
|
r4872 | ip.hooks.editor(fname) | ||
vivainio
|
r851 | |||
Brian Granger
|
r2205 | ip.define_alias("inote",inote) | ||
vivainio
|
r912 | |||
def pathobj_mangle(p): | ||||
return p.replace(' ', '__').replace('.','DOT') | ||||
def pathobj_unmangle(s): | ||||
return s.replace('__',' ').replace('DOT','.') | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r915 | class PathObj(path): | ||
vivainio
|
r912 | def __init__(self,p): | ||
self.path = p | ||||
vivainio
|
r914 | if p != '.': | ||
self.ents = [pathobj_mangle(ent) for ent in os.listdir(p)] | ||||
else: | ||||
vivainio
|
r912 | self.ents = None | ||
def __complete__(self): | ||||
vivainio
|
r914 | if self.path != '.': | ||
vivainio
|
r912 | return self.ents | ||
vivainio
|
r914 | self.ents = [pathobj_mangle(ent) for ent in os.listdir('.')] | ||
return self.ents | ||||
vivainio
|
r912 | def __getattr__(self,name): | ||
if name in self.ents: | ||||
if self.path.endswith('/'): | ||||
sep = '' | ||||
else: | ||||
sep = '/' | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r912 | tgt = self.path + sep + pathobj_unmangle(name) | ||
#print "tgt",tgt | ||||
if os.path.isdir(tgt): | ||||
return PathObj(tgt) | ||||
if os.path.isfile(tgt): | ||||
vivainio
|
r914 | return path(tgt) | ||
vivainio
|
r912 | |||
raise AttributeError, name # <<< DON'T FORGET THIS LINE !! | ||||
def __str__(self): | ||||
return self.path | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r912 | def __repr__(self): | ||
return "<PathObj to %s>" % self.path | ||||
Bernardo B. Marques
|
r4872 | |||
vivainio
|
r912 | def __call__(self): | ||
print "cd:",self.path | ||||
os.chdir(self.path) | ||||
Bernardo B. Marques
|
r4872 | |||
def complete_pathobj(obj, prev_completions): | ||||
vivainio
|
r912 | if hasattr(obj,'__complete__'): | ||
vivainio
|
r915 | res = obj.__complete__() | ||
if res: | ||||
return res | ||||
# just return normal attributes of 'path' object if the dir is empty | ||||
Brian Granger
|
r2205 | raise TryNext | ||
vivainio
|
r912 | |||
Brian Granger
|
r2022 | complete_pathobj = IPython.utils.generics.complete_object.when_type(PathObj)(complete_pathobj) | ||
vivainio
|
r912 | |||
def test_pathobj(): | ||||
#p = PathObj('c:/prj') | ||||
#p2 = p.cgi | ||||
#print p,p2 | ||||
vivainio
|
r915 | rootdir = PathObj("/") | ||
vivainio
|
r912 | startmenu = PathObj("d:/Documents and Settings/All Users/Start Menu/Programs") | ||
vivainio
|
r914 | cwd = PathObj('.') | ||
Brian Granger
|
r2205 | ip.push("rootdir startmenu cwd") | ||
Bernardo B. Marques
|
r4872 | |||
Julian Taylor
|
r7275 | #test_pathobj() | ||