diff --git a/src/diffpy/pdfgui/control/calculation.py b/src/diffpy/pdfgui/control/calculation.py index 13819b81..ec6928f9 100644 --- a/src/diffpy/pdfgui/control/calculation.py +++ b/src/diffpy/pdfgui/control/calculation.py @@ -18,10 +18,11 @@ import copy import math +import pickle from diffpy.pdfgui.control.controlerrors import ControlConfigError, ControlKeyError, ControlValueError from diffpy.pdfgui.control.pdfcomponent import PDFComponent -from diffpy.pdfgui.utils import pickle_loads, safeCPickleDumps +from diffpy.pdfgui.utils import safeCPickleDumps class Calculation(PDFComponent): @@ -253,7 +254,7 @@ def load(self, z, subpath): returns a tree of internal hierachy """ - config = pickle_loads(z.read(subpath + "config")) + config = pickle.loads(z.read(subpath + "config"), encoding="latin1") self.rmin = config["rmin"] self.rstep = config["rstep"] self.rmax = config["rmax"] diff --git a/src/diffpy/pdfgui/control/fitdataset.py b/src/diffpy/pdfgui/control/fitdataset.py index eb3d6a80..45a0e8e1 100644 --- a/src/diffpy/pdfgui/control/fitdataset.py +++ b/src/diffpy/pdfgui/control/fitdataset.py @@ -461,7 +461,9 @@ def load(self, z, subpath): z -- zipped project file subpath -- path to its own storage within project file """ - from diffpy.pdfgui.utils import asunicode, pickle_loads + import pickle + + from diffpy.pdfgui.utils import asunicode self.clear() subs = subpath.split("/") @@ -471,7 +473,7 @@ def load(self, z, subpath): self.readObsStr(obsdata) # data from calculation - content = pickle_loads(z.read(subpath + "calc")) + content = pickle.loads(z.read(subpath + "calc"), encoding="latin1") for item in FitDataSet.persistentItems: # skip items which are not in the project file if item not in content: diff --git a/src/diffpy/pdfgui/control/fitting.py b/src/diffpy/pdfgui/control/fitting.py index 0d56df89..0c534c8f 100644 --- a/src/diffpy/pdfgui/control/fitting.py +++ b/src/diffpy/pdfgui/control/fitting.py @@ -15,12 +15,13 @@ from __future__ import print_function +import pickle import threading import time from diffpy.pdfgui.control.controlerrors import ControlError, ControlStatusError, ControlValueError from diffpy.pdfgui.control.organizer import Organizer -from diffpy.pdfgui.utils import pickle_loads, safeCPickleDumps +from diffpy.pdfgui.utils import safeCPickleDumps # helper routines to deal with PDFfit2 exceptions @@ -210,9 +211,11 @@ def load(self, z, subpath): self.parameters = CtrlUnpickler.loads(z.read(subpath + "parameters")) if "steps" in rootDict: - self.itemIndex, self.dataNameDict, self.snapshots = pickle_loads(z.read(subpath + "steps")) + self.itemIndex, self.dataNameDict, self.snapshots = pickle.loads( + z.read(subpath + "steps"), encoding="latin1" + ) if "result" in rootDict: - self.rw, self.res = pickle_loads(z.read(subpath + "result")) + self.rw, self.res = pickle.loads(z.read(subpath + "result"), encoding="latin1") return Organizer.load(self, z, subpath) diff --git a/src/diffpy/pdfgui/control/organizer.py b/src/diffpy/pdfgui/control/organizer.py index e5c74d37..d44dfb41 100644 --- a/src/diffpy/pdfgui/control/organizer.py +++ b/src/diffpy/pdfgui/control/organizer.py @@ -160,25 +160,25 @@ def load(self, z, subpath): returns a tree of internal hierachy """ # subpath = projName/myName/ - from diffpy.pdfgui.utils import unquote_plain + from urllib.parse import unquote_plus subs = subpath.split("/") rootDict = z.fileTree[subs[0]][subs[1]] if "structure" in rootDict: for strucName in rootDict["structure"].keys(): - struc = FitStructure(unquote_plain(strucName)) + struc = FitStructure(unquote_plus(strucName)) struc.load(z, subpath + "structure/" + strucName + "/") self.add(struc) if "dataset" in rootDict: for datasetName in rootDict["dataset"].keys(): - dataset = FitDataSet(unquote_plain(datasetName)) + dataset = FitDataSet(unquote_plus(datasetName)) dataset.load(z, subpath + "dataset/" + datasetName + "/") self.add(dataset) if "calculation" in rootDict: for calcName in rootDict["calculation"].keys(): - calc = Calculation(unquote_plain(calcName)) + calc = Calculation(unquote_plus(calcName)) calc.load(z, subpath + "calculation/" + calcName + "/") self.add(calc) @@ -193,14 +193,14 @@ def save(self, z, subpath): subpath -- path to its own storage within project file """ # strucs and datasets - from diffpy.pdfgui.utils import quote_plain + from urllib.parse import quote_plus for struc in self.strucs: - struc.save(z, subpath + "structure/" + quote_plain(struc.name) + "/") + struc.save(z, subpath + "structure/" + quote_plus(struc.name) + "/") for dataset in self.datasets: - dataset.save(z, subpath + "dataset/" + quote_plain(dataset.name) + "/") + dataset.save(z, subpath + "dataset/" + quote_plus(dataset.name) + "/") for calc in self.calcs: - calc.save(z, subpath + "calculation/" + quote_plain(calc.name) + "/") + calc.save(z, subpath + "calculation/" + quote_plus(calc.name) + "/") return def copy(self, other=None): diff --git a/src/diffpy/pdfgui/control/parameter.py b/src/diffpy/pdfgui/control/parameter.py index cf8bbe94..06e89b02 100644 --- a/src/diffpy/pdfgui/control/parameter.py +++ b/src/diffpy/pdfgui/control/parameter.py @@ -17,8 +17,6 @@ To be stored in Fitting.parameters { idx : parameter } dictionary """ -import six - from diffpy.pdfgui.control.controlerrors import ( ControlError, ControlKeyError, @@ -79,7 +77,7 @@ def setInitial(self, initial): if isinstance(initial, Fitting): self.__initial = "=" + initial.name self.__fitrepr = repr(initial) - elif isinstance(initial, six.string_types) and initial[:1] == "=": + elif isinstance(initial, str) and initial[:1] == "=": self.__initial = initial self.__findLinkedFitting() else: diff --git a/src/diffpy/pdfgui/control/pdfguicontrol.py b/src/diffpy/pdfgui/control/pdfguicontrol.py index f7d480f5..87f3b39d 100644 --- a/src/diffpy/pdfgui/control/pdfguicontrol.py +++ b/src/diffpy/pdfgui/control/pdfguicontrol.py @@ -15,13 +15,13 @@ from __future__ import print_function +import io import os +import pickle import sys import threading import time - -import six -import six.moves.cPickle as pickle +from urllib.parse import quote_plus from diffpy.pdfgui.control.calculation import Calculation from diffpy.pdfgui.control.controlerrors import ControlError, ControlFileError, ControlTypeError @@ -30,7 +30,7 @@ from diffpy.pdfgui.control.fitting import Fitting from diffpy.pdfgui.control.organizer import Organizer from diffpy.pdfgui.control.pdflist import PDFList -from diffpy.pdfgui.utils import asunicode, quote_plain +from diffpy.pdfgui.utils import asunicode class PDFGuiControl: @@ -395,7 +395,7 @@ def _nameParser(namelist): continue fit = Fitting(name) # fitting name stored in rootDict should be quoted - rdname = quote_plain(name) + rdname = quote_plus(name) # but let's also handle old project files if rdname not in rootDict: rdname = name @@ -450,7 +450,7 @@ def save(self, projfile=None): # fits also contain calculations for fit in self.fits: name = fit.name - fit.save(z, projName + "/" + quote_plain(fit.name) + "/") + fit.save(z, projName + "/" + quote_plus(fit.name) + "/") fitnames.append(name) if self.journal: z.writestr(projName + "/journal", asunicode(self.journal)) @@ -516,7 +516,7 @@ def redirectStdout(self): from diffpy.pdffit2 import output, redirect_stdout if output.stdout is sys.stdout: - redirect_stdout(six.StringIO()) + redirect_stdout(io.StringIO()) return def getEngineOutput(self): @@ -525,7 +525,7 @@ def getEngineOutput(self): txt = output.stdout.getvalue() output.stdout.close() - redirect_stdout(six.StringIO()) + redirect_stdout(io.StringIO()) return txt @@ -571,7 +571,7 @@ def loads(s): missedModule = str(err).split(" ")[-1] if missedModule.find("pdfgui.control") == -1: raise err - f = six.StringIO(s) + f = io.StringIO(s) unpickler = pickle.Unpickler(f) unpickler.find_global = _find_global return unpickler.load() diff --git a/src/diffpy/pdfgui/gui/adddatapanel.py b/src/diffpy/pdfgui/gui/adddatapanel.py index 15cb48ca..6e9ff4ae 100644 --- a/src/diffpy/pdfgui/gui/adddatapanel.py +++ b/src/diffpy/pdfgui/gui/adddatapanel.py @@ -106,7 +106,7 @@ def readConfiguration(self): if remember: if self.cP.has_option("DATASET", "last"): - self.fullpath = self.cP.getquoted("DATASET", "last") + self.fullpath = self.cP.get("DATASET", "last") import os.path if not os.path.exists(self.fullpath): @@ -119,7 +119,7 @@ def updateConfiguration(self): """Update the configuration for the 'DATASET'.""" if not self.cP.has_section("DATASET"): self.cP.add_section("DATASET") - self.cP.setquoted("DATASET", "last", self.fullpath) + self.cP.set("DATASET", "last", self.fullpath) return # EVENT CODE #### diff --git a/src/diffpy/pdfgui/gui/addphasepanel.py b/src/diffpy/pdfgui/gui/addphasepanel.py index cc8bbdd3..20e6cce6 100644 --- a/src/diffpy/pdfgui/gui/addphasepanel.py +++ b/src/diffpy/pdfgui/gui/addphasepanel.py @@ -128,7 +128,7 @@ def readConfiguration(self): if remember: if self.cP.has_option("PHASE", "last"): - self.fullpath = self.cP.getquoted("PHASE", "last") + self.fullpath = self.cP.get("PHASE", "last") import os.path if not os.path.exists(self.fullpath): @@ -141,7 +141,7 @@ def updateConfiguration(self): """Update the configuration for the 'DATASET'.""" if not self.cP.has_section("PHASE"): self.cP.add_section("PHASE") - self.cP.setquoted("PHASE", "last", self.fullpath) + self.cP.set("PHASE", "last", self.fullpath) return # EVENT CODE #### diff --git a/src/diffpy/pdfgui/gui/errorreportdialog.py b/src/diffpy/pdfgui/gui/errorreportdialog.py index 308954c0..1eea082e 100644 --- a/src/diffpy/pdfgui/gui/errorreportdialog.py +++ b/src/diffpy/pdfgui/gui/errorreportdialog.py @@ -151,7 +151,7 @@ def onGoogle(self, event): # wxGlade: ErrorReportDialog. Search for path-independent module and function names and for error message extracted from exception traceback. """ - from six.moves.urllib.parse import quote_plus + from urllib.parse import quote_plus traceback = self.text_ctrl_log.GetValue() terms = _extractSearchTerms(traceback) diff --git a/src/diffpy/pdfgui/gui/fittree.py b/src/diffpy/pdfgui/gui/fittree.py index 250656e3..afd0fcc8 100644 --- a/src/diffpy/pdfgui/gui/fittree.py +++ b/src/diffpy/pdfgui/gui/fittree.py @@ -23,6 +23,7 @@ """ import base64 +import pickle import re import wx @@ -31,7 +32,7 @@ from diffpy.pdfgui.control.fitting import Fitting from diffpy.pdfgui.gui.pdfguiglobals import iconpath from diffpy.pdfgui.gui.wxextensions import wx12 -from diffpy.pdfgui.utils import pickle_loads, safeCPickleDumps +from diffpy.pdfgui.utils import safeCPickleDumps class FitTree(wx12.TreeCtrl): @@ -610,7 +611,7 @@ def GetClipboard(self): if cdatabytes[:16] == "pdfgui_cliboard=".encode(): cdatabytes = cdatabytes[16:] - cdata = pickle_loads(cdatabytes) + cdata = pickle.loads(cdatabytes, encoding="latin1") except Exception: pass return cdata diff --git a/src/diffpy/pdfgui/gui/mainframe.py b/src/diffpy/pdfgui/gui/mainframe.py index bbe63bca..1e96261a 100644 --- a/src/diffpy/pdfgui/gui/mainframe.py +++ b/src/diffpy/pdfgui/gui/mainframe.py @@ -18,6 +18,7 @@ """This module contains the main window of PDFgui.""" import os.path +from configparser import ConfigParser import wx import wx.aui @@ -48,7 +49,6 @@ from diffpy.pdfgui.gui.temperatureseriespanel import TemperatureSeriesPanel from diffpy.pdfgui.gui.welcomepanel import WelcomePanel from diffpy.pdfgui.gui.wxextensions import wx12 -from diffpy.pdfgui.utils import QuotedConfigParser (PDFCustomEvent, EVT_PDFCUSTOM) = wx.lib.newevent.NewEvent() @@ -300,9 +300,9 @@ def __customProperties(self): self.runningDict = {} # The configuration parser for getting configuration data. - # self.cP = QuotedConfigParser() + # self.cP = Configparser() # Long try this to avoid DuplicateSectionError and ParsingError - self.cP = QuotedConfigParser(strict=False, allow_no_value=True) + self.cP = ConfigParser(strict=False, allow_no_value=True, interpolation=None) # Set the program mode self.mode = "fitting" @@ -984,7 +984,7 @@ def loadConfiguration(self): self.cP.read(localpath) for i in range(pdfguiglobals.MAXMRU, 0, -1): if self.cP.has_option("MRU", str(i)): - filename = self.cP.getquoted("MRU", str(i)) + filename = self.cP.get("MRU", str(i)) if filename: self.fileHistory.AddFileToHistory(filename) @@ -1029,7 +1029,7 @@ def updateConfiguration(self): for i in range(self.fileHistory.GetCount()): item = self.fileHistory.GetHistoryFile(i) - self.cP.setquoted("MRU", str(i + 1), item) + self.cP.set("MRU", str(i + 1), item) # Window size if not self.cP.has_section("SIZE"): @@ -2522,8 +2522,7 @@ def onSaveCalc(self, event): def onDocumentation(self, event): """Show information about the documentation.""" import webbrowser - - from six.moves.urllib.request import pathname2url + from urllib.request import pathname2url url = "file://" + pathname2url(docMainFile) webbrowser.open(url) diff --git a/src/diffpy/pdfgui/utils.py b/src/diffpy/pdfgui/utils.py index 4a052a8e..e53a4c68 100644 --- a/src/diffpy/pdfgui/utils.py +++ b/src/diffpy/pdfgui/utils.py @@ -19,14 +19,6 @@ """ -import six -import six.moves.cPickle as pickle -from six.moves.configparser import RawConfigParser - -# protocol=2 keep project files compatible with Python 2 -# PDFGUI_PICKLE_PROTOCOL = 2 - - def numericStringSort(lst): """Sort list of strings inplace according to general numeric value. Each string gets split to string and integer segments to create keys @@ -47,18 +39,6 @@ def numericStringSort(lst): return -def pickle_loads(sdata, encoding="latin1"): - """Mimic interface of Python 3 pickle.loads. - - Using encoding='latin1' is required for unpickling NumPy arrays and - instances of datetime, date and time pickled by Python 2. - - Return the reconstructed object hierarchy. - """ - rv = pickle.loads(sdata, encoding=encoding) if six.PY3 else pickle.loads(sdata) - return rv - - def safeCPickleDumps(obj): """Get pickle representation of an object possibly containing NaN or Inf. By default it uses pickle.HIGHEST_PROTOCOL, but falls back to ASCII @@ -68,6 +48,9 @@ def safeCPickleDumps(obj): Return pickle string. """ + + import pickle + ascii_protocol = 0 try: s = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL) @@ -76,61 +59,10 @@ def safeCPickleDumps(obj): return s -# This should be unnecessary in Python 3 -# TODO - replace getquoted/setquoted with get/set after dropping Python 2 - - -class QuotedConfigParser(RawConfigParser): - def getquoted(self, section, option): - """Retrieve option value previously set with setquoted. - - This allows to work with unicode strings. - """ - vq = self.get(section, option) - rv = vq.decode("utf-8") if six.PY2 else vq - return rv - - def setquoted(self, section, option, value): - """Set option to a value encoded with urllib.quote. - - This allows to store and write out unicode strings. - Use getquoted to recover the decoded value. - """ - vq = value.encode("utf-8") if six.PY2 else value - return self.set(section, option, vq) - - -# class QuotedConfigParser - - -def quote_plain(s): - """Return a possibly Unicode string quoted as plain ASCII. - - The returned value is suitable as a path component in the - project file format. - """ - from six.moves.urllib.parse import quote_plus - - rv = quote_plus(asunicode(s).encode("utf-8")) - return rv - - -def unquote_plain(s): - """Unquote string previously encoded with quote_plain.""" - from six.moves.urllib.parse import unquote_plus - - u = unquote_plus(s) - rv = asunicode(u) - return rv - - def asunicode(s): - """Convert string or bytes object to a text type. - - This is `unicode` in Python 2 and `str` in Python 3. - """ + """Convert string or bytes object to a text type.""" rv = s - if not isinstance(s, six.text_type): + if not isinstance(s, str): rv = s.decode("utf-8") return rv