importer.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import json
  2. import os
  3. from tempfile import TemporaryDirectory
  4. from zipfile import BadZipFile, ZipFile
  5. from django.utils.translation import gettext as _
  6. from ..models import Theme
  7. class ThemeImportError(BaseException):
  8. pass
  9. def import_theme(name, parent, zipfile):
  10. with TemporaryDirectory() as tmp_dir:
  11. extract_zipfile_to_tmp_dir(zipfile, tmp_dir)
  12. validate_zipfile_contains_single_directory(tmp_dir)
  13. theme_dir = os.path.join(tmp_dir, os.listdir(tmp_dir)[0])
  14. clean_data = clean_theme_contents(theme_dir)
  15. # TODO: finish import
  16. return Theme.objects.create(
  17. name=name or clean_data["name"],
  18. parent=parent,
  19. version=clean_data["version"],
  20. author=clean_data["author"],
  21. url=clean_data["url"],
  22. )
  23. def extract_zipfile_to_tmp_dir(zipfile, tmp_dir):
  24. try:
  25. ZipFile(zipfile).extractall(tmp_dir)
  26. except BadZipFile:
  27. raise ThemeImportError(_("Uploaded ZIP file could not be extracted."))
  28. def validate_zipfile_contains_single_directory(tmp_dir):
  29. dir_contents = os.listdir(tmp_dir)
  30. if not len(dir_contents):
  31. raise ThemeImportError(_("Uploaded ZIP file is empty."))
  32. if len(dir_contents) > 1:
  33. raise ThemeImportError(_("Uploaded ZIP file should contain single directory."))
  34. if not os.path.isdir(os.path.join(tmp_dir, dir_contents[0])):
  35. raise ThemeImportError(_("Uploaded ZIP file didn't contain a directory."))
  36. def clean_theme_contents(theme_dir):
  37. return read_manifest(theme_dir)
  38. def read_manifest(theme_dir):
  39. try:
  40. with open(os.path.join(theme_dir, "manifest.json")) as fp:
  41. manifest = json.load(fp)
  42. if not isinstance(manifest, dict):
  43. message = _(
  44. '"manifest.json" contained by ZIP file is not a valid '
  45. 'theme manifest file.'
  46. )
  47. raise ThemeImportError(message)
  48. except FileNotFoundError:
  49. raise ThemeImportError(
  50. _('Uploaded ZIP file didn\'t contain a "manifest.json".')
  51. )
  52. except json.decoder.JSONDecodeError:
  53. raise ThemeImportError(
  54. _('"manifest.json" contained by ZIP file is not a valid JSON file.')
  55. )
  56. else:
  57. return manifest