|
@@ -1,13 +1,72 @@
|
|
|
+import json
|
|
|
+import os
|
|
|
from tempfile import TemporaryDirectory
|
|
|
+from zipfile import BadZipFile, ZipFile
|
|
|
|
|
|
from django.utils.translation import gettext as _
|
|
|
|
|
|
+from ..models import Theme
|
|
|
+
|
|
|
|
|
|
class ThemeImportError(BaseException):
|
|
|
pass
|
|
|
|
|
|
|
|
|
-def import_theme(name, zipfile):
|
|
|
+def import_theme(name, parent, zipfile):
|
|
|
with TemporaryDirectory() as tmp_dir:
|
|
|
- pass
|
|
|
+ extract_zipfile_to_tmp_dir(zipfile, tmp_dir)
|
|
|
+ validate_zipfile_contains_single_directory(tmp_dir)
|
|
|
+ theme_dir = os.path.join(tmp_dir, os.listdir(tmp_dir)[0])
|
|
|
+ clean_data = clean_theme_contents(theme_dir)
|
|
|
+
|
|
|
+ # TODO: finish import
|
|
|
+ return Theme.objects.create(
|
|
|
+ name=name or clean_data["name"],
|
|
|
+ parent=parent,
|
|
|
+ version=clean_data["version"],
|
|
|
+ author=clean_data["author"],
|
|
|
+ url=clean_data["url"],
|
|
|
+ )
|
|
|
|
|
|
+
|
|
|
+def extract_zipfile_to_tmp_dir(zipfile, tmp_dir):
|
|
|
+ try:
|
|
|
+ ZipFile(zipfile).extractall(tmp_dir)
|
|
|
+ except BadZipFile:
|
|
|
+ raise ThemeImportError(_("Uploaded ZIP file could not be extracted."))
|
|
|
+
|
|
|
+
|
|
|
+def validate_zipfile_contains_single_directory(tmp_dir):
|
|
|
+ dir_contents = os.listdir(tmp_dir)
|
|
|
+ if not len(dir_contents):
|
|
|
+ raise ThemeImportError(_("Uploaded ZIP file is empty."))
|
|
|
+ if len(dir_contents) > 1:
|
|
|
+ raise ThemeImportError(_("Uploaded ZIP file should contain single directory."))
|
|
|
+ if not os.path.isdir(os.path.join(tmp_dir, dir_contents[0])):
|
|
|
+ raise ThemeImportError(_("Uploaded ZIP file didn't contain a directory."))
|
|
|
+
|
|
|
+
|
|
|
+def clean_theme_contents(theme_dir):
|
|
|
+ return read_manifest(theme_dir)
|
|
|
+
|
|
|
+
|
|
|
+def read_manifest(theme_dir):
|
|
|
+ try:
|
|
|
+ with open(os.path.join(theme_dir, "manifest.json")) as fp:
|
|
|
+ manifest = json.load(fp)
|
|
|
+ if not isinstance(manifest, dict):
|
|
|
+ message = _(
|
|
|
+ '"manifest.json" contained by ZIP file is not a valid '
|
|
|
+ 'theme manifest file.'
|
|
|
+ )
|
|
|
+ raise ThemeImportError(message)
|
|
|
+ except FileNotFoundError:
|
|
|
+ raise ThemeImportError(
|
|
|
+ _('Uploaded ZIP file didn\'t contain a "manifest.json".')
|
|
|
+ )
|
|
|
+ except json.decoder.JSONDecodeError:
|
|
|
+ raise ThemeImportError(
|
|
|
+ _('"manifest.json" contained by ZIP file is not a valid JSON file.')
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ return manifest
|