]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/ide/activegrid/util/fileutils.py
Tweaks for demos on MacOSX
[wxWidgets.git] / wxPython / samples / ide / activegrid / util / fileutils.py
1 #----------------------------------------------------------------------------
2 # Name: fileutils.py
3 # Purpose: Active grid miscellaneous utilities
4 #
5 # Author: Jeff Norton
6 #
7 # Created: 12/10/04
8 # CVS-ID: $Id$
9 # Copyright: (c) 2004-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
12
13 import logging
14 import copy
15 import os
16 import shutil
17 import sys
18 import zipfile
19
20 import activegrid.util.aglogging as aglogging
21 import activegrid.util.sysutils as sysutils
22 from activegrid.util.lang import *
23
24 global fileutilsLogger
25 fileutilsLogger = logging.getLogger("activegrid.util.fileutils")
26 # FATAL : No logging
27 # ERROR : No logging
28 # WARN : No logging
29 # INFO : No logging
30 # DEBUG : debugging
31 aglogging.setLevelFatal(fileutilsLogger)
32 #logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))
33
34
35 def makeDirsForFile(filename):
36 d = os.path.dirname(filename)
37 if (not os.path.exists(d)):
38 os.makedirs(d)
39
40 def createFile(filename, mode='w'):
41 f = None
42 if (not os.path.exists(filename)):
43 makeDirsForFile(filename)
44 f = file(filename, mode)
45 return f
46
47 def compareFiles(file1, file2):
48 ## result = filecmp.cmp(file1, file2)
49 ## if result:
50 ## return 0
51 ## return -1
52 file1.seek(0)
53 file2.seek(0)
54 while True:
55 line1 = file1.readline()
56 line2 = file2.readline()
57 if (len(line1) == 0):
58 if (len(line2) == 0):
59 return 0
60 else:
61 return -1
62 elif (len(line2) == 0):
63 return -1
64 elif (line1 != line2):
65 line1 = line1.replace(" ", "")
66 line2 = line2.replace(" ", "")
67 if (line1 != line2):
68 len1 = len(line1)
69 len2 = len(line2)
70 if ((abs(len1 - len2) == 1) and (len1 > 0) and (len2 > 0)
71 and (line1[-1] == "\n") and (line2[-1] == "\n")):
72 if (len1 > len2):
73 longer = line1
74 shorter = line2
75 else:
76 shorter = line1
77 longer = line2
78 if ((longer[-2] == "\r") and (longer[:-2] == shorter[:-1])):
79 continue
80 if ((longer[-2:] == shorter[-2:]) and (longer[-3] == "\r") and (longer[:-3] == shorter[:-2])):
81 continue
82 return -1
83
84 def expandVars(value):
85 """Syntax: ${myvar,default="default value"}"""
86 import activegrid.runtime as runtime
87 sx = value.find("${")
88 if (sx >= 0):
89 result = asString(value[:sx])
90 endx = value.find("}")
91 if (endx > 1):
92 defaultValue = None
93 defsx = value.find(",default=\"")
94 if ((defsx > sx) and (defsx < endx)):
95 varname = value[sx+2:defsx]
96 if (value[endx-1] == '"'):
97 defaultValue = value[defsx+10:endx-1]
98 if (defaultValue == None):
99 varname = value[sx+2:endx]
100 if (varname == "AG_SYSTEM"):
101 varval = runtime.appInfo.getSystemDir()
102 elif (varname == "AG_SYSTEM_STATIC"):
103 varval = runtime.appInfo.getSystemStaticDir()
104 elif (varname == "AG_APP"):
105 varval = runtime.appInfo.getAppDir()
106 elif (varname == "AG_APP_STATIC"):
107 varval = runtime.appInfo.getAppStaticDir()
108 else:
109 varval = os.getenv(varname)
110 if ((varval == None) and (defaultValue != None)):
111 varval = defaultValue
112 if (varval == None):
113 result += value[sx:endx+1]
114 else:
115 result += varval
116 return result + expandVars(value[endx+1:])
117 return value
118
119 def toPHPpath(path, otherdir=None):
120 return convertSourcePath(path, "php", otherdir=otherdir)
121
122 def toPythonpath(path, otherdir=None):
123 return convertSourcePath(path, "python", otherdir=otherdir)
124
125 def toUnixPath(path):
126 if (path != None and os.sep != '/'):
127 path = path.replace(os.sep, '/')
128 return path
129
130 def convertSourcePath(path, to, otherdir=None):
131 fromname = "python"
132 if (to == "python"):
133 fromname = "php"
134 pythonNode = os.sep + fromname + os.sep
135 ix = path.find(pythonNode)
136 if (ix < 0):
137 ix = path.find(fromname) - 1
138 if ((ix < 0) or (len(path) <= ix+7)
139 or (path[ix] not in ("\\", "/")) or (path[ix+7] not in ("\\", "/"))):
140 raise Exception("Not in a %s source tree. Cannot create file name for %s." % (fromname, path))
141 if (otherdir == None):
142 return path[:ix+1] + to + path[ix+7:]
143 else:
144 return otherdir + path[ix+7:]
145 if (otherdir == None):
146 return path.replace(pythonNode, os.sep + to + os.sep)
147 else:
148 return otherdir + path[ix+7:]
149
150
151 def visit(directory, files, extension):
152 testdirs = os.listdir(directory)
153 for thing in testdirs:
154 fullpath = os.path.join(directory, thing)
155 if (os.path.isdir(fullpath)):
156 visit(fullpath, files, extension)
157 elif thing.endswith(extension):
158 fullname = os.path.normpath(os.path.join(directory, thing))
159 if not fullname in files:
160 files.append(fullname)
161
162 def listFilesByExtensionInPath(path=[], extension='.lyt'):
163 #Collect input and output arguments into one bunch
164 retval = []
165 for directory in path:
166 visit(directory, retval, extension)
167 return retval
168
169 def getFileLastModificationTime(fileName):
170 return os.path.getmtime(fileName)
171
172 def findFileLocation(location, fileName):
173 i = fileName.rfind(os.sep)
174 if i > 0:
175 fileName = fileName[:i]
176 while location[0:2] == '..' and location[2:3] == os.sep:
177 location = location[3:]
178 i = fileName.rfind(os.sep)
179 fileName = fileName[:i]
180 absPath = fileName + os.sep + location
181 return absPath
182
183 def getAllExistingFiles(files, basepath=None, forceForwardSlashes=False):
184 """For each file in files, if it exists, adds its absolute path to the rtn list. If file is a dir, calls this function recursively on all child files in the dir.
185 If basepath is set, and if the file being processed is relative to basedir, adds that relative path to rtn list instead of the abs path.
186 Is this is Windows, and forceForwardSlashes is True, make sure returned paths only have forward slashes."""
187 if isinstance(files, basestring):
188 files = [files]
189 rtn = []
190 for file in files:
191 if os.path.exists(file):
192 if os.path.isfile(file):
193 if basepath and hasAncestorDir(file, basepath):
194 rtn.append(getRelativePath(file, basepath))
195 else:
196 rtn.append(os.path.abspath(str(file)))
197 elif os.path.isdir(file):
198 dircontent = [os.path.join(file, f) for f in os.listdir(file)]
199 rtn.extend(getAllExistingFiles(dircontent, basepath))
200
201 if forceForwardSlashes and sysutils.isWindows():
202 newRtn = []
203 for f in rtn:
204 newRtn.append(f.replace("\\", "/"))
205 rtn = newRtn
206
207 return rtn
208
209 def hasAncestorDir(file, parent):
210 """Returns true if file has the dir 'parent' as some parent in its path."""
211 return getRelativePath(file, parent) != None
212
213 def getRelativePath(file, basedir):
214 """Returns relative path from 'basedir' to 'file', assuming 'file' lives beneath 'basedir'. If it doesn't, returns None."""
215 file = os.path.abspath(file)
216 parent = os.path.abspath(basedir)
217
218 if file == parent:
219 return None
220
221 if file.startswith(parent):
222 return file[len(parent)+1:]
223
224 return None
225
226 def isEmptyDir(dir):
227 if not os.path.isdir(dir):
228 return False
229 return len(os.listdir(dir)) == 0
230
231 ifDefPy()
232 def zip(zipfilepath, basedir=None, files=None):
233 """Zip all files in files and save zip as zipfilepath. If files is None, zip all files in basedir. For all files to be zipped, if they are relative to basedir, include the relative path in the archive."""
234
235 if not files and not basedir:
236 raise AssertionError("Either 'basedir' or 'files' must be set")
237
238 if not files:
239 aglogging.debug(fileutilsLogger,\
240 "Looking for files to zip in %s" % basedir)
241 files = getAllExistingFiles(basedir)
242 else:
243 # removes files that don't exist and gets abs for each
244 files = getAllExistingFiles(files)
245
246 if len(files) == 0:
247 aglogging.debug(fileutilsLogger, "No files to zip, nothing to do")
248 return
249
250 z = zipfile.ZipFile(zipfilepath, mode="w", compression=zipfile.ZIP_DEFLATED)
251
252 try:
253 for file in files:
254 arcname = None
255 if basedir:
256 arcname = getRelativePath(file, basedir)
257 if not arcname:
258 arcname = file
259 aglogging.debug(fileutilsLogger,\
260 "%s: adding %s with arcname %s" %\
261 (zipfilepath, file, arcname))
262 z.write(file, arcname)
263 finally:
264 z.close()
265 endIfDef()
266
267
268 ifDefPy()
269 def unzip(zipfilepath, extractdir):
270 """Unzip zipfilepath into extractdir."""
271 z = zipfile.ZipFile(zipfilepath, mode="r")
272 for info in z.infolist():
273 filename = os.path.join(extractdir, info.filename)
274 try:
275 dir = os.path.dirname(filename)
276 aglogging.debug(fileutilsLogger, "Creating dir %s" % dir)
277 os.makedirs(dir) # do we have to worry about permissions?
278 except:
279 pass
280 if os.path.isdir(filename):
281 continue
282 aglogging.debug(fileutilsLogger,\
283 ("Writing arcfile %s to %s" % (info.filename, filename)))
284 f = open(filename, "w")
285 f.write(z.read(info.filename))
286 f.close()
287 endIfDef()
288
289 ifDefPy()
290 def copyFile(src, dest):
291 """Copies file src to dest. Creates directories in 'dest' path if necessary."""
292 destdir = os.path.dirname(dest)
293 if not os.path.exists(destdir):
294 os.makedirs(destdir)
295 shutil.copy(src, dest)
296 endIfDef()
297
298 ifDefPy()
299 def copyDir(src, dest):
300 """Copies dir 'src' into dir 'dest'. Creates 'dest' if it does not exist."""
301 shutil.copytree(src, dest)
302 endIfDef()
303
304 ifDefPy()
305 def remove(file):
306 if not os.path.exists(file):
307 return
308 if os.path.isfile(file):
309 os.remove(file)
310 elif os.path.isdir(file):
311 shutil.rmtree(file)
312 endIfDef()
313
314 ifDefPy()
315 import warnings
316 warnings.filterwarnings("ignore", message="tmpnam is a potential security risk to your program")
317 def getTmpFile():
318 return os.tmpnam()
319 endIfDef()
320
321 ifDefPy()
322 #@accepts str, dict, str, str, boolean
323 def replaceToken(infilepath, tokens={}, outfilepath=None, delim="@@",\
324 useEnv=False):
325 """Replaces tokens of form 'delim'<tokenname>'delim' in file at 'infilepath', using values in dict 'tokens'. If 'outfilepath' is set, writes output to 'outfilepath', if not set, overwrites original file. If 'useEnv' is True, adds os.environ to 'tokens'. This makes it possible to define an env var FOO=BLAH, and have @@FOO@@ be replaced with BLAH, without explicitly passing FOO=BLAH in 'tokens'. Note that entries in 'tokens' take precedence over entries in os.environ."""
326
327 if useEnv:
328 for key, val in os.environ.items():
329 # passed in tokens take precedence
330 if not tokens.has_key(key):
331 tokens[key] = val
332
333 f = open(infilepath, "r")
334 try:
335 content = f.read()
336 finally:
337 if f: f.close()
338
339 for token, value in tokens.items():
340 content = content.replace("%s%s%s" % (delim, token , delim), str(value))
341
342 if not outfilepath: outfilepath = infilepath
343 f = open(outfilepath, "w")
344 try:
345 f.write(content)
346 finally:
347 if f: f.close()
348 endIfDef()