def save(self, z, subpath): """save data from a zipped project file z -- zipped project file subpath -- path to its own storage within project file """ # strucs and datasets from diffpy.pdfgui.utils import quote_plain for struc in self.strucs: struc.save(z, subpath + 'structure/' + quote_plain(struc.name) + '/') for dataset in self.datasets: dataset.save(z, subpath + 'dataset/' + quote_plain(dataset.name) + '/') for calc in self.calcs: calc.save(z, subpath + 'calculation/' + quote_plain(calc.name) + '/') return
def save(self, z, subpath): """save data from a zipped project file z -- zipped project file subpath -- path to its own storage within project file """ # strucs and datasets from diffpy.pdfgui.utils import quote_plain for struc in self.strucs: struc.save(z, subpath + 'structure/' + quote_plain(struc.name) + '/') for dataset in self.datasets: dataset.save( z, subpath + 'dataset/' + quote_plain(dataset.name) + '/') for calc in self.calcs: calc.save(z, subpath + 'calculation/' + quote_plain(calc.name) + '/') return
def save(self, projfile=None): """Save project to projfile, default projfile is self.projfile This method first writes to a temporary file and only when successful, it overwrites projfile with the temporary file content. These steps prevent corruption of existing projects should something go wrong in the middle of save. As an added benefit, all permissions and ownership flags in an existing projfile are preserved. """ if projfile is not None: self.projfile = projfile # self.projfile is unset here only due to a bug. assert self.projfile is not None import zipfile import shutil from cPickle import PickleError import tempfile from diffpy.pdfgui.utils import quote_plain projbase = os.path.basename(self.projfile) projName = os.path.splitext(projbase)[0] # prepare to write fitnames = [] z = None tmpfilename = None try: tmpfd, tmpfilename = tempfile.mkstemp() os.close(tmpfd) z = zipfile.ZipFile(tmpfilename, 'w', zipfile.ZIP_DEFLATED) # fits also contain calculations for fit in self.fits: name = fit.name fit.save(z, projName + '/' + quote_plain(fit.name) + '/') fitnames.append(name) if self.journal: z.writestr(projName + '/journal', self.journal.encode('utf8')) ftxt = '\n'.join(fitnames) z.writestr(projName + '/fits', ftxt.encode('utf8')) z.close() shutil.copyfile(tmpfilename, self.projfile) except (IOError, PickleError): emsg = "Error when writing to %s" % self.projfile raise ControlFileError(emsg) finally: if z is not None: z.close() if tmpfilename is not None: os.remove(tmpfilename) return
def load(self, projfile): """load project from projfile. projfile -- a zip file of everything """ def _nameParser(namelist): """parse the zipfile name list to get a file tree""" fileTree = {} for name in namelist: subs = name.split('/') pathDict = fileTree for x in subs[:-1]: # if no node has been created if not pathDict.has_key(x): pathDict[x] = {} pathDict = pathDict[x] # check if the entry is a leaf(file, not folder) if subs[-1] != '': pathDict[subs[-1]] = None return fileTree self.projfile = projfile organizations = [] import zipfile from cPickle import PickleError from diffpy.pdfgui.utils import quote_plain # IOError can be raised when reading invalid zipfile # check for file existence here. if not os.path.isfile(projfile): emsg = "Project file %s does not exist." % projfile raise ControlFileError(emsg) emsg_invalid_file = "Invalid or corrupted project %s." % projfile z = None try: z = zipfile.ZipFile(projfile, 'r') z.fileTree = _nameParser(z.namelist()) if len(z.fileTree) == 0: raise ControlFileError(emsg_invalid_file) # The first layer has only one folder rootDict = z.fileTree.values()[0] projName = z.fileTree.keys()[0] if rootDict.has_key('journal'): self.journal = z.read(projName + '/journal').decode('utf8') # all the fitting and calculations #NOTE: It doesn't hurt to keep backward compatibility # old test project may not have file 'fits' if rootDict.has_key('fits'): ftxt = z.read(projName + '/fits').decode('utf8') fitnames = ftxt.splitlines() else: fitnames = [ x for x in rootDict.keys() if rootDict[x] is not None ] for name in fitnames: if not name: # empty string continue fit = Fitting(name) # fitting name stored in rootDict should be quoted rdname = quote_plain(name) # but let's also handle old project files if rdname not in rootDict: rdname = name if rootDict.has_key(rdname): org = fit.load(z, projName + '/' + rdname + '/') else: # it's simply a blank fitting, has no info in proj file yet org = fit.organization() organizations.append(org) self.add(fit) except (IOError, zipfile.error, PickleError): raise ControlFileError(emsg_invalid_file) # close input file if opened finally: if z: z.close() return organizations