##// END OF EJS Templates
ipy_fsops: inherit pathobj from path
vivainio -
Show More
@@ -1,242 +1,244
1 """ File system operations
1 """ File system operations
2
2
3 Contains: Simple variants of normal unix shell commands (icp, imv, irm,
3 Contains: Simple variants of normal unix shell commands (icp, imv, irm,
4 imkdir, igrep).
4 imkdir, igrep).
5
5
6 Some "otherwise handy" utils ('collect' for gathering files to
6 Some "otherwise handy" utils ('collect' for gathering files to
7 ~/_ipython/collect, 'inote' for collecting single note lines to
7 ~/_ipython/collect, 'inote' for collecting single note lines to
8 ~/_ipython/note.txt)
8 ~/_ipython/note.txt)
9
9
10 Mostly of use for bare windows installations where cygwin/equivalent is not
10 Mostly of use for bare windows installations where cygwin/equivalent is not
11 installed and you would otherwise need to deal with dos versions of the
11 installed and you would otherwise need to deal with dos versions of the
12 commands (that e.g. don't understand / as path separator). These can
12 commands (that e.g. don't understand / as path separator). These can
13 do some useful tricks on their own, though (like use 'mglob' patterns).
13 do some useful tricks on their own, though (like use 'mglob' patterns).
14
14
15 Not to be confused with ipipe commands (ils etc.) that also start with i.
15 Not to be confused with ipipe commands (ils etc.) that also start with i.
16 """
16 """
17
17
18 import IPython.ipapi
18 import IPython.ipapi
19 ip = IPython.ipapi.get()
19 ip = IPython.ipapi.get()
20
20
21 import shutil,os,shlex
21 import shutil,os,shlex
22 from IPython.external import mglob
22 from IPython.external import mglob
23 from IPython.Extensions.path import path
23 from IPython.Extensions.path import path
24 from IPython.ipapi import UsageError
24 from IPython.ipapi import UsageError
25
25
26 def parse_args(args):
26 def parse_args(args):
27 """ Given arg string 'CMD files... target', return ([files], target) """
27 """ Given arg string 'CMD files... target', return ([files], target) """
28
28
29 tup = args.split(None, 1)
29 tup = args.split(None, 1)
30 if len(tup) == 1:
30 if len(tup) == 1:
31 raise UsageError("Expected arguments for " + tup[0])
31 raise UsageError("Expected arguments for " + tup[0])
32
32
33 tup2 = shlex.split(tup[1])
33 tup2 = shlex.split(tup[1])
34
34
35 flist, trg = mglob.expand(tup2[0:-1]), tup2[-1]
35 flist, trg = mglob.expand(tup2[0:-1]), tup2[-1]
36 if not flist:
36 if not flist:
37 raise UsageError("No files found:" + str(tup2[0:-1]))
37 raise UsageError("No files found:" + str(tup2[0:-1]))
38 return flist, trg
38 return flist, trg
39
39
40 def icp(ip,arg):
40 def icp(ip,arg):
41 """ icp files... targetdir
41 """ icp files... targetdir
42
42
43 Copy all files to target, creating dirs for target if necessary
43 Copy all files to target, creating dirs for target if necessary
44
44
45 icp srcdir dstdir
45 icp srcdir dstdir
46
46
47 Copy srcdir to distdir
47 Copy srcdir to distdir
48
48
49 """
49 """
50 import distutils.dir_util
50 import distutils.dir_util
51
51
52 fs, targetdir = parse_args(arg)
52 fs, targetdir = parse_args(arg)
53 if not os.path.isdir(targetdir) and len(fs) > 1:
53 if not os.path.isdir(targetdir) and len(fs) > 1:
54 distutils.dir_util.mkpath(targetdir,verbose =1)
54 distutils.dir_util.mkpath(targetdir,verbose =1)
55 for f in fs:
55 for f in fs:
56 if os.path.isdir(f):
56 if os.path.isdir(f):
57 shutil.copytree(f, targetdir)
57 shutil.copytree(f, targetdir)
58 else:
58 else:
59 shutil.copy2(f,targetdir)
59 shutil.copy2(f,targetdir)
60 return fs
60 return fs
61 ip.defalias("icp",icp)
61 ip.defalias("icp",icp)
62
62
63 def imv(ip,arg):
63 def imv(ip,arg):
64 """ imv src tgt
64 """ imv src tgt
65
65
66 Move source to target.
66 Move source to target.
67 """
67 """
68
68
69 fs, target = parse_args(arg)
69 fs, target = parse_args(arg)
70 if len(fs) > 1:
70 if len(fs) > 1:
71 assert os.path.isdir(target)
71 assert os.path.isdir(target)
72 for f in fs:
72 for f in fs:
73 shutil.move(f, target)
73 shutil.move(f, target)
74 return fs
74 return fs
75 ip.defalias("imv",imv)
75 ip.defalias("imv",imv)
76
76
77 def irm(ip,arg):
77 def irm(ip,arg):
78 """ irm path[s]...
78 """ irm path[s]...
79
79
80 Remove file[s] or dir[s] path. Dirs are deleted recursively.
80 Remove file[s] or dir[s] path. Dirs are deleted recursively.
81 """
81 """
82 try:
82 try:
83 paths = mglob.expand(arg.split(None,1)[1])
83 paths = mglob.expand(arg.split(None,1)[1])
84 except IndexError:
84 except IndexError:
85 raise UsageError("%irm paths...")
85 raise UsageError("%irm paths...")
86 import distutils.dir_util
86 import distutils.dir_util
87 for p in paths:
87 for p in paths:
88 print "rm",p
88 print "rm",p
89 if os.path.isdir(p):
89 if os.path.isdir(p):
90 distutils.dir_util.remove_tree(p, verbose = 1)
90 distutils.dir_util.remove_tree(p, verbose = 1)
91 else:
91 else:
92 os.remove(p)
92 os.remove(p)
93
93
94 ip.defalias("irm",irm)
94 ip.defalias("irm",irm)
95
95
96 def imkdir(ip,arg):
96 def imkdir(ip,arg):
97 """ imkdir path
97 """ imkdir path
98
98
99 Creates dir path, and all dirs on the road
99 Creates dir path, and all dirs on the road
100 """
100 """
101 import distutils.dir_util
101 import distutils.dir_util
102 targetdir = arg.split(None,1)[1]
102 targetdir = arg.split(None,1)[1]
103 distutils.dir_util.mkpath(targetdir,verbose =1)
103 distutils.dir_util.mkpath(targetdir,verbose =1)
104
104
105 ip.defalias("imkdir",imkdir)
105 ip.defalias("imkdir",imkdir)
106
106
107 def igrep(ip,arg):
107 def igrep(ip,arg):
108 """ igrep PAT files...
108 """ igrep PAT files...
109
109
110 Very dumb file scan, case-insensitive.
110 Very dumb file scan, case-insensitive.
111
111
112 e.g.
112 e.g.
113
113
114 igrep "test this" rec:*.py
114 igrep "test this" rec:*.py
115
115
116 """
116 """
117 elems = shlex.split(arg)
117 elems = shlex.split(arg)
118 dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:])
118 dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:])
119 res = []
119 res = []
120 for f in fs:
120 for f in fs:
121 found = False
121 found = False
122 for l in open(f):
122 for l in open(f):
123 if pat.lower() in l.lower():
123 if pat.lower() in l.lower():
124 if not found:
124 if not found:
125 print "[[",f,"]]"
125 print "[[",f,"]]"
126 found = True
126 found = True
127 res.append(f)
127 res.append(f)
128 print l.rstrip()
128 print l.rstrip()
129 return res
129 return res
130
130
131 ip.defalias("igrep",igrep)
131 ip.defalias("igrep",igrep)
132
132
133 def collect(ip,arg):
133 def collect(ip,arg):
134 """ collect foo/a.txt rec:bar=*.py
134 """ collect foo/a.txt rec:bar=*.py
135
135
136 Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar,
136 Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar,
137 likewise
137 likewise
138
138
139 Without args, try to open ~/_ipython/collect dir (in win32 at least).
139 Without args, try to open ~/_ipython/collect dir (in win32 at least).
140 """
140 """
141 from path import path
141 from path import path
142 basedir = path(ip.options.ipythondir + '/collect')
142 basedir = path(ip.options.ipythondir + '/collect')
143 try:
143 try:
144 fs = mglob.expand(arg.split(None,1)[1])
144 fs = mglob.expand(arg.split(None,1)[1])
145 except IndexError:
145 except IndexError:
146 os.startfile(basedir)
146 os.startfile(basedir)
147 return
147 return
148 for f in fs:
148 for f in fs:
149 f = path(f)
149 f = path(f)
150 trg = basedir / f.splitdrive()[1].lstrip('/\\')
150 trg = basedir / f.splitdrive()[1].lstrip('/\\')
151 if f.isdir():
151 if f.isdir():
152 print "mkdir",trg
152 print "mkdir",trg
153 trg.makedirs()
153 trg.makedirs()
154 continue
154 continue
155 dname = trg.dirname()
155 dname = trg.dirname()
156 if not dname.isdir():
156 if not dname.isdir():
157 dname.makedirs()
157 dname.makedirs()
158 print f,"=>",trg
158 print f,"=>",trg
159 shutil.copy2(f,trg)
159 shutil.copy2(f,trg)
160
160
161 ip.defalias("collect",collect)
161 ip.defalias("collect",collect)
162
162
163 def inote(ip,arg):
163 def inote(ip,arg):
164 """ inote Hello world
164 """ inote Hello world
165
165
166 Adds timestamp and Hello world to ~/_ipython/notes.txt
166 Adds timestamp and Hello world to ~/_ipython/notes.txt
167
167
168 Without args, opens notes.txt for editing.
168 Without args, opens notes.txt for editing.
169 """
169 """
170 import time
170 import time
171 fname = ip.options.ipythondir + '/notes.txt'
171 fname = ip.options.ipythondir + '/notes.txt'
172
172
173 try:
173 try:
174 entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n'
174 entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n'
175 f= open(fname, 'a').write(entry)
175 f= open(fname, 'a').write(entry)
176 except IndexError:
176 except IndexError:
177 ip.IP.hooks.editor(fname)
177 ip.IP.hooks.editor(fname)
178
178
179 ip.defalias("inote",inote)
179 ip.defalias("inote",inote)
180
180
181 def pathobj_mangle(p):
181 def pathobj_mangle(p):
182 return p.replace(' ', '__').replace('.','DOT')
182 return p.replace(' ', '__').replace('.','DOT')
183 def pathobj_unmangle(s):
183 def pathobj_unmangle(s):
184 return s.replace('__',' ').replace('DOT','.')
184 return s.replace('__',' ').replace('DOT','.')
185
185
186
186
187
187
188 class PathObj:
188 class PathObj(path):
189 def __init__(self,p):
189 def __init__(self,p):
190 self.path = p
190 self.path = p
191 if p != '.':
191 if p != '.':
192 self.ents = [pathobj_mangle(ent) for ent in os.listdir(p)]
192 self.ents = [pathobj_mangle(ent) for ent in os.listdir(p)]
193 else:
193 else:
194 self.ents = None
194 self.ents = None
195 def __complete__(self):
195 def __complete__(self):
196 if self.path != '.':
196 if self.path != '.':
197 return self.ents
197 return self.ents
198 self.ents = [pathobj_mangle(ent) for ent in os.listdir('.')]
198 self.ents = [pathobj_mangle(ent) for ent in os.listdir('.')]
199 return self.ents
199 return self.ents
200 def __getattr__(self,name):
200 def __getattr__(self,name):
201 if name in self.ents:
201 if name in self.ents:
202 if self.path.endswith('/'):
202 if self.path.endswith('/'):
203 sep = ''
203 sep = ''
204 else:
204 else:
205 sep = '/'
205 sep = '/'
206
206
207 tgt = self.path + sep + pathobj_unmangle(name)
207 tgt = self.path + sep + pathobj_unmangle(name)
208 #print "tgt",tgt
208 #print "tgt",tgt
209 if os.path.isdir(tgt):
209 if os.path.isdir(tgt):
210 return PathObj(tgt)
210 return PathObj(tgt)
211 if os.path.isfile(tgt):
211 if os.path.isfile(tgt):
212 return path(tgt)
212 return path(tgt)
213
213
214 raise AttributeError, name # <<< DON'T FORGET THIS LINE !!
214 raise AttributeError, name # <<< DON'T FORGET THIS LINE !!
215 def __str__(self):
215 def __str__(self):
216 return self.path
216 return self.path
217
217
218 def __repr__(self):
218 def __repr__(self):
219 return "<PathObj to %s>" % self.path
219 return "<PathObj to %s>" % self.path
220
220
221 def __call__(self):
221 def __call__(self):
222 print "cd:",self.path
222 print "cd:",self.path
223 os.chdir(self.path)
223 os.chdir(self.path)
224
224
225 def complete_pathobj(obj, prev_completions):
225 def complete_pathobj(obj, prev_completions):
226
227 if hasattr(obj,'__complete__'):
226 if hasattr(obj,'__complete__'):
228 return obj.__complete__()
227 res = obj.__complete__()
228 if res:
229 return res
230 # just return normal attributes of 'path' object if the dir is empty
229 raise IPython.ipapi.TryNext
231 raise IPython.ipapi.TryNext
230
232
231 complete_pathobj = IPython.generics.complete_object.when_type(PathObj)(complete_pathobj)
233 complete_pathobj = IPython.generics.complete_object.when_type(PathObj)(complete_pathobj)
232
234
233 def test_pathobj():
235 def test_pathobj():
234 #p = PathObj('c:/prj')
236 #p = PathObj('c:/prj')
235 #p2 = p.cgi
237 #p2 = p.cgi
236 #print p,p2
238 #print p,p2
237 croot = PathObj("c:/")
239 rootdir = PathObj("/")
238 startmenu = PathObj("d:/Documents and Settings/All Users/Start Menu/Programs")
240 startmenu = PathObj("d:/Documents and Settings/All Users/Start Menu/Programs")
239 cwd = PathObj('.')
241 cwd = PathObj('.')
240 ip.to_user_ns("croot startmenu cwd")
242 ip.to_user_ns("rootdir startmenu cwd")
241
243
242 #test_pathobj() No newline at end of file
244 #test_pathobj()
General Comments 0
You need to be logged in to leave comments. Login now