download_data.py
Go to the documentation of this file.
00001 from __future__ import print_function
00002 
00003 import hashlib
00004 import os
00005 import os.path as osp
00006 import re
00007 import shlex
00008 import subprocess
00009 import shutil
00010 import sys
00011 import tarfile
00012 import zipfile
00013 
00014 import rosbag.rosbag_main
00015 import rospkg
00016 
00017 
00018 def extract_file(path, to_directory='.', chmod=True):
00019     print('[%s] Extracting to %s' % (path, to_directory))
00020     if path.endswith('.zip'):
00021         opener, mode, getnames = zipfile.ZipFile, 'r', lambda f: f.namelist()
00022     elif path.endswith('.tar.gz') or path.endswith('.tgz'):
00023         opener, mode, getnames = tarfile.open, 'r:gz', lambda f: f.getnames()
00024     elif path.endswith('.tar.bz2') or path.endswith('.tbz'):
00025         opener, mode, getnames = tarfile.open, 'r:bz2', lambda f: f.getnames()
00026     else:
00027         raise ValueError("Could not extract '%s' as no appropriate "
00028                          "extractor is found" % path)
00029 
00030     cwd = os.getcwd()
00031     os.chdir(to_directory)
00032     root_files = []
00033     try:
00034         file = opener(path, mode)
00035         try:
00036             file.extractall()
00037             if chmod:
00038                 for fname in getnames(file):
00039                     os.chmod(fname, 0777)
00040             root_files = list(set(name.split('/')[0]
00041                                   for name in getnames(file)))
00042         finally:
00043             file.close()
00044     finally:
00045         os.chdir(cwd)
00046     print('[%s] Finished extracting to %s' % (path, to_directory))
00047     return root_files
00048 
00049 
00050 def decompress_rosbag(path, quiet=False, chmod=True):
00051     print('[%s] Decompressing the rosbag' % path)
00052     argv = [path]
00053     if quiet:
00054         argv.append('--quiet')
00055     rosbag.rosbag_main.decompress_cmd(argv)
00056     if chmod:
00057         orig_path = osp.splitext(path)[0] + '.orig.bag'
00058         os.chmod(orig_path, 0777)
00059         os.chmod(path, 0777)
00060     print('[%s] Finished decompressing the rosbag' % path)
00061 
00062 
00063 def download(client, url, output, quiet=False, chmod=True):
00064     print('[%s] Downloading from %s' % (output, url))
00065     cmd = '{client} {url} -O {output}'.format(client=client, url=url,
00066                                               output=output)
00067     if quiet:
00068         cmd += ' --quiet'
00069     subprocess.call(shlex.split(cmd))
00070     if chmod:
00071         os.chmod(output, 0766)
00072     print('[%s] Finished downloading' % output)
00073 
00074 
00075 def check_md5sum(path, md5):
00076     # validate md5 string length if it is specified
00077     if md5 and len(md5) != 32:
00078         raise ValueError('md5 must be 32 charactors\n'
00079                          'actual: {} ({} charactors)'.format(md5, len(md5)))
00080     print('[%s] Checking md5sum (%s)' % (path, md5))
00081     is_same = hashlib.md5(open(path, 'rb').read()).hexdigest() == md5
00082     print('[%s] Finished checking md5sum' % path)
00083     return is_same
00084 
00085 
00086 def is_google_drive_url(url):
00087     m = re.match('^https?://drive.google.com/uc\?id=.*$', url)
00088     return m is not None
00089 
00090 
00091 def download_data(pkg_name, path, url, md5, download_client=None,
00092                   extract=False, compressed_bags=None, quiet=True, chmod=True):
00093     """Install test data checking md5 and rosbag decompress if needed.
00094        The downloaded data are located in cache_dir, and then linked to specified path.
00095        cache_dir is set by environment variable `JSK_DATA_CACHE_DIR` if defined, set by ROS_HOME/data otherwise."""
00096     if download_client is None:
00097         if is_google_drive_url(url):
00098             download_client = 'gdown'
00099         else:
00100             download_client = 'wget'
00101     if compressed_bags is None:
00102         compressed_bags = []
00103     if not osp.isabs(path):
00104         # get package path
00105         rp = rospkg.RosPack()
00106         try:
00107             pkg_path = rp.get_path(pkg_name)
00108         except rospkg.ResourceNotFound:
00109             print('\033[31m{name} is not found in {path}\033[0m'
00110                   .format(name=pkg_name, path=rp.list()))
00111             return
00112         pkg_path = rp.get_path(pkg_name)
00113         path = osp.join(pkg_path, path)
00114         if not osp.exists(osp.dirname(path)):
00115             try:
00116                 os.makedirs(osp.dirname(path))
00117             except OSError as e:
00118                 # can fail on running with multiprocess
00119                 if not osp.isdir(path):
00120                     raise
00121     # prepare cache dir
00122     if "JSK_DATA_CACHE_DIR" in os.environ:
00123         cache_root_dir = os.getenv("JSK_DATA_CACHE_DIR")
00124     else:
00125         cache_root_dir = osp.join(os.getenv('ROS_HOME', osp.expanduser('~/.ros')), "data")
00126     cache_dir = osp.join(cache_root_dir, pkg_name)
00127     if not osp.exists(cache_dir):
00128         try:
00129             os.makedirs(cache_dir)
00130         except OSError as e:
00131             # can fail on running with multiprocess
00132             if not osp.isdir(path):
00133                 raise
00134         if chmod:
00135             os.chmod(cache_dir, 0777)
00136     cache_file = osp.join(cache_dir, osp.basename(path))
00137     # check if cache exists, and update if necessary
00138     if not (osp.exists(cache_file) and check_md5sum(cache_file, md5)):
00139         if osp.exists(cache_file):
00140             os.remove(cache_file)
00141         download(download_client, url, cache_file, quiet=quiet, chmod=chmod)
00142     if osp.islink(path):
00143         # overwrite the link
00144         os.remove(path)
00145         os.symlink(cache_file, path)
00146     elif not osp.exists(path):
00147         os.symlink(cache_file, path)  # create link
00148     else:
00149         # not link and exists so skipping
00150         print('[%s] File exists, so skipping creating symlink.' % path,
00151               file=sys.stderr)
00152         return
00153     if extract:
00154         # extract files in cache dir and create symlink for them
00155         extracted_files = extract_file(cache_file, to_directory=cache_dir, chmod=True)
00156         for file_ in extracted_files:
00157             file_ = osp.join(cache_dir, file_)
00158             dst_path = osp.join(osp.split(path)[0], osp.basename(file_))
00159             if osp.islink(dst_path):
00160                 os.remove(dst_path)
00161             elif osp.exists(dst_path) and not osp.isdir(dst_path):
00162                 os.remove(dst_path)
00163             elif osp.exists(dst_path) and osp.isdir(dst_path):
00164                 shutil.rmtree(dst_path)
00165             os.symlink(file_, dst_path)
00166     for compressed_bag in compressed_bags:
00167         if not osp.isabs(compressed_bag):
00168             rp = rospkg.RosPack()
00169             pkg_path = rp.get_path(pkg_name)
00170             compressed_bag = osp.join(pkg_path, compressed_bag)
00171         decompress_rosbag(compressed_bag, quiet=quiet, chmod=chmod)


jsk_data
Author(s):
autogenerated on Fri Sep 8 2017 03:39:16