1b144271179aaf82cb1151e9dfd8e866747402594epoger#!/usr/bin/python 2b144271179aaf82cb1151e9dfd8e866747402594epoger 3b144271179aaf82cb1151e9dfd8e866747402594epoger""" 4b144271179aaf82cb1151e9dfd8e866747402594epogerCopyright 2014 Google Inc. 5b144271179aaf82cb1151e9dfd8e866747402594epoger 6b144271179aaf82cb1151e9dfd8e866747402594epogerUse of this source code is governed by a BSD-style license that can be 7b144271179aaf82cb1151e9dfd8e866747402594epogerfound in the LICENSE file. 8b144271179aaf82cb1151e9dfd8e866747402594epoger 9b144271179aaf82cb1151e9dfd8e866747402594epogerUtilities for working with URLs. 10b144271179aaf82cb1151e9dfd8e866747402594epoger 11b144271179aaf82cb1151e9dfd8e866747402594epogerTODO(epoger): move this into tools/utils for broader use? 12b144271179aaf82cb1151e9dfd8e866747402594epoger""" 13b144271179aaf82cb1151e9dfd8e866747402594epoger 14b144271179aaf82cb1151e9dfd8e866747402594epoger# System-level imports 15b144271179aaf82cb1151e9dfd8e866747402594epogerimport contextlib 16b144271179aaf82cb1151e9dfd8e866747402594epogerimport os 17b144271179aaf82cb1151e9dfd8e866747402594epogerimport shutil 18b144271179aaf82cb1151e9dfd8e866747402594epogerimport urllib 19b144271179aaf82cb1151e9dfd8e866747402594epogerimport urlparse 20b144271179aaf82cb1151e9dfd8e866747402594epoger 21b144271179aaf82cb1151e9dfd8e866747402594epoger 22b144271179aaf82cb1151e9dfd8e866747402594epogerdef create_filepath_url(filepath): 23b144271179aaf82cb1151e9dfd8e866747402594epoger """ Returns a file:/// URL pointing at the given filepath on local disk. 24b144271179aaf82cb1151e9dfd8e866747402594epoger 25b144271179aaf82cb1151e9dfd8e866747402594epoger Args: 26b144271179aaf82cb1151e9dfd8e866747402594epoger filepath: string; path to a file on local disk (may be absolute or relative, 27b144271179aaf82cb1151e9dfd8e866747402594epoger and the file does not need to exist) 28b144271179aaf82cb1151e9dfd8e866747402594epoger 29b144271179aaf82cb1151e9dfd8e866747402594epoger Returns: 30b144271179aaf82cb1151e9dfd8e866747402594epoger A file:/// URL pointing at the file. Regardless of whether filepath was 31b144271179aaf82cb1151e9dfd8e866747402594epoger specified as a relative or absolute path, the URL will contain an 32b144271179aaf82cb1151e9dfd8e866747402594epoger absolute path to the file. 33b144271179aaf82cb1151e9dfd8e866747402594epoger 34b144271179aaf82cb1151e9dfd8e866747402594epoger Raises: 35b144271179aaf82cb1151e9dfd8e866747402594epoger An Exception, if filepath is already a URL. 36b144271179aaf82cb1151e9dfd8e866747402594epoger """ 37b144271179aaf82cb1151e9dfd8e866747402594epoger if urlparse.urlparse(filepath).scheme: 38b144271179aaf82cb1151e9dfd8e866747402594epoger raise Exception('"%s" is already a URL' % filepath) 39b144271179aaf82cb1151e9dfd8e866747402594epoger return urlparse.urljoin( 40b144271179aaf82cb1151e9dfd8e866747402594epoger 'file:', urllib.pathname2url(os.path.abspath(filepath))) 41b144271179aaf82cb1151e9dfd8e866747402594epoger 42b144271179aaf82cb1151e9dfd8e866747402594epoger 43b144271179aaf82cb1151e9dfd8e866747402594epogerdef copy_contents(source_url, dest_path, create_subdirs_if_needed=False): 44b144271179aaf82cb1151e9dfd8e866747402594epoger """ Copies the full contents of the URL 'source_url' into 45b144271179aaf82cb1151e9dfd8e866747402594epoger filepath 'dest_path'. 46b144271179aaf82cb1151e9dfd8e866747402594epoger 47b144271179aaf82cb1151e9dfd8e866747402594epoger Args: 48b144271179aaf82cb1151e9dfd8e866747402594epoger source_url: string; complete URL to read from 49b144271179aaf82cb1151e9dfd8e866747402594epoger dest_path: string; complete filepath to write to (may be absolute or 50b144271179aaf82cb1151e9dfd8e866747402594epoger relative) 51b144271179aaf82cb1151e9dfd8e866747402594epoger create_subdirs_if_needed: boolean; whether to create subdirectories as 52b144271179aaf82cb1151e9dfd8e866747402594epoger needed to create dest_path 53b144271179aaf82cb1151e9dfd8e866747402594epoger 54b144271179aaf82cb1151e9dfd8e866747402594epoger Raises: 55b144271179aaf82cb1151e9dfd8e866747402594epoger Some subclass of Exception if unable to read source_url or write dest_path. 56b144271179aaf82cb1151e9dfd8e866747402594epoger """ 57b144271179aaf82cb1151e9dfd8e866747402594epoger if create_subdirs_if_needed: 58b144271179aaf82cb1151e9dfd8e866747402594epoger dest_dir = os.path.dirname(dest_path) 59b144271179aaf82cb1151e9dfd8e866747402594epoger if not os.path.exists(dest_dir): 60b144271179aaf82cb1151e9dfd8e866747402594epoger os.makedirs(dest_dir) 61b144271179aaf82cb1151e9dfd8e866747402594epoger with contextlib.closing(urllib.urlopen(source_url)) as source_handle: 62b144271179aaf82cb1151e9dfd8e866747402594epoger with open(dest_path, 'wb') as dest_handle: 63b144271179aaf82cb1151e9dfd8e866747402594epoger shutil.copyfileobj(fsrc=source_handle, fdst=dest_handle) 64