download.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. """Serves annotation related files for downloads.
  2. Author: Pontus Stenetorp <pontus stenetorp se>
  3. Version: 2011-10-03
  4. """
  5. from os import close as os_close
  6. from os import remove
  7. from os.path import join as path_join
  8. from os.path import basename, dirname, normpath
  9. from subprocess import Popen
  10. from tempfile import mkstemp
  11. from annotation import open_textfile
  12. from common import NoPrintJSONError
  13. from document import real_directory
  14. try:
  15. pass
  16. except ImportError:
  17. pass
  18. def download_file(document, collection, extension):
  19. directory = collection
  20. real_dir = real_directory(directory)
  21. fname = '%s.%s' % (document, extension)
  22. fpath = path_join(real_dir, fname)
  23. hdrs = [('Content-Type', 'text/plain; charset=utf-8'),
  24. ('Content-Disposition',
  25. 'inline; filename=%s' % fname)]
  26. with open_textfile(fpath, 'r') as txt_file:
  27. data = txt_file.read()
  28. raise NoPrintJSONError(hdrs, data)
  29. def find_in_directory_tree(directory, filename):
  30. # TODO: DRY; partial dup of projectconfig.py:__read_first_in_directory_tree
  31. try:
  32. from config import BASE_DIR
  33. except ImportError:
  34. BASE_DIR = "/"
  35. from os.path import split, join, exists
  36. depth = 0
  37. directory, BASE_DIR = normpath(directory), normpath(BASE_DIR)
  38. while BASE_DIR in directory:
  39. if exists(join(directory, filename)):
  40. return (directory, depth)
  41. directory = split(directory)[0]
  42. depth += 1
  43. return (None, None)
  44. def download_collection(collection, include_conf=False):
  45. directory = collection
  46. real_dir = real_directory(directory)
  47. dir_name = basename(dirname(real_dir))
  48. fname = '%s.%s' % (dir_name, 'tar.gz')
  49. confs = ['annotation.conf', 'visual.conf', 'tools.conf',
  50. 'kb_shortcuts.conf']
  51. try:
  52. include_conf = int(include_conf)
  53. except ValueError:
  54. pass
  55. tmp_file_path = None
  56. try:
  57. tmp_file_fh, tmp_file_path = mkstemp()
  58. os_close(tmp_file_fh)
  59. tar_cmd_split = ['tar', '--exclude=.stats_cache']
  60. conf_names = []
  61. if not include_conf:
  62. tar_cmd_split.extend(['--exclude=%s' % c for c in confs])
  63. else:
  64. # also include configs from parent directories.
  65. for cname in confs:
  66. cdir, depth = find_in_directory_tree(real_dir, cname)
  67. if depth is not None and depth > 0:
  68. relpath = path_join(
  69. dir_name, *['..' for _ in range(depth)])
  70. conf_names.append(path_join(relpath, cname))
  71. if conf_names:
  72. # replace pathname components ending in ".." with target
  73. # directory name so that .confs in parent directories appear
  74. # in the target directory in the tar.
  75. tar_cmd_split.extend(['--absolute-names', '--transform',
  76. 's|.*\\.\\.|%s|' % dir_name])
  77. tar_cmd_split.extend(['-c', '-z', '-f', tmp_file_path, dir_name])
  78. tar_cmd_split.extend(conf_names)
  79. tar_p = Popen(tar_cmd_split, cwd=path_join(real_dir, '..'))
  80. tar_p.wait()
  81. hdrs = [('Content-Type', 'application/octet-stream'), # 'application/x-tgz'),
  82. ('Content-Disposition', 'inline; filename=%s' % fname)]
  83. with open(tmp_file_path, 'rb') as tmp_file:
  84. tar_data = tmp_file.read()
  85. raise NoPrintJSONError(hdrs, tar_data)
  86. finally:
  87. if tmp_file_path is not None:
  88. remove(tmp_file_path)