summaryrefslogtreecommitdiffstats
path: root/platform_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'platform_utils.py')
-rw-r--r--platform_utils.py43
1 files changed, 43 insertions, 0 deletions
diff --git a/platform_utils.py b/platform_utils.py
index 1c719b1d..f4dfa0b1 100644
--- a/platform_utils.py
+++ b/platform_utils.py
@@ -167,3 +167,46 @@ class _FileDescriptorStreamsThreads(FileDescriptorStreams):
167 self.queue.put(_FileDescriptorStreamsThreads.QueueItem(self, line)) 167 self.queue.put(_FileDescriptorStreamsThreads.QueueItem(self, line))
168 self.fd.close() 168 self.fd.close()
169 self.queue.put(_FileDescriptorStreamsThreads.QueueItem(self, None)) 169 self.queue.put(_FileDescriptorStreamsThreads.QueueItem(self, None))
170
171
172def symlink(source, link_name):
173 """Creates a symbolic link pointing to source named link_name.
174 Note: On Windows, source must exist on disk, as the implementation needs
175 to know whether to create a "File" or a "Directory" symbolic link.
176 """
177 if isWindows():
178 import platform_utils_win32
179 source = _validate_winpath(source)
180 link_name = _validate_winpath(link_name)
181 target = os.path.join(os.path.dirname(link_name), source)
182 if os.path.isdir(target):
183 platform_utils_win32.create_dirsymlink(source, link_name)
184 else:
185 platform_utils_win32.create_filesymlink(source, link_name)
186 else:
187 return os.symlink(source, link_name)
188
189
190def _validate_winpath(path):
191 path = os.path.normpath(path)
192 if _winpath_is_valid(path):
193 return path
194 raise ValueError("Path \"%s\" must be a relative path or an absolute "
195 "path starting with a drive letter".format(path))
196
197
198def _winpath_is_valid(path):
199 """Windows only: returns True if path is relative (e.g. ".\\foo") or is
200 absolute including a drive letter (e.g. "c:\\foo"). Returns False if path
201 is ambiguous (e.g. "x:foo" or "\\foo").
202 """
203 assert isWindows()
204 path = os.path.normpath(path)
205 drive, tail = os.path.splitdrive(path)
206 if tail:
207 if not drive:
208 return tail[0] != os.sep # "\\foo" is invalid
209 else:
210 return tail[0] == os.sep # "x:foo" is invalid
211 else:
212 return not drive # "x:" is invalid