/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Lib/fileutil.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/Lib/fileutil.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2734 - (show annotations)
Thu Mar 1 12:42:59 2007 UTC (18 years ago) by bramz
File MIME type: text/x-python
File size: 7967 byte(s)
made a copy
1 # Copyright (c) 2001, 2002 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 #
5 # This program is free software under the GPL (>=v2)
6 # Read the file COPYING coming with Thuban for details.
7
8 """
9 Functions to deal with filenames
10 """
11
12 __version__ = "$Revision$"
13
14 import os
15 import os.path
16 from tempfile import mktemp
17
18 from string import join
19
20 from Thuban import _
21
22 def relative_filename_common(dir, absname, sep):
23 """Return a filename relative to dir for the absolute file name absname.
24 This is part the posix and nt versions have in common. Both dir and
25 absname are assumed to be normalized (as done with os.normpath)
26 absolute filenames without drive letters. sep is the platform
27 specific directory separator.
28 """
29
30 # split the filenames into their components. remove the first item
31 # since it will be always empty because both names are absolute.
32 dir_parts = dir.split(sep)[1:]
33 absname_parts = absname.split(sep)[1:]
34
35 # count the number of common parts at the start of dir_parts and
36 # absname_parts
37 max_common = min(len(dir_parts), len(absname_parts))
38 common = 0
39 while common < max_common and dir_parts[common] == absname_parts[common]:
40 common = common + 1
41
42 # If the common part is the root directory, return absname
43 if common == 0:
44 return absname
45
46 # for each directory under the common part prepend a '..'.
47 rel_parts = (len(dir_parts) - common) * ['..'] + absname_parts[common:]
48 return join(rel_parts, sep)
49
50
51 def relative_filename_posix(dir, absname):
52 """Return a filename relative to dir for the absolute file name absname.
53
54 If absname is already a relative filename, return it unchanged. If
55 the common directory of dir and absname is /, return absname
56 unchanged. If dir is not an absolute name, raise TypeError.
57
58 This is the posix specific version of relative_filename.
59
60 Example:
61 >>> from fileutil import relative_filename_posix
62 >>> relative_filename_posix("/usr/local/lib/", "/usr/local/lib/python")
63 'python'
64 >>> relative_filename_posix("/usr/local/lib/", "/usr/local/bin/python")
65 '../bin/python'
66 >>> relative_filename_posix("/usr/local/lib/", "/usr/bin/python")
67 '../../bin/python'
68 >>> relative_filename_posix("/usr/local/lib/", "/var/spool/mail")
69 '/var/spool/mail'
70 >>> relative_filename_posix("/home/", "xyzzy")
71 'xyzzy'
72 >>> relative_filename_posix("home/", "/xyzzy")
73 Traceback (most recent call last):
74 File "<stdin>", line 1, in ?
75 File "fileutil.py", line 42, in relative_filename_posix
76 raise TypeError("first argument must be an absolute filename")
77 TypeError: first argument must be an absolute filename
78 """
79 # for posix, the common part does exactly what we need, except for
80 # the special cases and input checking. Import posixpath explicitly
81 # for that to faciliate testing
82 import posixpath
83 if not posixpath.isabs(absname):
84 return absname
85
86 if not posixpath.isabs(dir):
87 raise TypeError(_("first argument must be an absolute filename"))
88
89 dir = posixpath.normpath(dir)
90 absname = posixpath.normpath(absname)
91
92 return relative_filename_common(dir, absname, "/")
93
94 def relative_filename_nt(dir, absname):
95 r"""Return a filename relative to dir for the absolute file name absname.
96
97 If absname is already a relative filename or if dir and absname are
98 on different drives, return absname. If the common directory of dir
99 and absname is the drive's root directory, return absname. If dir is
100 not an absolute name or either name doesn't have a drive letter,
101 raise TypeError.
102
103 This is the nt specific version of relative_filename.
104
105 Example:
106 >>> from fileutil import relative_filename_nt
107 >>> relative_filename_nt(r"C:\Programme\Python", r"C:\Programme\Thuban")
108 '..\\Thuban'
109 >>> relative_filename_nt(r"C:\Programme\Python", r"D:\Programme\Thuban")
110 'D:\\Programme\\Thuban'
111 >>> relative_filename_nt(r"C:\Programme\Python", r"C:Programme")
112 'C:Programme'
113 >>> relative_filename_nt(r"C:Programme\Python", r"C:Programme")
114 Traceback (most recent call last):
115 File "<stdin>", line 1, in ?
116 File "fileutil.py", line 123, in relative_filename_nt
117 raise TypeError("first argument must be an absolute filename")
118 TypeError: first argument must be an absolute filename
119 >>> relative_filename_nt(r"\Programme\Python", r"\Programme")
120 Traceback (most recent call last):
121 File "<stdin>", line 1, in ?
122 File "fileutil.py", line 120, in relative_filename_nt
123 raise TypeError("Both parameters must have a drive letter")
124 TypeError: Both parameters must have a drive letter
125 """
126 # first check the parameters. Imort ntpath directly to facilitate
127 # testing on non-nt systems.
128 import ntpath
129
130 dir = ntpath.normpath(dir)
131 absname = ntpath.normpath(absname)
132
133 dir_drive, dir_rest = ntpath.splitdrive(dir)
134 absname_drive, absname_rest = ntpath.splitdrive(absname)
135 #print dir_drive, dir_rest
136 #print absname_drive, absname_rest
137 if not dir_drive or not absname_drive:
138 raise TypeError(_("Both parameters must have a drive letter"))
139
140 if not ntpath.isabs(dir_rest):
141 raise TypeError(_("first argument must be an absolute filename"))
142
143 # handle some special cases
144 if not ntpath.isabs(absname_rest):
145 return absname
146
147 if dir_drive != absname_drive:
148 return absname
149
150 # Now both dir_rest and absname_rest are absolute filenames without
151 # drive letter. We can now use the common part to determine the
152 # relative name
153 return relative_filename_common(dir_rest, absname_rest, "\\")
154
155 def get_application_dir():
156 """Determine the path to the .thuban directory. Create the directory
157 if it doesn't exist.
158
159 Under posix systems use the os.expanduser() method.
160 Under Win32 try to read the "Explorer/Shell Folders/" value "AppData".
161 """
162
163 if os.name == 'posix':
164 dir = os.path.expanduser("~/.thuban")
165 if not os.path.isdir(dir):
166 os.mkdir(dir)
167 return dir
168 elif os.name == 'nt':
169 regkey = 1
170 try:
171 import _winreg as wreg
172 except ImportError:
173 regkey = 0
174
175 if regkey:
176 try:
177 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
178 "Software\\Microsoft\\Windows\\CurrentVersion\\"\
179 "Explorer\\Shell Folders")
180 dir = wreg.QueryValueEx(key, "AppData")[0]
181 dir = os.path.join(dir, "thuban")
182 except:
183 regkey = 0
184
185 if not regkey:
186 # The fallback. This should result in something like the
187 # user directory ...
188 guess = os.path.dirname(
189 os.path.dirname(os.path.dirname(mktemp()))
190 )
191 dir = os.path.join(guess, "thuban")
192 if not os.path.isdir(dir):
193 os.mkdir(dir)
194
195 return dir
196
197 else:
198 raise RuntimeError(_("No implementation of get_application_dir"
199 " available for platform") + os.name)
200
201 # bind the appropriate version of relative_filename for the platform
202 # we're currently running on.
203 if os.name == "posix":
204 relative_filename = relative_filename_posix
205 elif os.name == "nt":
206 relative_filename = relative_filename_nt
207 else:
208 raise RuntimeError(_("No implementation of relative_filename"
209 " available for platform") + os.name)
210
211 __test__ = {"relative_filename_posix": relative_filename_posix,
212 "relative_filename_nt": relative_filename_nt}
213
214 # if run as a script, run doctest
215 def _test():
216 import doctest, fileutil
217 # Pass an isprivate function that always returns true so that only
218 # items in __test__ are tested
219 return doctest.testmod(fileutil, isprivate = lambda *args: 1)
220
221 if __name__ == "__main__":
222 _test()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26