OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 |
| 3 """ |
| 4 Copyright 2014 Google Inc. |
| 5 |
| 6 Use of this source code is governed by a BSD-style license that can be |
| 7 found in the LICENSE file. |
| 8 |
| 9 Utility module for handling paths that may be either URL paths or local |
| 10 filepaths. |
| 11 |
| 12 TODO(epoger): Move this module to some common place so we can use it more widely |
| 13 """ |
| 14 |
| 15 # System-level imports |
| 16 import contextlib |
| 17 import os |
| 18 import posixpath |
| 19 import shutil |
| 20 import urllib |
| 21 import urllib2 |
| 22 import urlparse |
| 23 |
| 24 def is_url(path): |
| 25 """ Returns true if path looks like a URL. """ |
| 26 return True if urlparse.urlparse(path).scheme else False |
| 27 |
| 28 def join(first, *remaining): |
| 29 """ Joins two or more URL or pathname components. If the first component |
| 30 looks like a valid URL, we assemble a URL; otherwise, we assemble it as |
| 31 a pathname to a local file. |
| 32 |
| 33 Args: |
| 34 first: string; first component of the URL/path |
| 35 remaining: variable number of strings; remaining URL/path components |
| 36 |
| 37 Returns: |
| 38 The complete URL or filename path. |
| 39 """ |
| 40 if is_url(first): |
| 41 return posixpath.join(first, *remaining) |
| 42 else: |
| 43 return os.path.join(first, *remaining) |
| 44 |
| 45 def create_filepath_url(filepath): |
| 46 """ Returns a file:/// URL pointing at the given filepath on local disk. |
| 47 |
| 48 Args: |
| 49 filepath: string; path to a file on local disk (may be absolute or relative, |
| 50 and the file does not need to exist) |
| 51 |
| 52 Returns: |
| 53 A file:/// URL pointing at the file. Regardless of whether filepath was |
| 54 specified as a relative or absolute path, the URL will contain an |
| 55 absolute path to the file. |
| 56 |
| 57 Raises: |
| 58 An Exception, if filepath is already a URL. |
| 59 """ |
| 60 if is_url(filepath): |
| 61 raise Exception('"%s" is already a URL' % filepath) |
| 62 return urlparse.urljoin( |
| 63 'file:', urllib.pathname2url(os.path.abspath(filepath))) |
| 64 |
| 65 def read_as_string(path): |
| 66 """ Reads in the full contents of the URL or filepath 'path', returning those |
| 67 contents as a single string. |
| 68 |
| 69 Args: |
| 70 path: string; complete URL or filepath (if filepath, may be absolute or |
| 71 relative) |
| 72 |
| 73 Returns: |
| 74 Complete contents of the URL or filepath as a string. |
| 75 |
| 76 Raises: |
| 77 Some subclass of Exception if unable to read the contents (URL/file not |
| 78 found, etc.) |
| 79 """ |
| 80 if is_url(path): |
| 81 try: |
| 82 return urllib2.urlopen(path).read() |
| 83 except Exception, e: |
| 84 e.msg += ' for URL ' + path |
| 85 raise |
| 86 else: |
| 87 return open(path, 'r').read() |
| 88 |
| 89 def copy_contents(source_path, dest_path, create_subdirs_if_needed=False): |
| 90 """ Copies the full contents of the URL or filepath 'source_path' into |
| 91 filepath 'dest_path'. |
| 92 |
| 93 Args: |
| 94 source_path: string; complete URL or filepath to read from (if filepath, |
| 95 may be absolute or relative) |
| 96 dest_path: string; complete filepath to write to (may be absolute or |
| 97 relative) |
| 98 create_subdirs_if_needed: boolean; whether to create subdirectories as |
| 99 needed to create dest_path |
| 100 |
| 101 Raises: |
| 102 Some subclass of Exception if unable to read source_path (URL/file not |
| 103 found, etc.) or write dest_path. |
| 104 """ |
| 105 if create_subdirs_if_needed: |
| 106 dest_dir = os.path.dirname(dest_path) |
| 107 if not os.path.exists(dest_dir): |
| 108 os.makedirs(dest_dir) |
| 109 if is_url(source_path): |
| 110 with contextlib.closing(urllib.urlopen(source_path)) as source_handle: |
| 111 with open(dest_path, 'wb') as dest_handle: |
| 112 shutil.copyfileobj(fsrc=source_handle, fdst=dest_handle) |
| 113 else: |
| 114 shutil.copyfile(source_path, dest_path) |
OLD | NEW |