dataarchive.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import os
  2. import shutil
  3. from django.core.files import File
  4. from django.utils import timezone
  5. from django.utils.crypto import get_random_string
  6. from django.utils import six
  7. from misago.core.utils import slugify
  8. class DataArchive(object):
  9. def __init__(self, user, working_dir_path):
  10. self.user = user
  11. self.working_dir_path = working_dir_path
  12. self.tmp_dir_path = None
  13. self.data_dir_path = None
  14. self.file_path = None
  15. self.file = None
  16. def __enter__(self):
  17. self.tmp_dir_path = self.create_tmp_dir()
  18. self.data_dir_path = self.create_data_dir()
  19. return self
  20. def __exit__(self, *args):
  21. self.delete_file()
  22. self.delete_tmp_dir()
  23. def create_tmp_dir(self):
  24. tmp_dir_name = get_tmp_filename(self.user)
  25. tmp_dir_path = os.path.join(self.working_dir_path, tmp_dir_name)
  26. os.mkdir(tmp_dir_path)
  27. return tmp_dir_path
  28. def create_data_dir(self):
  29. data_dir_name = get_tmp_filename(self.user)
  30. data_dir_path = os.path.join(self.tmp_dir_path, data_dir_name)
  31. os.mkdir(data_dir_path)
  32. return data_dir_path
  33. def delete_tmp_dir(self):
  34. if self.tmp_dir_path:
  35. shutil.rmtree(self.tmp_dir_path)
  36. self.tmp_dir_path = None
  37. self.data_dir_path = None
  38. def get_file(self):
  39. file_name = get_tmp_filename(self.user)
  40. file_path = os.path.join(self.working_dir_path, file_name)
  41. self.file_path = shutil.make_archive(file_path, 'zip', self.tmp_dir_path)
  42. self.file = open(self.file_path, 'rb')
  43. return File(self.file)
  44. def delete_file(self):
  45. if self.file:
  46. self.file.close()
  47. self.file = None
  48. if self.file_path:
  49. os.remove(self.file_path)
  50. self.file_path = None
  51. def add_text(self, name, value, path=None):
  52. clean_filename = slugify(str(name))
  53. file_dir_path = self.make_path(path)
  54. file_path = os.path.join(file_dir_path, '{}.txt'.format(clean_filename))
  55. with open(file_path, 'w+') as fp:
  56. fp.write(six.text_type(value))
  57. return file_path
  58. def add_dict(self, name, value, path=None):
  59. text_lines = []
  60. for key, value in value.items():
  61. text_lines.append(u"{}: {}".format(key, value))
  62. text = u'\n'.join(text_lines)
  63. return self.add_text(name, text, path)
  64. def add_model_file(self, model_file, path=None):
  65. if not model_file:
  66. return None
  67. clean_filename = model_file.name.split('/')[-1]
  68. target_dir_path = self.make_path(path)
  69. target_path = os.path.join(target_dir_path, clean_filename)
  70. with open(target_path, 'wb') as fp:
  71. for chunk in model_file.chunks():
  72. fp.write(chunk)
  73. return target_path
  74. def make_path(self, path):
  75. # fixme: this can be simplified in py37k
  76. final_path = self.data_dir_path
  77. if not path:
  78. return final_path
  79. for path_item in path:
  80. final_path = os.path.join(final_path, six.text_type(path_item))
  81. if not os.path.isdir(final_path):
  82. os.mkdir(final_path)
  83. return final_path
  84. def get_tmp_filename(user):
  85. filename_bits = [
  86. user.slug,
  87. timezone.now().strftime('%Y%m%d-%H%M%S'),
  88. get_random_string(6),
  89. ]
  90. return '-'.join(filename_bits)