diff --git a/bin/test_io.py b/bin/test_io.py index a0fdbb79..5da09a80 100644 --- a/bin/test_io.py +++ b/bin/test_io.py @@ -13,27 +13,19 @@ import manuskript.data as data path = os.path.join(sys.path[1], "sample-projects/book-of-acts") -settings = data.Settings(path) +project = data.Project(path + ".msk") +project.load() -settings.load() -settings.save() +settings = project.settings print(settings.properties) -plots = data.Plots(path) +plots = project.plots -plots.load() -plots.save() +revs = project.revisions -revs = data.Revisions(path) - -revs.load() - -statusHost = data.StatusHost(path) - -statusHost.load() - -for status in statusHost: +for status in project.statuses: print("--" + str(status)) -statusHost.save() +settings.set("saveToZip", True) +project.save() diff --git a/manuskript/data/__init__.py b/manuskript/data/__init__.py index 9e5457da..01591ff4 100644 --- a/manuskript/data/__init__.py +++ b/manuskript/data/__init__.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # --!-- coding: utf8 --!-- - from manuskript.data.plots import Plots, PlotLine, PlotStep +from manuskript.data.project import Project from manuskript.data.revisions import Revisions from manuskript.data.settings import Settings from manuskript.data.status import StatusHost, Status diff --git a/manuskript/data/plots.py b/manuskript/data/plots.py index d863c036..ae439b37 100644 --- a/manuskript/data/plots.py +++ b/manuskript/data/plots.py @@ -135,8 +135,12 @@ class Plots: cls.loadPlotLine(plots, element) def load(self): - tree = self.file.load() - Plots.loadPlots(self, tree.getroot()) + try: + tree = self.file.load() + Plots.loadPlots(self, tree.getroot()) + except FileNotFoundError: + self.host.reset() + self.lines.clear() @classmethod def saveElementAttribute(cls, element: etree.Element, name: str, value): diff --git a/manuskript/data/project.py b/manuskript/data/project.py new file mode 100644 index 00000000..33a70221 --- /dev/null +++ b/manuskript/data/project.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +from zipfile import BadZipFile +from manuskript.data.plots import Plots +from manuskript.data.revisions import Revisions +from manuskript.data.settings import Settings +from manuskript.data.status import StatusHost +from manuskript.io.mskFile import MskFile + + +class Project: + + def __init__(self, path): + self.file = MskFile(path) + + self.statuses = StatusHost(self.file.dir_path) + self.settings = Settings(self.file.dir_path) + self.plots = Plots(self.file.dir_path) + self.revisions = Revisions(self.file.dir_path) + + def __del__(self): + del self.file + + def load(self): + try: + self.file.load() + except BadZipFile: + return + except FileNotFoundError: + return + + self.statuses.load() + self.settings.load() + self.plots.load() + self.revisions.load() + + self.file.setZipFile(self.settings.isEnabled("saveToZip")) + + def save(self): + print("Save project: " + str(self.file.path) + " " + str(self.file.dir_path)) + + self.statuses.save() + self.settings.save() + self.plots.save() + #self.revisions.save() + + self.file.save(self.settings.isEnabled("saveToZip")) diff --git a/manuskript/data/revisions.py b/manuskript/data/revisions.py index 3648e982..c02db7ac 100644 --- a/manuskript/data/revisions.py +++ b/manuskript/data/revisions.py @@ -78,5 +78,10 @@ class Revisions: cls.loadRevisionOutline(revisions, child, element) def load(self): - tree = self.file.load() - Revisions.loadRevisionOutline(self, tree.getroot(), None) + try: + tree = self.file.load() + self.outline.clear() + + Revisions.loadRevisionOutline(self, tree.getroot(), None) + except FileNotFoundError: + self.outline.clear() diff --git a/manuskript/data/settings.py b/manuskript/data/settings.py index 4314e960..7e14b8a1 100644 --- a/manuskript/data/settings.py +++ b/manuskript/data/settings.py @@ -15,6 +15,15 @@ class Settings: if initDefault: Settings.loadDefaultSettings(self) + def get(self, key: str): + return self.properties.get(key) + + def isEnabled(self, key: str) -> bool: + return self.properties.get(key, False) is True + + def set(self, key: str, value): + self.properties[key] = value + def __iter__(self): return self.properties.__iter__() @@ -113,7 +122,10 @@ class Settings: } def load(self): - self.properties = self.file.load() + try: + self.properties = self.file.load() + except FileNotFoundError: + Settings.loadDefaultSettings(self) def save(self): self.file.save(self.properties) diff --git a/manuskript/data/status.py b/manuskript/data/status.py index 46ebca50..74def9ae 100644 --- a/manuskript/data/status.py +++ b/manuskript/data/status.py @@ -48,8 +48,12 @@ class StatusHost: return self.statuses.values().__iter__() def load(self): - text = self.file.load() - self.statuses.clear() + try: + text = self.file.load() + self.statuses.clear() + except FileNotFoundError: + self.statuses.clear() + return if len(text) <= 1: return diff --git a/manuskript/io/__init__.py b/manuskript/io/__init__.py index cf1cb0c7..7a5a8292 100644 --- a/manuskript/io/__init__.py +++ b/manuskript/io/__init__.py @@ -5,10 +5,5 @@ from manuskript.io.textFile import TextFile from manuskript.io.jsonFile import JsonFile from manuskript.io.xmlFile import XmlFile from manuskript.io.opmlFile import OpmlFile - -extensions = { - ".txt": TextFile, - ".json": JsonFile, - ".xml": XmlFile, - ".opml": OpmlFile -} +from manuskript.io.zipFile import ZipFile +from manuskript.io.mskFile import MskFile diff --git a/manuskript/io/mskFile.py b/manuskript/io/mskFile.py new file mode 100644 index 00000000..0d9a1780 --- /dev/null +++ b/manuskript/io/mskFile.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +import os +import shutil + +from manuskript.io.textFile import TextFile +from manuskript.io.zipFile import ZipFile + + +class MskFile(TextFile, ZipFile): + + def __init__(self, path): + dir_path = os.path.splitext(path)[0] + + if (not os.path.isdir(dir_path)) or (os.path.getsize(path) > 1): + dir_path = None + + self.zipFile = dir_path is None + ZipFile.__init__(self, path, dir_path) + + def __del__(self): + ZipFile.__del__(self) + + if self.isZipFile() and (self.tmp is None) and not (self.dir_path is None): + shutil.rmtree(self.dir_path) + + def isZipFile(self) -> bool: + return self.zipFile + + def setZipFile(self, zipFile: bool): + if zipFile is self.zipFile: + return + + if not zipFile: + self.dir_path = os.path.splitext(self.path)[0] + os.mkdir(self.dir_path) + ZipFile.load(self) + + self.zipFile = zipFile + + def load(self): + if self.zipFile: + ZipFile.load(self) + else: + value = TextFile.load(self) + + if value == "1": + self.setZipFile(False) + + return self.zipFile + + def save(self, content=None): + if not (content is None): + self.setZipFile(content) + + if self.zipFile: + ZipFile.save(self) + else: + TextFile.save(self, "1") diff --git a/manuskript/io/zipFile.py b/manuskript/io/zipFile.py new file mode 100644 index 00000000..ce583ae9 --- /dev/null +++ b/manuskript/io/zipFile.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +import tempfile +import shutil + +from zipfile import ZipFile as _ZipFile +from manuskript.io.abstractFile import AbstractFile + + +class ZipFile(AbstractFile): + + def __init__(self, path, dir_path=None): + AbstractFile.__init__(self, path) + + if dir_path is None: + self.tmp = tempfile.TemporaryDirectory() + dir_path = self.tmp.name + else: + self.tmp = None + + self.dir_path = dir_path + + def __del__(self): + if not (self.tmp is None): + self.tmp.cleanup() + + def load(self): + if self.dir_path is None: + self.tmp = tempfile.TemporaryDirectory() + self.dir_path = self.tmp.name + + archive = _ZipFile(self.path) + archive.extractall(self.dir_path) + return self.dir_path + + def save(self, content=None): + if not (content is None): + if not (self.tmp is None): + self.tmp.cleanup() + + self.tmp = None + self.dir_path = content + elif self.dir_path is None: + if self.tmp is None: + self.tmp = tempfile.TemporaryDirectory() + + self.dir_path = self.tmp.name + + shutil.make_archive(self.path, 'zip', self.dir_path) + shutil.move(self.path + ".zip", self.path)