From 564b36339ba5d38baf5bcc777facc49fd1ebfa57 Mon Sep 17 00:00:00 2001 From: Dylan Gatlin Date: Tue, 11 Feb 2020 00:37:17 -0700 Subject: [PATCH 1/6] Some major upgrades to Python 3. Guider still fails --- .gitignore | 6 ++- python/RO/AddCallback.py | 6 +-- python/RO/Alg/GenericCallback.py | 2 +- python/RO/Alg/IDGen.py | 4 +- python/RO/Alg/ListPlus.py | 8 +-- python/RO/Alg/MatchList.py | 4 +- python/RO/Alg/MultiDict.py | 6 +-- python/RO/Alg/MultiListIter.py | 8 +-- python/RO/Alg/OrderedDict.py | 38 +++++++------- python/RO/Alg/RandomWalk.py | 6 +-- python/RO/Alg/SavedDict.py | 2 +- python/RO/Astro/Cnv/AppGeoData.py | 2 +- python/RO/Astro/Cnv/AzAltFromHADec.py | 2 +- python/RO/Astro/Cnv/CoordConv.py | 28 +++++------ python/RO/Astro/Cnv/FK4FromICRS.py | 2 +- python/RO/Astro/Cnv/FK5Prec.py | 2 +- python/RO/Astro/Cnv/GalFromICRS.py | 2 +- python/RO/Astro/Cnv/GeoFromICRS.py | 4 +- python/RO/Astro/Cnv/GeoFromTopo.py | 6 +-- python/RO/Astro/Cnv/HADecFromAzAlt.py | 2 +- python/RO/Astro/Cnv/ICRSFromFK4.py | 2 +- python/RO/Astro/Cnv/ICRSFromFixedFK4.py | 2 +- python/RO/Astro/Cnv/ICRSFromGal.py | 2 +- python/RO/Astro/Cnv/ICRSFromGeo.py | 4 +- python/RO/Astro/Cnv/ObsFromTopo.py | 2 +- python/RO/Astro/Cnv/ObserverData.py | 2 +- python/RO/Astro/Cnv/TopoFromGeo.py | 6 +-- python/RO/Astro/Cnv/TopoFromGeoSimple.py | 4 +- python/RO/Astro/Cnv/TopoFromObs.py | 2 +- python/RO/Astro/Cnv/__init__.py | 2 +- python/RO/Astro/ImageWindow.py | 2 +- python/RO/Astro/Sph/Airmass.py | 2 +- python/RO/Astro/Sph/AngSep.py | 4 +- python/RO/Astro/Sph/AngSideAng.py | 2 +- python/RO/Astro/Sph/AzAltFromHADec.py | 8 +-- python/RO/Astro/Sph/CCFromSC.py | 2 +- python/RO/Astro/Sph/CCFromSCPV.py | 4 +- python/RO/Astro/Sph/CCFromSCPVOff.py | 8 +-- python/RO/Astro/Sph/CoordConv.py | 8 +-- python/RO/Astro/Sph/DCFromSC.py | 4 +- python/RO/Astro/Sph/HADecFromAzAlt.py | 8 +-- python/RO/Astro/Sph/SCFromCC.py | 2 +- python/RO/Astro/Sph/SCFromCCPV.py | 4 +- python/RO/Astro/Sph/SCFromCCPVOff.py | 8 +-- python/RO/Astro/Sph/SCFromDC.py | 4 +- python/RO/Astro/Sph/__init__.py | 2 +- python/RO/Astro/Tm/EpJFromMJD.py | 2 +- python/RO/Astro/Tm/GMSTFromUT1.py | 2 +- python/RO/Astro/Tm/ISODate.py | 2 +- python/RO/Astro/Tm/LASTFromUT1.py | 2 +- python/RO/Astro/Tm/LMSTFromUT1.py | 2 +- python/RO/Astro/Tm/MJDFromEpJ.py | 2 +- python/RO/Astro/Tm/MJDFromPyTuple.py | 2 +- python/RO/Astro/Tm/TAI.py | 2 +- python/RO/Astro/Tm/UTCFromPySec.py | 2 +- python/RO/Astro/Tm/__init__.py | 2 +- python/RO/Astro/llv/__init__.py | 2 +- python/RO/Astro/llv/epb.py | 2 +- python/RO/Astro/llv/epb2d.py | 2 +- python/RO/Astro/llv/epj.py | 2 +- python/RO/Astro/llv/epj2d.py | 2 +- python/RO/Astro/llv/eqeqx.py | 4 +- python/RO/Astro/llv/etrms.py | 2 +- python/RO/Astro/llv/euler.py | 2 +- python/RO/Astro/llv/evp.py | 6 +-- python/RO/Astro/llv/geoc.py | 2 +- python/RO/Astro/llv/mappa.py | 10 ++-- python/RO/Astro/llv/nut.py | 6 +-- python/RO/Astro/llv/nutc.py | 2 +- python/RO/Astro/llv/prebn.py | 4 +- python/RO/Astro/llv/prec.py | 4 +- python/RO/Astro/llv/prenut.py | 8 +-- python/RO/Astro/llv/vn.py | 2 +- python/RO/Astro/runTests.py | 2 +- python/RO/BitDescr.py | 2 +- python/RO/CanvasUtil.py | 6 +-- python/RO/CnvUtil.py | 10 ++-- python/RO/Comm/BaseSocket.py | 2 +- python/RO/Comm/BrowseURL.py | 8 +-- python/RO/Comm/FTPGet.py | 6 +-- python/RO/Comm/Generic.py | 6 +-- python/RO/Comm/HTTPGet.py | 12 ++--- python/RO/Comm/HubConnection.py | 22 ++++---- python/RO/Comm/TCPConnection.py | 8 +-- python/RO/Comm/TCPEcho.py | 8 +-- python/RO/Comm/TkSerial.py | 14 +++--- python/RO/Comm/TkSocket.py | 18 +++---- python/RO/Comm/TwistedSocket.py | 2 +- python/RO/Comm/VMSTelnet.py | 16 +++--- python/RO/Constants.py | 8 +-- python/RO/CoordSys.py | 2 +- python/RO/DS9.py | 16 +++--- python/RO/InputCont.py | 36 ++++++------- python/RO/KeyDispatcher.py | 16 +++--- python/RO/KeyVariable.py | 16 +++--- python/RO/MathUtil.py | 2 +- python/RO/OS/OSUtil.py | 2 +- python/RO/OS/__init__.py | 2 +- python/RO/OS/getDirs.py | 6 +-- python/RO/OS/getMacDirs.py | 2 +- python/RO/OS/getWinDirs.py | 2 +- python/RO/PVT.py | 2 +- python/RO/ParseMsg/GetHeader.py | 2 +- python/RO/ParseMsg/GetKeyword.py | 2 +- python/RO/ParseMsg/GetString.py | 2 +- python/RO/ParseMsg/GetValues.py | 4 +- python/RO/ParseMsg/ParseData.py | 8 +-- python/RO/ParseMsg/ParseMsg.py | 6 +-- python/RO/ParseMsg/__init__.py | 2 +- python/RO/Prefs/PrefEditor.py | 64 ++++++++++++------------ python/RO/Prefs/PrefVar.py | 38 +++++++------- python/RO/Prefs/PrefWdg.py | 52 +++++++++---------- python/RO/SQLUtil.py | 10 ++-- python/RO/ScriptRunner.py | 16 +++--- python/RO/SeqUtil.py | 24 ++++----- python/RO/StringUtil.py | 18 +++---- python/RO/TkUtil.py | 14 +++--- python/RO/Wdg/BalloonHelp.py | 22 ++++---- python/RO/Wdg/Bindings.py | 12 ++--- python/RO/Wdg/Button.py | 27 +++++----- python/RO/Wdg/ChangedIndicator.py | 15 +++--- python/RO/Wdg/Checkbutton.py | 26 +++++----- python/RO/Wdg/CmdWdg.py | 14 +++--- python/RO/Wdg/CtxMenu.py | 16 +++--- python/RO/Wdg/DropletApp.py | 12 ++--- python/RO/Wdg/DropletRunner.py | 12 ++--- python/RO/Wdg/Entry.py | 62 +++++++++++------------ python/RO/Wdg/FTPLogWdg.py | 35 ++++++------- python/RO/Wdg/GrayImageDispWdg.py | 55 ++++++++++---------- python/RO/Wdg/Gridder.py | 43 ++++++++-------- python/RO/Wdg/HTTPGetWdg.py | 34 ++++++------- python/RO/Wdg/HistoryMenu.py | 23 +++++---- python/RO/Wdg/InputContFrame.py | 8 +-- python/RO/Wdg/InputContPresetsWdg.py | 47 ++++++++--------- python/RO/Wdg/InputDialog.py | 38 +++++++------- python/RO/Wdg/IsCurrentMixin.py | 36 ++++++------- python/RO/Wdg/Label.py | 23 +++++---- python/RO/Wdg/LogWdg.py | 26 +++++----- python/RO/Wdg/Menubutton.py | 19 +++---- python/RO/Wdg/OptionButtons.py | 19 +++---- python/RO/Wdg/OptionMenu.py | 23 +++++---- python/RO/Wdg/OptionPanelControl.py | 26 +++++----- python/RO/Wdg/PatchedCanvas.py | 10 ++-- python/RO/Wdg/PathWdg.py | 29 +++++------ python/RO/Wdg/ProgressBar.py | 33 ++++++------ python/RO/Wdg/PythonTk.py | 28 +++++------ python/RO/Wdg/PythonWdg.py | 60 +++++++++++----------- python/RO/Wdg/RadiobuttonSet.py | 28 +++++------ python/RO/Wdg/ResizableRect.py | 12 ++--- python/RO/Wdg/ScriptWdg.py | 29 +++++------ python/RO/Wdg/ScrolledWdg.py | 20 ++++---- python/RO/Wdg/SeverityMixin.py | 36 ++++++------- python/RO/Wdg/Sound.py | 6 +-- python/RO/Wdg/StateTracker.py | 6 +-- python/RO/Wdg/StatusBar.py | 12 ++--- python/RO/Wdg/StatusConfigGridder.py | 13 ++--- python/RO/Wdg/StripChartWdg.py | 16 +++--- python/RO/Wdg/Text.py | 31 ++++++------ python/RO/Wdg/Toplevel.py | 18 +++---- python/RO/Wdg/WdgPrefs.py | 10 ++-- python/RO/Wdg/__init__.py | 2 +- python/RO/Wdg/sampleDroplet.py | 2 +- python/RO/__init__.py | 2 +- python/RO/procFiles.py | 6 +-- releaseNewVersion.py | 6 +-- setup.py | 2 +- tests/Comm/testTkSocket.py | 6 +-- tests/Comm/testTwistedSocket.py | 2 +- tools/cheol.py | 2 +- tools/eventlogger.py | 16 +++--- tools/fitsinfo.py | 6 +-- tools/keysym.py | 8 +-- tools/serialterm.py | 10 ++-- tools/tcpclient.py | 10 ++-- 174 files changed, 1005 insertions(+), 983 deletions(-) diff --git a/.gitignore b/.gitignore index 253fad6..bbf3434 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ dist/ RO.egg-info/ -*.pyc \ No newline at end of file +*.pyc + +# Pycharm settings +.idea + diff --git a/python/RO/AddCallback.py b/python/RO/AddCallback.py index cf69d02..9e5aced 100644 --- a/python/RO/AddCallback.py +++ b/python/RO/AddCallback.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Mixing class(es) for adding callback capabilities. History: @@ -145,7 +145,7 @@ def addCallback(self, return if not callable(callFunc): - raise ValueError, "callFunc %r is not callable" % (callFunc,) + raise ValueError("callFunc %r is not callable" % (callFunc,)) # add new function if callFunc not in self._callbacks: @@ -264,7 +264,7 @@ def __init__(self, if command is not None: if not callable(command): - raise ValueError, "command %r is not callable" % (command,) + raise ValueError("command %r is not callable" % (command,)) def doCommand(wdg): return command() self.addCallback(doCommand) diff --git a/python/RO/Alg/GenericCallback.py b/python/RO/Alg/GenericCallback.py index 2862d05..4bf5c26 100644 --- a/python/RO/Alg/GenericCallback.py +++ b/python/RO/Alg/GenericCallback.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """From Scott David Daniels . My changes include: - Used a name suggested by Eric Brunel diff --git a/python/RO/Alg/IDGen.py b/python/RO/Alg/IDGen.py index 9725a4e..297c81e 100644 --- a/python/RO/Alg/IDGen.py +++ b/python/RO/Alg/IDGen.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Generate a series of ID numbers. Note: this would be a bit simpler as a generator instead of a class, @@ -39,7 +39,7 @@ def __init__(self, startVal=1, wrapVal=None, incr=1): def __iter__(self): return self - def next(self): + def __next__(self): """Return the next ID number.""" newID = self.startVal + (self.ind * self.incr) self.ind += 1 diff --git a/python/RO/Alg/ListPlus.py b/python/RO/Alg/ListPlus.py index 997d7a8..4a1467f 100644 --- a/python/RO/Alg/ListPlus.py +++ b/python/RO/Alg/ListPlus.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """A ListPlus adds a few methods to a standard list to make it more consistent with dict. @@ -23,17 +23,17 @@ def has_key(self, key): return False def iteritems(self): - for key in self.iterkeys(): + for key in self.keys(): yield (key, self[key]) def iterkeys(self): - return iter(xrange(len(self))) + return iter(range(len(self))) def itervalues(self): return iter(self) def keys(self): - return range(len(self)) + return list(range(len(self))) def values(self): return self[:] diff --git a/python/RO/Alg/MatchList.py b/python/RO/Alg/MatchList.py index 1b8aafc..f4892fc 100644 --- a/python/RO/Alg/MatchList.py +++ b/python/RO/Alg/MatchList.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """ History: 2003-10-23 ROwen Renamed from GetByPrefix and enhanced. @@ -59,7 +59,7 @@ def matchKeys(self, fromDict): If more than one key in fromDict has the same match, raises ValueError """ toDict = {} - for fromKey, val in fromDict.iteritems(): + for fromKey, val in fromDict.items(): toKey = self.getUniqueMatch(fromKey) if toKey in toDict: raise ValueError("%r contains multiple keys that match %s" % (fromDict, toKey,)) diff --git a/python/RO/Alg/MultiDict.py b/python/RO/Alg/MultiDict.py index 95e6c41..f685519 100755 --- a/python/RO/Alg/MultiDict.py +++ b/python/RO/Alg/MultiDict.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A dictionary that stores a list of values for each key. Note: one could subclass dict but this requires writing @@ -16,9 +16,9 @@ """ __all__ = ["ListDict", "SetDict"] -import UserDict +from collections import UserDict -class ListDict(UserDict.UserDict): +class ListDict(UserDict): """A dictionary whose values are a list of items. """ def __setitem__(self, key, val): diff --git a/python/RO/Alg/MultiListIter.py b/python/RO/Alg/MultiListIter.py index c3828f7..600b1c7 100755 --- a/python/RO/Alg/MultiListIter.py +++ b/python/RO/Alg/MultiListIter.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ An iterator over multiple lists or other collections. Stops at the end of the shortest list. @@ -13,18 +13,18 @@ class MultiListIter(object): def __init__(self, *lists): - self.iters = map(iter, lists) + self.iters = list(map(iter, lists)) def __iter__(self): return self - def next(self): + def __next__(self): return [next(elem) for elem in self.iters] if __name__ == "__main__": print("MultiListIter example") - a = range(5) + a = list(range(5)) b = [x**2 for x in a] print(("a = %r" % a)) print(("b = %r" % b)) diff --git a/python/RO/Alg/OrderedDict.py b/python/RO/Alg/OrderedDict.py index 6f6c300..835f05b 100644 --- a/python/RO/Alg/OrderedDict.py +++ b/python/RO/Alg/OrderedDict.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """A dictionary in which the order of adding items is preserved. Replacing an existing item replaces it at its current location. @@ -50,7 +50,7 @@ def __init__(self, seqOrDict=None): if seqOrDict is None: return elif hasattr(seqOrDict, "iteritems"): - for key, val in seqOrDict.iteritems(): + for key, val in seqOrDict.items(): self[key] = val else: for key, val in seqOrDict: @@ -67,7 +67,7 @@ def iterkeys(self): return iter(self.__keyList) def itervalues(self): - for key in self.iterkeys(): + for key in self.keys(): yield self[key] def iteritems(self): @@ -123,11 +123,11 @@ def sort(self, cmpFunc=None): def update(self, aDict): """Add all items from dictionary aDict to self (in order if aDict is an ordered dictionary). """ - for key, value in aDict.iteritems(): + for key, value in aDict.items(): self[key] = value def values(self): - return [self[key] for key in self.iterkeys()] + return [self[key] for key in self.keys()] def _checkIntegrity(self): """Perform an internal consistency check and raise an AssertionError if anything is wrong. @@ -136,7 +136,7 @@ def _checkIntegrity(self): """ assert len(self) == len(self.__keyList), \ "length of dict %r != length of key list %r" % (len(self), len(self.__keyList)) - for key in self.iterkeys(): + for key in self.keys(): assert key in self, \ "key %r in key list missing from dictionary" % (key,) @@ -145,16 +145,16 @@ def __delitem__(self, key): self.__keyList.remove(key) def __iter__(self): - return self.iterkeys() + return iter(self.keys()) def __repr__(self): - return "%s([%s])" % (self.__class__.__name__, ', '.join(["(%r, %r)" % item for item in self.iteritems()])) + return "%s([%s])" % (self.__class__.__name__, ', '.join(["(%r, %r)" % item for item in self.items()])) def __str__(self): - return "{%s}" % (', '.join(["(%r, %r)" % item for item in self.iteritems()]),) + return "{%s}" % (', '.join(["(%r, %r)" % item for item in self.items()]),) def __setitem__(self, key, value): - if not self.has_key(key): + if key not in self: self.__keyList.append(key) dict.__setitem__(self, key, value) @@ -188,7 +188,7 @@ def copy(self): return revCopy def __repr__(self): - descrList = ["(%r, %r)" % item for item in self.iteritems()] + descrList = ["(%r, %r)" % item for item in self.items()] descrList.reverse() return "%s([%s])" % (self.__class__.__name__, ', '.join(descrList)) @@ -209,10 +209,10 @@ def __repr__(self): def testDict(desKeys, desValues, theDict): """Test an ordered dictionary, given the expected keys and values (in order)""" - actKeys = theDict.keys() + actKeys = list(theDict.keys()) assert desKeys == actKeys, "keys() failed; keys %r != %r" % (desKeys, actKeys) - actValues = theDict.values() + actValues = list(theDict.values()) assert desValues == actValues, "values() failed; values %r != %r" % (desValues, actValues) assert len(theDict) == len(desKeys), "len() failed: %r != %r" % (len(desKeys), len(theDict)) @@ -221,11 +221,11 @@ def testDict(desKeys, desValues, theDict): actKeys = [key for key in theDict] assert desKeys == actKeys, "__iter__() failed; keys %r != %r" % (desKeys, actKeys) - actValues = [v for v in theDict.itervalues()] + actValues = [v for v in theDict.values()] assert desValues == actValues, "itervalues() failed; values %r != %r" % (desValues, actValues) - desKeyValues = map(lambda key, v: (key, v), desKeys, desValues) - actKeyValues = [kv for kv in theDict.iteritems()] + desKeyValues = list(map(lambda key, v: (key, v), desKeys, desValues)) + actKeyValues = [kv for kv in theDict.items()] assert desKeyValues == actKeyValues, "iteritems() failed; values %r != %r" % (desKeyValues, actKeyValues) theDict._checkIntegrity() @@ -273,11 +273,11 @@ def altKeyToValue(key): # test copying dictCopy = oDict.copy() - assert dictCopy.keys() == oDict.keys(), "copy failed; keys %r != %r" % (dictCopy.keys(), testDict.keys()) + assert list(dictCopy.keys()) == list(oDict.keys()), "copy failed; keys %r != %r" % (list(dictCopy.keys()), list(testDict.keys())) - testKey = dictCopy.keys()[0] + testKey = list(dictCopy.keys())[0] dictCopy[testKey] = "changed value" - assert dictCopy.values() != oDict.values(), "copy failed; changing a value in one affected the other" + assert list(dictCopy.values()) != list(oDict.values()), "copy failed; changing a value in one affected the other" # add a new item to dictCopy and make sure the integrity of both are preserved # (verifies that the __keyList lists in each dictionary are separate entities) diff --git a/python/RO/Alg/RandomWalk.py b/python/RO/Alg/RandomWalk.py index 7ef2692..9fb11d0 100755 --- a/python/RO/Alg/RandomWalk.py +++ b/python/RO/Alg/RandomWalk.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["ConstrainedGaussianRandomWalk", "GaussianRandomWalk"] @@ -26,7 +26,7 @@ def __init__(self, homeValue, sigma, minValue, maxValue): def __iter__(self): return self - def next(self): + def __next__(self): """Randomly change the value and return the next value """ rawDelta = random.gauss(0, self.sigma) @@ -59,7 +59,7 @@ def __init__(self, initialValue, sigma): def __iter__(self): return self - def next(self): + def __next__(self): """Randomly change the value and return the new value """ self.value += random.gauss(0, self.sigma) diff --git a/python/RO/Alg/SavedDict.py b/python/RO/Alg/SavedDict.py index fde9485..f7e5135 100644 --- a/python/RO/Alg/SavedDict.py +++ b/python/RO/Alg/SavedDict.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """A dictionary that is automatically persisted to a file Useful for managing saved configurations and similar purposes. diff --git a/python/RO/Astro/Cnv/AppGeoData.py b/python/RO/Astro/Cnv/AppGeoData.py index 8fc8f1c..31d21b7 100755 --- a/python/RO/Astro/Cnv/AppGeoData.py +++ b/python/RO/Astro/Cnv/AppGeoData.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2004-05-18 ROwen Stop importing RO.PhysConst; it wasn't used. diff --git a/python/RO/Astro/Cnv/AzAltFromHADec.py b/python/RO/Astro/Cnv/AzAltFromHADec.py index 07d5265..d751910 100755 --- a/python/RO/Astro/Cnv/AzAltFromHADec.py +++ b/python/RO/Astro/Cnv/AzAltFromHADec.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-22 ROwen Converted to Python from the TCC's cnv_HADec2AzAlt 1-1. diff --git a/python/RO/Astro/Cnv/CoordConv.py b/python/RO/Astro/Cnv/CoordConv.py index cd965d1..a918c15 100755 --- a/python/RO/Astro/Cnv/CoordConv.py +++ b/python/RO/Astro/Cnv/CoordConv.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Convert astronomical positions between various coordinate systems. The CnvObj code is getting ugly enough (I had to add ICRS<->ICRS2000 cases @@ -32,19 +32,19 @@ import numpy import RO.CoordSys from RO.Astro import Tm -from AppGeoData import AppGeoData -from FK4FromICRS import fk4FromICRS -from FK5Prec import fk5Prec -from GalFromICRS import galFromICRS -from GeoFromICRS import geoFromICRS -from GeoFromTopo import geoFromTopo -from ICRSFromFK4 import icrsFromFK4 -from ICRSFromFixedFK4 import icrsFromFixedFK4 -from ICRSFromGal import icrsFromGal -from ICRSFromGeo import icrsFromGeo -from ObsFromTopo import obsFromTopo -from TopoFromGeo import topoFromGeo -from TopoFromObs import topoFromObs +from .AppGeoData import AppGeoData +from .FK4FromICRS import fk4FromICRS +from .FK5Prec import fk5Prec +from .GalFromICRS import galFromICRS +from .GeoFromICRS import geoFromICRS +from .GeoFromTopo import geoFromTopo +from .ICRSFromFK4 import icrsFromFK4 +from .ICRSFromFixedFK4 import icrsFromFixedFK4 +from .ICRSFromGal import icrsFromGal +from .ICRSFromGeo import icrsFromGeo +from .ObsFromTopo import obsFromTopo +from .TopoFromGeo import topoFromGeo +from .TopoFromObs import topoFromObs _CSysList = (RO.CoordSys.ICRS, RO.CoordSys.FK5, RO.CoordSys.FK4, RO.CoordSys.Galactic, RO.CoordSys.Geocentric, RO.CoordSys.Topocentric, RO.CoordSys.Observed, diff --git a/python/RO/Astro/Cnv/FK4FromICRS.py b/python/RO/Astro/Cnv/FK4FromICRS.py index b98ca64..1140442 100755 --- a/python/RO/Astro/Cnv/FK4FromICRS.py +++ b/python/RO/Astro/Cnv/FK4FromICRS.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-22 ROwen Converted to Python from the TCC's cnv_J2FK4 4-1. diff --git a/python/RO/Astro/Cnv/FK5Prec.py b/python/RO/Astro/Cnv/FK5Prec.py index 2826e58..9efc5e9 100755 --- a/python/RO/Astro/Cnv/FK5Prec.py +++ b/python/RO/Astro/Cnv/FK5Prec.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-22 ROwen Converted from the TCC's cnv_FK5Prec 6-1 diff --git a/python/RO/Astro/Cnv/GalFromICRS.py b/python/RO/Astro/Cnv/GalFromICRS.py index 9752023..67d1e5d 100755 --- a/python/RO/Astro/Cnv/GalFromICRS.py +++ b/python/RO/Astro/Cnv/GalFromICRS.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-17 ROwen Converted to Python from the TCC's cnv_J2Gal 4-1. diff --git a/python/RO/Astro/Cnv/GeoFromICRS.py b/python/RO/Astro/Cnv/GeoFromICRS.py index 7c92f85..5dfa449 100755 --- a/python/RO/Astro/Cnv/GeoFromICRS.py +++ b/python/RO/Astro/Cnv/GeoFromICRS.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: 2002-07-12 ROwen Converted to Python from the TCC's cnv_J2AppGeo 7-3 @@ -64,7 +64,7 @@ def geoFromICRS(icrsP, icrsV, agData): if __name__ == "__main__": import RO.SeqUtil - from AppGeoData import AppGeoData + from .AppGeoData import AppGeoData print("testing geoFromICRS") # test data is formatted as follows: # a list of entries, each consisting of: diff --git a/python/RO/Astro/Cnv/GeoFromTopo.py b/python/RO/Astro/Cnv/GeoFromTopo.py index 1bd852a..a9a0adf 100755 --- a/python/RO/Astro/Cnv/GeoFromTopo.py +++ b/python/RO/Astro/Cnv/GeoFromTopo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: 2002-07-22 ROwen Converted to Python from the TCC's cnv_AppTopo2AppGeo 3-3. @@ -12,7 +12,7 @@ import numpy import RO.MathUtil from RO.Astro import llv -from HADecFromAzAlt import haDecFromAzAlt +from .HADecFromAzAlt import haDecFromAzAlt def geoFromTopo(appTopoP, last, obsData): """ @@ -64,7 +64,7 @@ def geoFromTopo(appTopoP, last, obsData): if __name__ == "__main__": import RO.SeqUtil - from ObserverData import ObserverData + from .ObserverData import ObserverData print("testing geoFromTopo") # test data is formatted as follows: # a list of entries, each consisting of: diff --git a/python/RO/Astro/Cnv/HADecFromAzAlt.py b/python/RO/Astro/Cnv/HADecFromAzAlt.py index b3a09aa..1c2e442 100755 --- a/python/RO/Astro/Cnv/HADecFromAzAlt.py +++ b/python/RO/Astro/Cnv/HADecFromAzAlt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-22 ROwen Converted from the TCC's cnv_AzAlt2HADec 1-1. diff --git a/python/RO/Astro/Cnv/ICRSFromFK4.py b/python/RO/Astro/Cnv/ICRSFromFK4.py index 63092a4..7300f3d 100755 --- a/python/RO/Astro/Cnv/ICRSFromFK4.py +++ b/python/RO/Astro/Cnv/ICRSFromFK4.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-11 ROwen Converted to Python from the TCC's cnv_FK42J 4-1. diff --git a/python/RO/Astro/Cnv/ICRSFromFixedFK4.py b/python/RO/Astro/Cnv/ICRSFromFixedFK4.py index 6bfc3ed..dfd0eae 100755 --- a/python/RO/Astro/Cnv/ICRSFromFixedFK4.py +++ b/python/RO/Astro/Cnv/ICRSFromFixedFK4.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-09 ROwen Converted to Python from the TCC's cnv_ZPMFK42J 4-1. diff --git a/python/RO/Astro/Cnv/ICRSFromGal.py b/python/RO/Astro/Cnv/ICRSFromGal.py index 49f227a..7c7a25c 100755 --- a/python/RO/Astro/Cnv/ICRSFromGal.py +++ b/python/RO/Astro/Cnv/ICRSFromGal.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-22 ROwen Converted to Python from the TCC's cnv_Gal2J 4-1. diff --git a/python/RO/Astro/Cnv/ICRSFromGeo.py b/python/RO/Astro/Cnv/ICRSFromGeo.py index ab72203..1f48f3a 100755 --- a/python/RO/Astro/Cnv/ICRSFromGeo.py +++ b/python/RO/Astro/Cnv/ICRSFromGeo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: 2002-07-22 ROwen Converted to Python from cnv_AppGeo2J 4-2. @@ -96,7 +96,7 @@ def icrsFromGeo(appGeoP, agData): if __name__ == "__main__": import RO.SeqUtil - from AppGeoData import AppGeoData + from .AppGeoData import AppGeoData print("testing icrsFromGeo") # test data is formatted as follows: # a list of entries, each consisting of: diff --git a/python/RO/Astro/Cnv/ObsFromTopo.py b/python/RO/Astro/Cnv/ObsFromTopo.py index 8877e37..83de8fa 100755 --- a/python/RO/Astro/Cnv/ObsFromTopo.py +++ b/python/RO/Astro/Cnv/ObsFromTopo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-22 ROwen Converted from the TCC's cnv_Refract 2-2. diff --git a/python/RO/Astro/Cnv/ObserverData.py b/python/RO/Astro/Cnv/ObserverData.py index f0fe8dd..d6bf5f7 100755 --- a/python/RO/Astro/Cnv/ObserverData.py +++ b/python/RO/Astro/Cnv/ObserverData.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2007-04-24 ROwen Converted from Numeric to numpy. diff --git a/python/RO/Astro/Cnv/TopoFromGeo.py b/python/RO/Astro/Cnv/TopoFromGeo.py index 65f473f..9031169 100755 --- a/python/RO/Astro/Cnv/TopoFromGeo.py +++ b/python/RO/Astro/Cnv/TopoFromGeo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: 2002-07-22 ROwen Converted to Python from the TCC's cnv_AppGeo2AppTopo 7-3. @@ -11,7 +11,7 @@ import numpy import RO.MathUtil from RO.Astro import llv -from AzAltFromHADec import azAltFromHADec +from .AzAltFromHADec import azAltFromHADec def topoFromGeo(appGeoP, last, obsData): """ @@ -62,7 +62,7 @@ def topoFromGeo(appGeoP, last, obsData): if __name__ == "__main__": import RO.SeqUtil - from ObserverData import ObserverData + from .ObserverData import ObserverData print("testing topoFromGeo") # test data is formatted as follows: # a list of entries, each consisting of: diff --git a/python/RO/Astro/Cnv/TopoFromGeoSimple.py b/python/RO/Astro/Cnv/TopoFromGeoSimple.py index cfee21b..b3a02b6 100755 --- a/python/RO/Astro/Cnv/TopoFromGeoSimple.py +++ b/python/RO/Astro/Cnv/TopoFromGeoSimple.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: 2002-07-22 ROwen Converted to Python from the TCC's cnv_AppGeo2AppTopo. @@ -8,7 +8,7 @@ __all__ = ["topoFromGeoSimple"] import RO.MathUtil -from AzAltFromHADec import azAltFromHADec +from .AzAltFromHADec import azAltFromHADec # needs test code diff --git a/python/RO/Astro/Cnv/TopoFromObs.py b/python/RO/Astro/Cnv/TopoFromObs.py index b4ba33a..e0d7170 100755 --- a/python/RO/Astro/Cnv/TopoFromObs.py +++ b/python/RO/Astro/Cnv/TopoFromObs.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2002-07-22 ROwen Converted to Python from the TCC's cnv_UnRefract 2-2. diff --git a/python/RO/Astro/Cnv/__init__.py b/python/RO/Astro/Cnv/__init__.py index 432e337..935d5b3 100644 --- a/python/RO/Astro/Cnv/__init__.py +++ b/python/RO/Astro/Cnv/__init__.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + """ Astronomical math, including numerous coordinate conversions, in cartesian coordinates. diff --git a/python/RO/Astro/ImageWindow.py b/python/RO/Astro/ImageWindow.py index 23e09bf..2754db8 100755 --- a/python/RO/Astro/ImageWindow.py +++ b/python/RO/Astro/ImageWindow.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Code to handle imager windowing (subimage) and binning. Note: uses the expansionist or inclusive philosophy. diff --git a/python/RO/Astro/Sph/Airmass.py b/python/RO/Astro/Sph/Airmass.py index d36e39e..fcb0d68 100755 --- a/python/RO/Astro/Sph/Airmass.py +++ b/python/RO/Astro/Sph/Airmass.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["airmass"] diff --git a/python/RO/Astro/Sph/AngSep.py b/python/RO/Astro/Sph/AngSep.py index 4f1b973..b59c8e4 100755 --- a/python/RO/Astro/Sph/AngSep.py +++ b/python/RO/Astro/Sph/AngSep.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: 6/01 ROwen Initial release. @@ -11,7 +11,7 @@ import math import numpy import RO.MathUtil -from DCFromSC import dcFromSC +from .DCFromSC import dcFromSC def angSep(posA, posB): """Computes the angular separation between two points on a sphere. diff --git a/python/RO/Astro/Sph/AngSideAng.py b/python/RO/Astro/Sph/AngSideAng.py index 4e66b8e..af940bc 100755 --- a/python/RO/Astro/Sph/AngSideAng.py +++ b/python/RO/Astro/Sph/AngSideAng.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["angSideAng"] diff --git a/python/RO/Astro/Sph/AzAltFromHADec.py b/python/RO/Astro/Sph/AzAltFromHADec.py index 2d1cc64..3e3d7aa 100755 --- a/python/RO/Astro/Sph/AzAltFromHADec.py +++ b/python/RO/Astro/Sph/AzAltFromHADec.py @@ -1,10 +1,10 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["azAltFromHADec"] -from DCFromSC import dcFromSC -from SCFromDC import scFromDC +from .DCFromSC import dcFromSC +from .SCFromDC import scFromDC from RO.Astro import Cnv def azAltFromHADec(haDec, lat): @@ -39,7 +39,7 @@ def azAltFromHADec(haDec, lat): if __name__ == "__main__": - from AngSep import angSep + from .AngSep import angSep MaxErrArcSec = 1e-6 # max error on sky, in arc seconds print("testing azAltFromHADec") # test data is formatted as follows: diff --git a/python/RO/Astro/Sph/CCFromSC.py b/python/RO/Astro/Sph/CCFromSC.py index c832fdd..d7b7142 100755 --- a/python/RO/Astro/Sph/CCFromSC.py +++ b/python/RO/Astro/Sph/CCFromSC.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History 2002-07-23 ROwen Converted from TCC's sph_SC2CC 1-1. diff --git a/python/RO/Astro/Sph/CCFromSCPV.py b/python/RO/Astro/Sph/CCFromSCPV.py index 0c913a6..4cbbecd 100755 --- a/python/RO/Astro/Sph/CCFromSCPV.py +++ b/python/RO/Astro/Sph/CCFromSCPV.py @@ -1,11 +1,11 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["ccFromSCPV"] import RO.PhysConst import RO.MathUtil -from CCFromSC import ccFromSC +from .CCFromSC import ccFromSC # Magic Numbers # if parallax is less than _MinParallax, diff --git a/python/RO/Astro/Sph/CCFromSCPVOff.py b/python/RO/Astro/Sph/CCFromSCPVOff.py index 90cc34e..ad0ca2e 100755 --- a/python/RO/Astro/Sph/CCFromSCPVOff.py +++ b/python/RO/Astro/Sph/CCFromSCPVOff.py @@ -1,12 +1,12 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["ccFromSCPVOff"] import RO.MathUtil -from AngSideAng import angSideAng -from CCFromSC import ccFromSC -from CCFromSCPV import ccFromSCPV +from .AngSideAng import angSideAng +from .CCFromSC import ccFromSC +from .CCFromSCPV import ccFromSCPV def ccFromSCPVOff(pos, pm, parlax, radVel, offDir, offMag): """ diff --git a/python/RO/Astro/Sph/CoordConv.py b/python/RO/Astro/Sph/CoordConv.py index 217747c..e661b81 100755 --- a/python/RO/Astro/Sph/CoordConv.py +++ b/python/RO/Astro/Sph/CoordConv.py @@ -1,13 +1,13 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["coordConv"] -import Const +from . import Const from RO.Astro import Cnv import RO.MathUtil -from CCFromSCPVOff import ccFromSCPVOff -from SCFromCCPVOff import scFromCCPVOff +from .CCFromSCPVOff import ccFromSCPVOff +from .SCFromCCPVOff import scFromCCPVOff def coordConv( fromPos, fromSys, fromDate, toSys, toDate, diff --git a/python/RO/Astro/Sph/DCFromSC.py b/python/RO/Astro/Sph/DCFromSC.py index c864fb4..9c9f533 100755 --- a/python/RO/Astro/Sph/DCFromSC.py +++ b/python/RO/Astro/Sph/DCFromSC.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: 2002-07-23 R Owen. @@ -7,7 +7,7 @@ """ __all__ = ["dcFromSC"] -from CCFromSC import ccFromSC +from .CCFromSC import ccFromSC def dcFromSC(pos): """Convert spherical coordinates to direction cosines, i.e. a unit vector. diff --git a/python/RO/Astro/Sph/HADecFromAzAlt.py b/python/RO/Astro/Sph/HADecFromAzAlt.py index 0fb3f09..84fdec3 100755 --- a/python/RO/Astro/Sph/HADecFromAzAlt.py +++ b/python/RO/Astro/Sph/HADecFromAzAlt.py @@ -1,12 +1,12 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["haDecFromAzAlt"] import RO.MathUtil import RO.SysConst -from DCFromSC import dcFromSC -from SCFromDC import scFromDC +from .DCFromSC import dcFromSC +from .SCFromDC import scFromDC from RO.Astro import Cnv def haDecFromAzAlt (azAlt, lat): @@ -50,7 +50,7 @@ def haDecFromAzAlt (azAlt, lat): if __name__ == "__main__": - from AngSep import angSep + from .AngSep import angSep MaxErrArcSec = 1e-6 # max error on sky, in arc seconds print("testing haDecFromAzAlt") # test data is formatted as follows: diff --git a/python/RO/Astro/Sph/SCFromCC.py b/python/RO/Astro/Sph/SCFromCC.py index b9825b7..8941096 100755 --- a/python/RO/Astro/Sph/SCFromCC.py +++ b/python/RO/Astro/Sph/SCFromCC.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["scFromCC"] diff --git a/python/RO/Astro/Sph/SCFromCCPV.py b/python/RO/Astro/Sph/SCFromCCPV.py index edf7c56..dae6490 100755 --- a/python/RO/Astro/Sph/SCFromCCPV.py +++ b/python/RO/Astro/Sph/SCFromCCPV.py @@ -1,11 +1,11 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["scFromCCPV"] import math import RO.PhysConst -from SCFromCC import scFromCC +from .SCFromCC import scFromCC # Constants _ASPerCy_Per_RadPerYear = 100.0 * RO.PhysConst.ArcSecPerDeg / RO.PhysConst.RadPerDeg diff --git a/python/RO/Astro/Sph/SCFromCCPVOff.py b/python/RO/Astro/Sph/SCFromCCPVOff.py index d9f0875..5140863 100755 --- a/python/RO/Astro/Sph/SCFromCCPVOff.py +++ b/python/RO/Astro/Sph/SCFromCCPVOff.py @@ -1,11 +1,11 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["scFromCCPVOff"] -from AngSideAng import angSideAng -from SCFromCCPV import scFromCCPV -from SCFromCC import scFromCC +from .AngSideAng import angSideAng +from .SCFromCCPV import scFromCCPV +from .SCFromCC import scFromCC def scFromCCPVOff(p, v, offP): """ diff --git a/python/RO/Astro/Sph/SCFromDC.py b/python/RO/Astro/Sph/SCFromDC.py index 9172260..609c283 100755 --- a/python/RO/Astro/Sph/SCFromDC.py +++ b/python/RO/Astro/Sph/SCFromDC.py @@ -1,9 +1,9 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["scFromDC"] -from SCFromCC import scFromCC +from .SCFromCC import scFromCC def scFromDC(p): """Convert direction cosines or any cartesian vector to spherical coordinates. diff --git a/python/RO/Astro/Sph/__init__.py b/python/RO/Astro/Sph/__init__.py index b7787ec..42179c5 100644 --- a/python/RO/Astro/Sph/__init__.py +++ b/python/RO/Astro/Sph/__init__.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + """ Astronomical math in spherical coordinates. Most coordinate conversions are in the Cnv package, diff --git a/python/RO/Astro/Tm/EpJFromMJD.py b/python/RO/Astro/Tm/EpJFromMJD.py index b7c58c4..d41909f 100755 --- a/python/RO/Astro/Tm/EpJFromMJD.py +++ b/python/RO/Astro/Tm/EpJFromMJD.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, absolute_import + __all__ = ["epJFromMJD"] diff --git a/python/RO/Astro/Tm/GMSTFromUT1.py b/python/RO/Astro/Tm/GMSTFromUT1.py index 6a755df..6fd860c 100755 --- a/python/RO/Astro/Tm/GMSTFromUT1.py +++ b/python/RO/Astro/Tm/GMSTFromUT1.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["gmstFromUT1"] diff --git a/python/RO/Astro/Tm/ISODate.py b/python/RO/Astro/Tm/ISODate.py index 57c768a..46ca887 100755 --- a/python/RO/Astro/Tm/ISODate.py +++ b/python/RO/Astro/Tm/ISODate.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Routines to format date and time as ISO date History: diff --git a/python/RO/Astro/Tm/LASTFromUT1.py b/python/RO/Astro/Tm/LASTFromUT1.py index 42f0040..51df90a 100644 --- a/python/RO/Astro/Tm/LASTFromUT1.py +++ b/python/RO/Astro/Tm/LASTFromUT1.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + __all__ = ["lastFromUT1"] diff --git a/python/RO/Astro/Tm/LMSTFromUT1.py b/python/RO/Astro/Tm/LMSTFromUT1.py index 6aa0358..8844930 100644 --- a/python/RO/Astro/Tm/LMSTFromUT1.py +++ b/python/RO/Astro/Tm/LMSTFromUT1.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + __all__ = ["lmstFromUT1"] diff --git a/python/RO/Astro/Tm/MJDFromEpJ.py b/python/RO/Astro/Tm/MJDFromEpJ.py index 99d47c9..82ad6fc 100755 --- a/python/RO/Astro/Tm/MJDFromEpJ.py +++ b/python/RO/Astro/Tm/MJDFromEpJ.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + __all__ = ["mjdFromEpJ"] diff --git a/python/RO/Astro/Tm/MJDFromPyTuple.py b/python/RO/Astro/Tm/MJDFromPyTuple.py index 9923eb9..3b7006e 100755 --- a/python/RO/Astro/Tm/MJDFromPyTuple.py +++ b/python/RO/Astro/Tm/MJDFromPyTuple.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["mjdFromPyTuple"] diff --git a/python/RO/Astro/Tm/TAI.py b/python/RO/Astro/Tm/TAI.py index 918d366..cedae2d 100644 --- a/python/RO/Astro/Tm/TAI.py +++ b/python/RO/Astro/Tm/TAI.py @@ -1,4 +1,4 @@ -from __future__ import division, absolute_import + """Functions to convert to/from TAI History: diff --git a/python/RO/Astro/Tm/UTCFromPySec.py b/python/RO/Astro/Tm/UTCFromPySec.py index 17acfad..bad5c5b 100644 --- a/python/RO/Astro/Tm/UTCFromPySec.py +++ b/python/RO/Astro/Tm/UTCFromPySec.py @@ -1,4 +1,4 @@ -from __future__ import division, absolute_import + """Functions to convert python seconds <-> UTC and to compensate for clock error. History: diff --git a/python/RO/Astro/Tm/__init__.py b/python/RO/Astro/Tm/__init__.py index 3a76af2..704130d 100644 --- a/python/RO/Astro/Tm/__init__.py +++ b/python/RO/Astro/Tm/__init__.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + """Time routines for Astronomy The heart of these routines is software written by Pat Wallace. diff --git a/python/RO/Astro/llv/__init__.py b/python/RO/Astro/llv/__init__.py index 2674840..c79d56a 100644 --- a/python/RO/Astro/llv/__init__.py +++ b/python/RO/Astro/llv/__init__.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + """Low-level routines. Most of these were written by Pat Wallace in FORTRAN diff --git a/python/RO/Astro/llv/epb.py b/python/RO/Astro/llv/epb.py index 2e1d5a7..e8341f4 100755 --- a/python/RO/Astro/llv/epb.py +++ b/python/RO/Astro/llv/epb.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["epb"] diff --git a/python/RO/Astro/llv/epb2d.py b/python/RO/Astro/llv/epb2d.py index 5c2281f..63602fb 100755 --- a/python/RO/Astro/llv/epb2d.py +++ b/python/RO/Astro/llv/epb2d.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["epb2d"] diff --git a/python/RO/Astro/llv/epj.py b/python/RO/Astro/llv/epj.py index 21a84eb..76f9911 100755 --- a/python/RO/Astro/llv/epj.py +++ b/python/RO/Astro/llv/epj.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["epj"] diff --git a/python/RO/Astro/llv/epj2d.py b/python/RO/Astro/llv/epj2d.py index 2e52da5..f722694 100755 --- a/python/RO/Astro/llv/epj2d.py +++ b/python/RO/Astro/llv/epj2d.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["epj2d"] diff --git a/python/RO/Astro/llv/eqeqx.py b/python/RO/Astro/llv/eqeqx.py index 756f8c9..652f6a3 100755 --- a/python/RO/Astro/llv/eqeqx.py +++ b/python/RO/Astro/llv/eqeqx.py @@ -1,11 +1,11 @@ #!/usr/bin/env python -from __future__ import division, print_function + __all__ = ["eqeqx"] import math import RO.PhysConst -from nutc import nutc +from .nutc import nutc _ArcSecPerRev = RO.PhysConst.ArcSecPerDeg * 360.0 diff --git a/python/RO/Astro/llv/etrms.py b/python/RO/Astro/llv/etrms.py index 3f0f244..ecd7958 100755 --- a/python/RO/Astro/llv/etrms.py +++ b/python/RO/Astro/llv/etrms.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: P.T.Wallace Starlink 10 April 1990 diff --git a/python/RO/Astro/llv/euler.py b/python/RO/Astro/llv/euler.py index fd75b6a..8002cee 100755 --- a/python/RO/Astro/llv/euler.py +++ b/python/RO/Astro/llv/euler.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: P.T.Wallace Starlink November 1988 diff --git a/python/RO/Astro/llv/evp.py b/python/RO/Astro/llv/evp.py index a540d1c..fc78270 100755 --- a/python/RO/Astro/llv/evp.py +++ b/python/RO/Astro/llv/evp.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: P.t.Wallace Starlink 21 November 1994 @@ -10,8 +10,8 @@ from math import sin, cos, pi, sqrt, fmod import numpy -from prec import prec -from epj import epj +from .prec import prec +from .epj import epj # Constants TWOPI = pi * 2.0 diff --git a/python/RO/Astro/llv/geoc.py b/python/RO/Astro/llv/geoc.py index 5121483..7882bdd 100755 --- a/python/RO/Astro/llv/geoc.py +++ b/python/RO/Astro/llv/geoc.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["geoc"] diff --git a/python/RO/Astro/llv/mappa.py b/python/RO/Astro/llv/mappa.py index 5aa8499..0ea3f18 100755 --- a/python/RO/Astro/llv/mappa.py +++ b/python/RO/Astro/llv/mappa.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: P.T.Wallace Starlink 21 July 1994 @@ -9,10 +9,10 @@ __all__ = ["mappa"] from math import sqrt -from vn import vn -from evp import evp -from prenut import prenut -from epj import epj +from .vn import vn +from .evp import evp +from .prenut import prenut +from .epj import epj # Constants # Light time for 1 au (sec) diff --git a/python/RO/Astro/llv/nut.py b/python/RO/Astro/llv/nut.py index 63b33c6..7af6f23 100755 --- a/python/RO/Astro/llv/nut.py +++ b/python/RO/Astro/llv/nut.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: P.T.Wallace Starlink 1 January 1993 @@ -8,8 +8,8 @@ """ __all__ = ["nut"] -from nutc import nutc -from euler import euler +from .nutc import nutc +from .euler import euler def nut(tdb): """ diff --git a/python/RO/Astro/llv/nutc.py b/python/RO/Astro/llv/nutc.py index 316baae..258e067 100755 --- a/python/RO/Astro/llv/nutc.py +++ b/python/RO/Astro/llv/nutc.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + __all__ = ["nutc"] diff --git a/python/RO/Astro/llv/prebn.py b/python/RO/Astro/llv/prebn.py index 0ef10f3..2788cbe 100755 --- a/python/RO/Astro/llv/prebn.py +++ b/python/RO/Astro/llv/prebn.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: P.T.Wallace Starlink 30 December 1992 @@ -11,7 +11,7 @@ import numpy import RO.PhysConst -from euler import euler +from .euler import euler def prebn(bep0, bep1): """ diff --git a/python/RO/Astro/llv/prec.py b/python/RO/Astro/llv/prec.py index e6d0e6a..b6776ff 100755 --- a/python/RO/Astro/llv/prec.py +++ b/python/RO/Astro/llv/prec.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: P.T.Wallace Starlink 10 July 1994 @@ -9,7 +9,7 @@ __all__ = ["prec"] import RO.PhysConst -from euler import euler +from .euler import euler def prec(begEpoch, endEpoch): """ diff --git a/python/RO/Astro/llv/prenut.py b/python/RO/Astro/llv/prenut.py index 6d1a67d..b702e80 100755 --- a/python/RO/Astro/llv/prenut.py +++ b/python/RO/Astro/llv/prenut.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: P.T.Wallace Starlink April 1987 @@ -9,9 +9,9 @@ __all__ = ["prenut"] import numpy -from prec import prec -from nut import nut -from epj import epj +from .prec import prec +from .nut import nut +from .epj import epj def prenut(epoch, mjd): """ diff --git a/python/RO/Astro/llv/vn.py b/python/RO/Astro/llv/vn.py index 5d91b20..c27355f 100755 --- a/python/RO/Astro/llv/vn.py +++ b/python/RO/Astro/llv/vn.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ History: P.T.Wallace Starlink November 1984 diff --git a/python/RO/Astro/runTests.py b/python/RO/Astro/runTests.py index 521ff7a..89dfe97 100755 --- a/python/RO/Astro/runTests.py +++ b/python/RO/Astro/runTests.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ Run Astro test code in Astro package. diff --git a/python/RO/BitDescr.py b/python/RO/BitDescr.py index ac17a0f..6c74ef9 100755 --- a/python/RO/BitDescr.py +++ b/python/RO/BitDescr.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Handles the bits set in a word such as a status word """ __all__ = ["getDescr"] diff --git a/python/RO/CanvasUtil.py b/python/RO/CanvasUtil.py index fa772bc..5e88979 100755 --- a/python/RO/CanvasUtil.py +++ b/python/RO/CanvasUtil.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Utilities to help in use of Tk canvasses. History: @@ -22,7 +22,7 @@ __all__ = ["ctrCircle", "ctrPlus", "ctrX", "radialLine", "Spiral"] import math -import Tkinter +import tkinter import RO.MathUtil def ctrCircle(cnv, xpos, ypos, rad, width = 1, **kargs): @@ -256,7 +256,7 @@ def angToXY(self, ang, doLimit=1): from RO.Wdg.PythonTk import PythonTk root = PythonTk() - cnv = Tkinter.Canvas (root, width=201, height=201) + cnv = tkinter.Canvas (root, width=201, height=201) cnv.pack() ctrPlus (cnv, 80, 80, 10, 5) ctrPlus (cnv, 100, 80, 10, 5, 5) diff --git a/python/RO/CnvUtil.py b/python/RO/CnvUtil.py index fb8ca94..7bc95d0 100755 --- a/python/RO/CnvUtil.py +++ b/python/RO/CnvUtil.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Value conversion functions. These are mostly used for converting string representations of values @@ -20,7 +20,7 @@ 2009-07-19 ROwen Added posFromPVT. 2015-09-24 ROwen Replace "== None" with "is None" to future-proof array tests and modernize the code. """ -import SeqUtil +from . import SeqUtil _FalseValues = set((False, 0, "0", "f", "false", "no", "off", None)) _TrueValues = set((True, 1, "1", "t", "true", "yes", "on")) @@ -41,7 +41,7 @@ def asASCII(val): """ # The inner "str" converts objects with str representations to strings. # The outer str converts the unicode string to a normal string. - return str(unicode(str(val), "ascii")) + return str(str(str(val), "ascii")) def asBool(val): """Converts typical human-readable boolean values to True or False @@ -261,7 +261,7 @@ def asStr(val): try: return str(val) except ValueError: - return unicode(val) + return str(val) class StrCnv(object): """Similar to str but with an optional substitution dictionary. @@ -291,7 +291,7 @@ def __init__(self, subsDict=None): """ self.subsDict = {} if subsDict: - for key, val in subsDict.iteritems(): + for key, val in subsDict.items(): self.subsDict[key.lower()] = val def __call__(self, key): diff --git a/python/RO/Comm/BaseSocket.py b/python/RO/Comm/BaseSocket.py index 7250638..0d9d168 100644 --- a/python/RO/Comm/BaseSocket.py +++ b/python/RO/Comm/BaseSocket.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Base class for sockets using event-driven programming. The intention is to work with TCPConnection and all the infrastructure that uses it. diff --git a/python/RO/Comm/BrowseURL.py b/python/RO/Comm/BrowseURL.py index ddcdd97..32df339 100644 --- a/python/RO/Comm/BrowseURL.py +++ b/python/RO/Comm/BrowseURL.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Open a URL in the user's default browser. The URL is opened in a background thread. @@ -10,7 +10,7 @@ __all__ = ["browseURL"] import threading -import urlparse +import urllib.parse import webbrowser class _BrowseURLThread(threading.Thread): @@ -29,10 +29,10 @@ def run(self): # failed! if this is a file URL with an anchor, # try again without the anchor - urlTuple = urlparse.urlparse(url) + urlTuple = urllib.parse.urlparse(url) if urlTuple[0] == "file" and urlTuple[-1] != '': urlTuple = urlTuple[0:-1] + ('',) - url = urlparse.urlunparse(urlTuple) + url = urllib.parse.urlunparse(urlTuple) if not url: return try: diff --git a/python/RO/Comm/FTPGet.py b/python/RO/Comm/FTPGet.py index b01a706..6c93f4f 100644 --- a/python/RO/Comm/FTPGet.py +++ b/python/RO/Comm/FTPGet.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Retrieve a remote file via ftp to a local file. The retrieval occurs in a background thread. @@ -43,7 +43,7 @@ import os import sys -import urlparse +import urllib.parse import threading import ftplib @@ -117,7 +117,7 @@ def __init__(self, self.password = password or "abc@def.org" if dispStr is None: - self.dispStr = urlparse.urljoin("ftp://" + self.host, self.fromPath) + self.dispStr = urllib.parse.urljoin("ftp://" + self.host, self.fromPath) else: self.dispStr = dispStr diff --git a/python/RO/Comm/Generic.py b/python/RO/Comm/Generic.py index 0c8bb7a..3c2e7bf 100755 --- a/python/RO/Comm/Generic.py +++ b/python/RO/Comm/Generic.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Generic classes for event-based communication and timing. Generic in the sense that it supports both Twisted framework and Tcl sockets. @@ -166,8 +166,8 @@ def __repr__(self): if __name__ == "__main__": - import Tkinter - root = Tkinter.Tk() + import tkinter + root = tkinter.Tk() root.withdraw() setFramework("tk") # since it is almost always installed clientSocket = None diff --git a/python/RO/Comm/HTTPGet.py b/python/RO/Comm/HTTPGet.py index c214e99..adc2eca 100755 --- a/python/RO/Comm/HTTPGet.py +++ b/python/RO/Comm/HTTPGet.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Retrieve a remote file via http to a local file. Note: at exit attempts to abort all outstanding transfers and delete the output files. @@ -46,7 +46,7 @@ import os import sys import time -import Tkinter +import tkinter import RO.AddCallback import RO.StringUtil import RO.TkUtil @@ -94,7 +94,7 @@ def abortAll(self): if not self.transferDict: return - transferList = self.transferDict.keys() + transferList = list(self.transferDict.keys()) for xfer in transferList: if _DebugExit: print("HTTGet._Exit: aborting %s" % (xfer,)) @@ -180,7 +180,7 @@ def __init__(self, timeLim = None, ): if self._tkApp is None: - self._tkApp = Tkinter.Frame().tk + self._tkApp = tkinter.Frame().tk self.fromURL = fromURL self.toPath = toPath self.isBinary = isBinary @@ -259,7 +259,7 @@ def start(self): self._createdFile = True if self.isBinary: self._tkApp.call('fconfigure', self._tclFile, "-encoding", "binary", "-translation", "binary") - except Tkinter.TclError as e: + except tkinter.TclError as e: raise RuntimeError("Could not open %r: %s" % (self.toPath, e)) # start http transfer @@ -510,7 +510,7 @@ def _toPrep(self): raise RuntimeError("%r is a file, not a directory" % (toDir,)) if __name__ == "__main__": - root = Tkinter.Tk() + root = tkinter.Tk() testURL = "http://www.astro.washington.edu/" outFile = "httpget_test.html" diff --git a/python/RO/Comm/HubConnection.py b/python/RO/Comm/HubConnection.py index 8b12d88..9bcffe6 100755 --- a/python/RO/Comm/HubConnection.py +++ b/python/RO/Comm/HubConnection.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A version of RO.TCPConnection that can negotiate a connection with the APO Hub. This is a good example of the sort of connection used by KeyDispatcher. @@ -40,7 +40,7 @@ shaClass = sha.sha import sys -from TCPConnection import TCPConnection +from .TCPConnection import TCPConnection import RO.ParseMsg import RO.StringUtil @@ -230,9 +230,9 @@ def writeLine(self, str): if __name__ == "__main__": - import Tkinter + import tkinter import RO.Wdg - root = Tkinter.Tk() + root = tkinter.Tk() host = "hub35m.apo.nmsu.edu" port = 9877 @@ -257,12 +257,12 @@ def doConnect(host, port): class PasswordDialog(RO.Wdg.ModalDialogBase): def body(self, master): - Tkinter.Label(master, text="Program ID:").grid(row=0, column=0) - Tkinter.Label(master, text="Password :").grid(row=1, column=0) + tkinter.Label(master, text="Program ID:").grid(row=0, column=0) + tkinter.Label(master, text="Password :").grid(row=1, column=0) - self.nameEntry = Tkinter.Entry(master) + self.nameEntry = tkinter.Entry(master) self.nameEntry.grid(row=0, column=1) - self.pwdEntry = Tkinter.Entry(master, show="*") + self.pwdEntry = tkinter.Entry(master, show="*") self.pwdEntry.grid(row=1, column=1) return self.nameEntry # return the item that gets initial focus @@ -282,15 +282,15 @@ def setResult(self): ) - Tkinter.Label(text="Send:").pack(side="left") - sendText = Tkinter.Entry(root) + tkinter.Label(text="Send:").pack(side="left") + sendText = tkinter.Entry(root) sendText.pack(fill="x", expand="yes", side="left") sendText.focus_set() def sendCmd (evt): try: astr = sendText.get() - sendText.delete(0,Tkinter.END) + sendText.delete(0,tkinter.END) myConn.writeLine(astr) except Exception as e: sys.stderr.write ("Could not extract or send: %s\nError: %s\n" % (astr, e)) diff --git a/python/RO/Comm/TCPConnection.py b/python/RO/Comm/TCPConnection.py index 02451c8..ab484ca 100755 --- a/python/RO/Comm/TCPConnection.py +++ b/python/RO/Comm/TCPConnection.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Reconnectable versions of TCPSocket. All permit disconnection and reconnection and the base class offers support for @@ -415,8 +415,8 @@ def __str__(self): if __name__ == "__main__": """Demo using a simple echo server. """ - import Tkinter - root = Tkinter.Tk() + import tkinter + root = tkinter.Tk() root.withdraw() from RO.Comm.Generic import TCPServer from RO.TkUtil import Timer @@ -432,7 +432,7 @@ def __str__(self): "string with 3 quoted nulls: 1 \\0 2 \\0 3 \\0 end", '"quoted string followed by carriage return"\r', '', - u"unicode string", + "unicode string", "string with newline: \n end", "string with carriage return: \r end", "quit", diff --git a/python/RO/Comm/TCPEcho.py b/python/RO/Comm/TCPEcho.py index 2ba72ed..72a137c 100755 --- a/python/RO/Comm/TCPEcho.py +++ b/python/RO/Comm/TCPEcho.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """A simple TCP echo server. Based on the SocketServer example in Python Essential Reference. @@ -9,9 +9,9 @@ 2004-07-09 ROwen 2007-01-03 ROwen Fixed execution code. """ -import SocketServer +import socketserver -class _EchoHandler(SocketServer.BaseRequestHandler): +class _EchoHandler(socketserver.BaseRequestHandler): def handle(self): f = self.request.makefile() for line in f: @@ -30,7 +30,7 @@ def startServer(port, multi=False): else just serves one user and quits when that user is done """ - serv = SocketServer.TCPServer(("", port), _EchoHandler) + serv = socketserver.TCPServer(("", port), _EchoHandler) if multi: print("Starting multiple-user echo server on port", port) print("Send 'quit' to end a connection") diff --git a/python/RO/Comm/TkSerial.py b/python/RO/Comm/TkSerial.py index 67d6c36..307e8c0 100644 --- a/python/RO/Comm/TkSerial.py +++ b/python/RO/Comm/TkSerial.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Serial connections optimized for use with Tkinter GUIs. Known issues: @@ -31,7 +31,7 @@ import sys import traceback -import Tkinter +import tkinter import RO.SeqUtil import RO.TkUtil try: @@ -95,7 +95,7 @@ def _clearCallbacks(self): Called just after the serial is closed. """ #print "%s._clearCallbacks()" % (self,) - for tclFunc in self._tkCallbackDict.itervalues(): + for tclFunc in self._tkCallbackDict.values(): tclFunc.deregister() self._tkCallbackDict = dict() self._stateCallback = None @@ -185,7 +185,7 @@ def __init__(self, ) self._readCallback = readCallback - self._tk = Tkinter.StringVar()._tk + self._tk = tkinter.StringVar()._tk self._chanID = 0 try: @@ -196,7 +196,7 @@ def __init__(self, cfgArgs = [ "-blocking", 0, ] - for key, value in chanKArgs.iteritems(): + for key, value in chanKArgs.items(): cfgArgs += ["-" + key, value] cfgArgs += ["-mode", "%s,%s,%s,%s" % (int(baud), parity, int(dataBits), int(stopBits))] if buffering is not None: @@ -212,7 +212,7 @@ def __init__(self, # and is just used to detect state self._setSockCallback(self._doRead) - except Tkinter.TclError as e: + except tkinter.TclError as e: raise RuntimeError(e) def close(self, isOK=True, reason=None): @@ -368,7 +368,7 @@ def _setSockCallback(self, callFunc=None, doWrite=False): try: self._tk.call('fileevent', self._chanID, typeStr, tkFuncName) - except Tkinter.TclError as e: + except tkinter.TclError as e: if tclFunc: tclFunc.deregister() raise RuntimeError(e) diff --git a/python/RO/Comm/TkSocket.py b/python/RO/Comm/TkSocket.py index 23781da..c2d4e00 100755 --- a/python/RO/Comm/TkSocket.py +++ b/python/RO/Comm/TkSocket.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Sockets optimized for use with Tkinter GUIs. TkSocket allows nonblocking event-driven operation: @@ -95,7 +95,7 @@ import re import sys import traceback -import Tkinter +import tkinter import RO.TkUtil from RO.Comm.BaseSocket import BaseSocket, BaseServer, nullCallback @@ -120,7 +120,7 @@ def __init__(self, # typeStr is one of "readable" or "writable" # tclFunc is a tcl-wrapped function, an instance of RO.TkUtil.TclFunc self._callbackDict = dict() - self._readVar = Tkinter.StringVar() + self._readVar = tkinter.StringVar() self._tk = self._readVar._tk if tkSock: @@ -128,7 +128,7 @@ def __init__(self, elif sockArgs: try: self._tkSocket = self._tk.call('socket', *sockArgs) - except Tkinter.TclError as e: + except tkinter.TclError as e: raise RuntimeError(e) else: raise RuntimeError("Must specify tkSock or sockArgs") @@ -143,7 +143,7 @@ def __init__(self, #print "name=%s, configArgs=%s" % (name, configArgs) self._tk.call('fconfigure', self._tkSocket, *configArgs) - except Tkinter.TclError as e: + except tkinter.TclError as e: raise RuntimeError(e) @property @@ -180,7 +180,7 @@ def clearCallbacks(self): """Clear any callbacks added by this class. Called just after the socket is closed. """ - for tclFunc in self._callbackDict.itervalues(): + for tclFunc in self._callbackDict.values(): tclFunc.deregister() self._callbackDict = dict() @@ -206,7 +206,7 @@ def setCallback(self, callFunc=None, doWrite=False): try: self._tk.call('fileevent', self._tkSocket, typeStr, tkFuncName) - except Tkinter.TclError as e: + except tkinter.TclError as e: if tclFunc: tclFunc.deregister() raise RuntimeError(e) @@ -301,7 +301,7 @@ def __init__(self, # and is just used to detect state self._tkSocketWrapper.setCallback(self._doRead, doWrite=False) self._tkSocketWrapper.setCallback(self._doConnect, doWrite=True) - except Tkinter.TclError as e: + except tkinter.TclError as e: raise RuntimeError(e) self._setState(self.Connecting) @@ -549,7 +549,7 @@ def _getArgStr(self): if __name__ == "__main__": """Demo using a simple echo server. """ - root = Tkinter.Tk() + root = tkinter.Tk() root.withdraw() from RO.TkUtil import Timer diff --git a/python/RO/Comm/TwistedSocket.py b/python/RO/Comm/TwistedSocket.py index adc5cd4..b7ed2ec 100755 --- a/python/RO/Comm/TwistedSocket.py +++ b/python/RO/Comm/TwistedSocket.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """BasicSocket wrapper that works with the Twisted framework The intention is to work with TCPConnection and all the infrastructure that uses it. diff --git a/python/RO/Comm/VMSTelnet.py b/python/RO/Comm/VMSTelnet.py index 2d67a2d..2e7fb20 100755 --- a/python/RO/Comm/VMSTelnet.py +++ b/python/RO/Comm/VMSTelnet.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """VMS telnet connection. May work with other operating systems. Note: not very well tested, since I no longer use it. @@ -31,7 +31,7 @@ import sys import RO.Wdg -from TCPConnection import TCPConnection +from .TCPConnection import TCPConnection class VMSTelnet(TCPConnection): """A telnet connection that negotiates the telnet protocol @@ -198,8 +198,8 @@ def writeLine(self, str): if __name__ == "__main__": - import Tkinter - root = Tkinter.Tk() + import tkinter + root = tkinter.Tk() host = "tccdev" username = "TCC" @@ -220,16 +220,16 @@ def stateCallback (sock): stateCallback = stateCallback, ) - sendText = Tkinter.Entry(root) - sendText.pack(fill=Tkinter.X, expand=Tkinter.YES) + sendText = tkinter.Entry(root) + sendText.pack(fill=tkinter.X, expand=tkinter.YES) sendText.focus_set() - Tkinter.Button(root, text="Disconnect", command=myConn.disconnect).pack() + tkinter.Button(root, text="Disconnect", command=myConn.disconnect).pack() def sendCmd (evt): try: astr = sendText.get() - sendText.delete(0, Tkinter.END) + sendText.delete(0, tkinter.END) myConn.writeLine(astr) except Exception as e: sys.stderr.write ("Could not extract or send: %s\n" % (astr)) diff --git a/python/RO/Constants.py b/python/RO/Constants.py index ce5a093..24eb7a5 100644 --- a/python/RO/Constants.py +++ b/python/RO/Constants.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """Constants for the RO package, especially RO.Wdg. Supplies the following constants: @@ -26,7 +26,7 @@ """ __all__ = ['sevDebug', 'sevNormal', 'sevWarning', 'sevError', 'sevCritical', 'SevNameDict', 'NameSevDict'] -import urlparse +import urllib.parse from collections import OrderedDict # severity constants; numeric value increases with severity @@ -46,7 +46,7 @@ )) # ordered dictionary of severity name (lowercase): severity; order is least to most severe -NameSevDict = OrderedDict(zip(SevNameDict.values(), SevNameDict.keys())) +NameSevDict = OrderedDict(list(zip(list(SevNameDict.values()), list(SevNameDict.keys())))) # Call setHelpURLBase if you want to specify URLs relative to a base _HelpURLBase = "" @@ -59,7 +59,7 @@ def _joinHelpURL(urlSuffix=""): # print "_joinHelpURL(urlSuffix=%r)" % (urlSuffix,) global _HelpURLBase, _gotHelpURLBase _gotHelpURLBase = True - return urlparse.urljoin(_HelpURLBase, urlSuffix) + return urllib.parse.urljoin(_HelpURLBase, urlSuffix) def _setHelpURLBase(urlBase): """Set the base url for help urls. diff --git a/python/RO/CoordSys.py b/python/RO/CoordSys.py index a9779f4..8a3524b 100644 --- a/python/RO/CoordSys.py +++ b/python/RO/CoordSys.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """Basic information and utilities for dealing with coordinate systems. To do: diff --git a/python/RO/DS9.py b/python/RO/DS9.py index 2ebe273..e676aeb 100755 --- a/python/RO/DS9.py +++ b/python/RO/DS9.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + r""" Interface for viewing images with the ds9 image viewer. Loosely based on XPA, by Andrew Williams. @@ -168,6 +168,7 @@ _DirFromWhichToRunDS9 = None _DS9Path = None + def _addToPATH(newPath): """Add newPath to the PATH environment variable. Do nothing if newPath already in PATH. @@ -238,13 +239,12 @@ def _findUnixApp(appName): if errMsg: fullErrMsg = "'which %s' failed: %s" % (appName, errMsg) raise RuntimeError(fullErrMsg) - appPath = p.stdout.read() - if not appPath.startswith("/"): + appPath = p.stdout.read().strip(b'\n') + if not appPath.startswith(b"/"): raise RuntimeError("Could not find %s on your PATH" % (appName,)) finally: p.stdout.close() p.stderr.close() - return appPath def _findDS9AndXPA(): @@ -512,7 +512,7 @@ def _formatOptions(kargs): """Returns a string: "key1=val1,key2=val2,..." (where keyx and valx are string representations) """ - arglist = ["%s=%s" % keyVal for keyVal in kargs.iteritems()] + arglist = ["%s=%s" % keyVal for keyVal in kargs.items()] return "%s" % (",".join(arglist)) @@ -656,7 +656,7 @@ def showArray(self, arr, **kargs): dataFunc = arr.tofile, ) - for keyValue in kargs.iteritems(): + for keyValue in kargs.items(): self.xpaset(cmd=" ".join(keyValue)) def showFITSFile(self, fname, **kargs): @@ -674,9 +674,9 @@ def showFITSFile(self, fname, **kargs): # remove array info keywords from kargs; we compute all that arrKeys = _splitDict(kargs, _ArrayKeys) if arrKeys: - raise RuntimeError("Array info not allowed; rejected keywords: %s" % arrKeys.keys()) + raise RuntimeError("Array info not allowed; rejected keywords: %s" % list(arrKeys.keys())) - for keyValue in kargs.iteritems(): + for keyValue in kargs.items(): self.xpaset(cmd=" ".join(keyValue)) def xpaget(self, cmd): diff --git a/python/RO/InputCont.py b/python/RO/InputCont.py index a80e015..446780b 100755 --- a/python/RO/InputCont.py +++ b/python/RO/InputCont.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -from __future__ import absolute_import, division, print_function + """Containers (wrappers) for RO.Wdg input widgets, including Entry, Checkbutton and OptionMenu. @@ -476,7 +476,7 @@ def setValueList(self, valList): # we want just one callback instead of one per container, so disable callbacks until finished with self._disableCallbacksContext(): - for wdg, val in itertools.izip(self._wdgList, valList): + for wdg, val in zip(self._wdgList, valList): wdg.set(val) self._doCallbacks() @@ -550,7 +550,7 @@ def __init__ (self, raise ValueError('invalid widget name %r; cannot start with negStr=%r' % (name, self._negStr)) # generate widget dict and widget name getter - self._wdgDict = RO.Alg.OrderedDict(zip(self._wdgNames, self._wdgList)) + self._wdgDict = RO.Alg.OrderedDict(list(zip(self._wdgNames, self._wdgList))) self._wdgNameGetter = RO.Alg.MatchList(wdgNames, abbrevOK=True, ignoreCase=True) def getDefValueList(self): @@ -561,7 +561,7 @@ def fmtFunc(name, wdg): return name else: return self._negStr + name - return [fmtFunc(name, wdg) for name, wdg in self._wdgDict.iteritems()] + return [fmtFunc(name, wdg) for name, wdg in self._wdgDict.items()] def getValueList(self, omitDef=None): """Get the value as a list: [name1, negStr + name2, ...]. @@ -578,10 +578,10 @@ def fmtFunc(name, wdg): else: return self._negStr + name if omitDef: - return [fmtFunc(name, wdg) for name, wdg in self._wdgDict.iteritems() \ + return [fmtFunc(name, wdg) for name, wdg in self._wdgDict.items() \ if wdg.getDefault() != wdg.getString()] else: - return [fmtFunc(name, wdg) for name, wdg in self._wdgDict.iteritems()] + return [fmtFunc(name, wdg) for name, wdg in self._wdgDict.items()] def getWdgByName(self, name): """Return a widget given its name. @@ -670,11 +670,11 @@ def __init__ (self, self._wdgNames = wdgNames # generate widget dict and widget name getter - self._wdgDict = RO.Alg.OrderedDict(zip(self._wdgNames, self._wdgList)) + self._wdgDict = RO.Alg.OrderedDict(list(zip(self._wdgNames, self._wdgList))) self._wdgNameGetter = RO.Alg.MatchList(wdgNames, abbrevOK=True, ignoreCase=True) # verify that all widgets have default=checked - for name, wdg in self._wdgDict.iteritems(): + for name, wdg in self._wdgDict.items(): if not wdg.getDefBool(): raise ValueError("widget %s does not have default=checked" % (name,)) @@ -688,7 +688,7 @@ def getValueList(self, omitDef=None): """ if omitDef is None: omitDef = self._omitDef - valList = [name for name, wdg in self._wdgDict.iteritems() + valList = [name for name, wdg in self._wdgDict.items() if wdg.getBool()] if omitDef and len(valList) == len(self._wdgList): return [] @@ -914,7 +914,7 @@ def setValueList(self, valList): if __name__ == "__main__": - import Tkinter + import tkinter import RO.Wdg root = RO.Wdg.PythonTk() @@ -946,22 +946,22 @@ def setEnable(*args): doEnable = enableVar.get() cList.setEnable(doEnable) - hideVar = Tkinter.IntVar() + hideVar = tkinter.IntVar() hideVar.set(False) hideVar.trace_variable('w', doHide) - hideButton = Tkinter.Checkbutton (root, variable=hideVar, text='hide') + hideButton = tkinter.Checkbutton (root, variable=hideVar, text='hide') hideButton.pack() - enableVar = Tkinter.IntVar() + enableVar = tkinter.IntVar() enableVar.set(1) enableVar.trace_variable('w', setEnable) - enableButton = Tkinter.Checkbutton (root, variable=enableVar, text='Enable') + enableButton = tkinter.Checkbutton (root, variable=enableVar, text='Enable') enableButton.pack() - getButton = Tkinter.Button (root, command=printOptions, text='Print Options') + getButton = tkinter.Button (root, command=printOptions, text='Print Options') getButton.pack() - wdgFrame = Tkinter.Frame(root) + wdgFrame = tkinter.Frame(root) conts = ( WdgCont ( @@ -995,10 +995,10 @@ def setEnable(*args): callFunc = printCallback, ) - clearButton = Tkinter.Button (root, command=cList.clear, text='Clear') + clearButton = tkinter.Button (root, command=cList.clear, text='Clear') clearButton.pack() - defButton = Tkinter.Button (root, command=cList.restoreDefault, text='Default') + defButton = tkinter.Button (root, command=cList.restoreDefault, text='Default') defButton.pack() flatWdgList = cList.getWdgList() diff --git a/python/RO/KeyDispatcher.py b/python/RO/KeyDispatcher.py index 5741935..2b8a263 100755 --- a/python/RO/KeyDispatcher.py +++ b/python/RO/KeyDispatcher.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Sends commands (of type RO.KeyVariable.CmdVar) and dispatches replies to key variables (RO.KeyVariable.KeyVar and subclasses). @@ -248,7 +248,7 @@ def checkCmdTimeouts(self): # iterate over a copy of the values # so we can modify the dictionary while checking command timeouts - cmdVarIter = iter(self.cmdDict.values()) + cmdVarIter = iter(list(self.cmdDict.values())) self._checkRemCmdTimeouts(cmdVarIter) def dispatch(self, msgDict): @@ -279,7 +279,7 @@ def dispatch(self, msgDict): keyActor = actor[5:] else: keyActor = actor - for keywd, valueTuple in dataDict.iteritems(): + for keywd, valueTuple in dataDict.items(): dictKey = (keyActor, keywd.lower()) keyVarList = self.keyVarListDict.get(dictKey, []) for keyVar in keyVarList: @@ -482,7 +482,7 @@ def refreshAllVar(self, resetAll=True): # clear the refresh command dict # and invalidate all keyVars # (leave pending refresh commands alone; they will time out) - for keyVarList in self.keyVarListDict.values(): + for keyVarList in list(self.keyVarListDict.values()): for keyVar in keyVarList: keyVar.setNotCurrent() @@ -527,7 +527,7 @@ def _updateRefreshCmds(self): """Update the cache of refresh commands by scanning the keyVars. """ self.refreshCmdDict = {} - for keyVarList in self.keyVarListDict.itervalues(): + for keyVarList in self.keyVarListDict.values(): for keyVar in keyVarList: if keyVar.hasRefreshCmd(): refreshInfo = keyVar.getRefreshInfo() @@ -663,7 +663,7 @@ def _sendNextRefreshCmd(self, refreshCmdItemIter=None): if refreshCmdItemIter is None: self._updateRefreshCmds() - refreshCmdItemIter = self.refreshCmdDict.iteritems() + refreshCmdItemIter = iter(self.refreshCmdDict.items()) try: refreshCmdInfo, keyVarSet = next(refreshCmdItemIter) @@ -687,8 +687,8 @@ def _sendNextRefreshCmd(self, refreshCmdItemIter=None): if __name__ == "__main__": print("\nTesting RO.KeyDispatcher\n") - import Tkinter - root = Tkinter.Tk() + import tkinter + root = tkinter.Tk() kdb = KeyDispatcher() diff --git a/python/RO/KeyVariable.py b/python/RO/KeyVariable.py index 333a08f..a217125 100755 --- a/python/RO/KeyVariable.py +++ b/python/RO/KeyVariable.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """KeyVar and its cousins are used monitor data from the keyword dispatcher. Keyword data may trigger callbacks or automatically update RO.Wdg widgets. @@ -163,7 +163,7 @@ ":":("finished", RO.Constants.sevNormal), } # all message types -AllTypes = "".join(TypeDict.keys()) +AllTypes = "".join(list(TypeDict.keys())) # useful other message types DoneTypes = ":f!" FailTypes = "f!" @@ -399,7 +399,7 @@ def addROWdgSet (self, wdgSet, setDefault=False): class callWdgSet(object): def __init__(self, wdgSet): self.wdgSet = wdgSet - self.wdgInd = range(len(wdgSet)) + self.wdgInd = list(range(len(wdgSet))) def __call__(self, valueList, isCurrent, keyVar): for wdg, val in zip(self.wdgSet, valueList): wdg.setDefault(val, isCurrent=isCurrent, keyVar=keyVar) @@ -407,7 +407,7 @@ def __call__(self, valueList, isCurrent, keyVar): class callWdgSet(object): def __init__(self, wdgSet): self.wdgSet = wdgSet - self.wdgInd = range(len(wdgSet)) + self.wdgInd = list(range(len(wdgSet))) def __call__(self, valueList, isCurrent, keyVar): for wdg, val in zip(self.wdgSet, valueList): wdg.set(val, isCurrent=isCurrent, keyVar=keyVar) @@ -659,7 +659,7 @@ def addROWdgSet (self, wdgSet): class callWdgSet(object): def __init__(self, wdgSet): self.wdgSet = wdgSet - self.wdgInd = range(len(wdgSet)) + self.wdgInd = list(range(len(wdgSet))) def __call__(self, valueList, isCurrent, keyVar): for ind in self.wdgInd: wdgSet[ind].set(valueList[ind].getPos(), isCurrent=isCurrent, keyVar=keyVar) @@ -1095,7 +1095,7 @@ def setKeysRefreshCmd(self, getAllKeys = False): In case key variables with more than one actor have been produced, those for each actor get their own command. """ - for actor, keyVars in self._actorKeyVarsRefreshDict.iteritems(): + for actor, keyVars in self._actorKeyVarsRefreshDict.items(): if getAllKeys: refreshCmd = "getFor=%s" % (actor,) else: @@ -1112,12 +1112,12 @@ def setKeysRefreshCmd(self, getAllKeys = False): if __name__ == "__main__": - import Tkinter + import tkinter doBasic = True doFmt = True import RO.Astro.Tm - root = Tkinter.Tk() + root = tkinter.Tk() if doBasic: print("\nrunning basic variables test") diff --git a/python/RO/MathUtil.py b/python/RO/MathUtil.py index ebbe6ba..98d4c58 100644 --- a/python/RO/MathUtil.py +++ b/python/RO/MathUtil.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Math utilities by Russell Owen History: diff --git a/python/RO/OS/OSUtil.py b/python/RO/OS/OSUtil.py index 8b2a3df..e2c6942 100644 --- a/python/RO/OS/OSUtil.py +++ b/python/RO/OS/OSUtil.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Operating system utilities History: diff --git a/python/RO/OS/__init__.py b/python/RO/OS/__init__.py index 4ffbe6a..8e29a2e 100644 --- a/python/RO/OS/__init__.py +++ b/python/RO/OS/__init__.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + """Operating system utilties including: - Extensions to os.path for splitting a path into component pieces and searching for lists of files that match a particular criteria. diff --git a/python/RO/OS/getDirs.py b/python/RO/OS/getDirs.py index 6302ba2..0170f29 100755 --- a/python/RO/OS/getDirs.py +++ b/python/RO/OS/getDirs.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Get useful directories for Mac (X or Classic), unix or modern versions of Windows. Defines: @@ -86,12 +86,12 @@ try: # try Mac - from getMacDirs import getAppDirs, getAppSuppDirs, getDocsDir, getPrefsDirs + from .getMacDirs import getAppDirs, getAppSuppDirs, getDocsDir, getPrefsDirs PlatformName = 'mac' except ImportError: # try Windows try: - from getWinDirs import getAppDirs, getAppSuppDirs, getDocsDir, getPrefsDirs + from .getWinDirs import getAppDirs, getAppSuppDirs, getDocsDir, getPrefsDirs PlatformName = 'win' except ImportError: # assume Unix diff --git a/python/RO/OS/getMacDirs.py b/python/RO/OS/getMacDirs.py index eac7e36..9a8a668 100644 --- a/python/RO/OS/getMacDirs.py +++ b/python/RO/OS/getMacDirs.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Utilities for finding standard Mac directories. History: diff --git a/python/RO/OS/getWinDirs.py b/python/RO/OS/getWinDirs.py index 520fbd5..e8ad1c9 100644 --- a/python/RO/OS/getWinDirs.py +++ b/python/RO/OS/getWinDirs.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Determine the application data directory for Windows. Requires Mark Hammond's win32 extensions diff --git a/python/RO/PVT.py b/python/RO/PVT.py index 50c1b25..4deced7 100644 --- a/python/RO/PVT.py +++ b/python/RO/PVT.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """PVT implements a class to describe (position, velocity, time) triplets. History: diff --git a/python/RO/ParseMsg/GetHeader.py b/python/RO/ParseMsg/GetHeader.py index 5e2f6d3..fb62ba1 100755 --- a/python/RO/ParseMsg/GetHeader.py +++ b/python/RO/ParseMsg/GetHeader.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Parses the header from a keyword/variable string in various formats History: diff --git a/python/RO/ParseMsg/GetKeyword.py b/python/RO/ParseMsg/GetKeyword.py index 58de86b..80e59dc 100755 --- a/python/RO/ParseMsg/GetKeyword.py +++ b/python/RO/ParseMsg/GetKeyword.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ History: 2004-05-18 ROwen Modified test code to use astr instead of str diff --git a/python/RO/ParseMsg/GetString.py b/python/RO/ParseMsg/GetString.py index a2c5d24..625fb78 100755 --- a/python/RO/ParseMsg/GetString.py +++ b/python/RO/ParseMsg/GetString.py @@ -6,7 +6,7 @@ 2004-05-18 ROwen Modified test code to use astr instead of str. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. """ -from __future__ import absolute_import, division, print_function + import sys __all__ = ["getString"] diff --git a/python/RO/ParseMsg/GetValues.py b/python/RO/ParseMsg/GetValues.py index a15e278..4237425 100755 --- a/python/RO/ParseMsg/GetValues.py +++ b/python/RO/ParseMsg/GetValues.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Obtains all values (0 or more) associated with a keyword. History: @@ -17,7 +17,7 @@ __all__ = ["getValues"] import re -import GetString +from . import GetString _StartRE = re.compile(r"\s*(?P[=;])\s*(?:(?P\S)|$)") diff --git a/python/RO/ParseMsg/ParseData.py b/python/RO/ParseMsg/ParseData.py index 06c0a85..041a2a6 100755 --- a/python/RO/ParseMsg/ParseData.py +++ b/python/RO/ParseMsg/ParseData.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Parse a keyword-value message. History: @@ -13,8 +13,8 @@ """ __all__ = ["parseKeyValueData"] -from GetKeyword import getKeyword -from GetValues import getValues +from .GetKeyword import getKeyword +from .GetValues import getValues import RO.Alg def parseKeyValueData(astr): @@ -73,7 +73,7 @@ def parseKeyValueData(astr): try: dataDict = parseKeyValueData(astr) print("parseHubMsg(%r) = {" % (astr,)) - for key, value in dataDict.iteritems(): + for key, value in dataDict.items(): print(" %r: %r" % (key, value)) print("}") except Exception as e: diff --git a/python/RO/ParseMsg/ParseMsg.py b/python/RO/ParseMsg/ParseMsg.py index dce20f5..d2cfceb 100755 --- a/python/RO/ParseMsg/ParseMsg.py +++ b/python/RO/ParseMsg/ParseMsg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Parses a message of the form: header keywordValueData returning a dictionary. @@ -11,8 +11,8 @@ """ __all__ = ["parseHubMsg"] -from GetHeader import getHubHeader -from ParseData import parseKeyValueData +from .GetHeader import getHubHeader +from .ParseData import parseKeyValueData def parseHubMsg(astr): """Parses one message of the form: diff --git a/python/RO/ParseMsg/__init__.py b/python/RO/ParseMsg/__init__.py index e5a6e3b..1257821 100644 --- a/python/RO/ParseMsg/__init__.py +++ b/python/RO/ParseMsg/__init__.py @@ -1,3 +1,3 @@ -from __future__ import absolute_import + """ parse Hub messages and the like """ from .ParseMsg import * diff --git a/python/RO/Prefs/PrefEditor.py b/python/RO/Prefs/PrefEditor.py index cbf3d23..ab8b953 100755 --- a/python/RO/Prefs/PrefEditor.py +++ b/python/RO/Prefs/PrefEditor.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Widgets for editing individual preference variables. To Do: @@ -61,10 +61,10 @@ 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. """ import sys -import PrefVar -import Tkinter -import tkColorChooser -import tkFont +from . import PrefVar +import tkinter +import tkinter.colorchooser +import tkinter.font import RO.Alg import RO.Wdg from RO.TkUtil import Timer @@ -109,7 +109,7 @@ def __init__(self, self.prefVar = prefVar # create and set a variable to contain the edited value - self.editVar = Tkinter.StringVar() + self.editVar = tkinter.StringVar() self.editVar.set(self.prefVar.getValueStr()) # save initial value, in case we have to restore it @@ -125,18 +125,18 @@ def __init__(self, ("editWdg", "w"), ("unitsWdg", "w"), ) - self.labelWdg = Tkinter.Label(self.master, text = self.prefVar.name) + self.labelWdg = tkinter.Label(self.master, text = self.prefVar.name) self._addCtxMenu(self.labelWdg) - self.changedVar = Tkinter.StringVar() - self.changedWdg = Tkinter.Label(self.master, width=1, textvariable=self.changedVar) + self.changedVar = tkinter.StringVar() + self.changedWdg = tkinter.Label(self.master, width=1, textvariable=self.changedVar) self._addCtxMenu(self.changedWdg) self.editWdg = self._getEditWdg() # self.rangeWdg = self._getRangeWdg() if self.prefVar.units: - self.unitsWdg = Tkinter.Label(self.master, text = self.prefVar.name) + self.unitsWdg = tkinter.Label(self.master, text = self.prefVar.name) self._addCtxMenu(self.unitsWdg) else: self.unitsWdg = None @@ -257,17 +257,17 @@ def _getEditWdg(self): return wdg def _getRangeWdg(self): - return Tkinter.Label(self.master, text = self.prefVar.getRangeStr()) + return tkinter.Label(self.master, text = self.prefVar.getRangeStr()) def _getShowMenu(self): - mbut = Tkinter.Menubutton(self.master, + mbut = tkinter.Menubutton(self.master, indicatoron=1, direction="below", borderwidth=2, relief="raised", highlightthickness=2, ) - mnu = Tkinter.Menu(mbut, tearoff=0) + mnu = tkinter.Menu(mbut, tearoff=0) mnu.add_command(label="Current", command=self.showCurrentValue) mnu.add_command(label="Initial", command=self.showInitialValue) mnu.add_command(label="Default", command=self.showDefaultValue) @@ -312,7 +312,7 @@ def summaryFromVal(val): return False -class _ColorButton(Tkinter.Frame, RO.Wdg.CtxMenuMixin): +class _ColorButton(tkinter.Frame, RO.Wdg.CtxMenuMixin): """A button whose color can be set (without fussing with bitmaps and such). @@ -337,12 +337,12 @@ def __init__(self, self.helpText = helpText # self is outer frame; button is a frame within (to allow padding) - Tkinter.Frame.__init__(self, + tkinter.Frame.__init__(self, master, borderwidth = 0, ) - self.button = Tkinter.Frame( + self.button = tkinter.Frame( self, background = color, relief = "raised", @@ -398,7 +398,7 @@ def updateEditor(self): def editColor(self, evt=None): """Called when the color editor button is pressed""" oldColor = self.getEditValue() - newColor = tkColorChooser.askcolor(oldColor)[1] + newColor = tkinter.colorchooser.askcolor(oldColor)[1] if newColor: self.showValue(newColor) @@ -454,7 +454,7 @@ def _getEditWdg(self): - var: a Tkinter variable to be used in the widget - ctxConfigFunc: a function that updates the contextual menu """ - wdgFrame = Tkinter.Frame(self.master) + wdgFrame = tkinter.Frame(self.master) self.fileWdg = RO.Wdg.FileWdg( master = wdgFrame, defPath = self.getEditValue(), @@ -506,7 +506,7 @@ class FontPrefEditor(PrefEditor): def _getEditWdg(self): currFontDict = self.prefVar.value fontFamilies = [] - for fam in tkFont.families(): + for fam in tkinter.font.families(): try: fam = str(fam) if fam.startswith("."): @@ -518,15 +518,15 @@ def _getEditWdg(self): fontSizes = [str(x) for x in range(6, 25)] # create a Font for the font editor widgets - self.editFont = tkFont.Font(**currFontDict) + self.editFont = tkinter.font.Font(**currFontDict) fontNameVarSet = ( - ("family", Tkinter.StringVar()), - ("size", Tkinter.StringVar()), - ("weight", Tkinter.StringVar()), - ("slant", Tkinter.StringVar()), - ("underline", Tkinter.BooleanVar()), - ("overstrike", Tkinter.BooleanVar()), + ("family", tkinter.StringVar()), + ("size", tkinter.StringVar()), + ("weight", tkinter.StringVar()), + ("slant", tkinter.StringVar()), + ("underline", tkinter.BooleanVar()), + ("overstrike", tkinter.BooleanVar()), ) self.varDict = {} for varName, var in fontNameVarSet: @@ -536,7 +536,7 @@ def _getEditWdg(self): var.set(defValue) self.varDict[varName] = var - frame = Tkinter.Frame(self.master) + frame = tkinter.Frame(self.master) fontNameWdg = RO.Wdg.OptionMenu( master = frame, items = fontFamilies, @@ -558,7 +558,7 @@ def _getEditWdg(self): fontSizeWdg.configure(font=self.editFont) fontSizeWdg.ctxSetConfigFunc(self._configCtxMenu) - fontOptionWdg = Tkinter.Menubutton(frame, + fontOptionWdg = tkinter.Menubutton(frame, text="Options", indicatoron=1, direction="below", @@ -566,7 +566,7 @@ def _getEditWdg(self): relief="raised", highlightthickness=2, ) - mnu = Tkinter.Menu(fontOptionWdg, tearoff=0) + mnu = tkinter.Menu(fontOptionWdg, tearoff=0) mnu.add_checkbutton(label="Bold", variable=self.varDict["weight"], onvalue="bold", offvalue="normal") mnu.add_checkbutton(label="Italic", variable=self.varDict["slant"], onvalue="italic", offvalue="roman") mnu.add_checkbutton(label="Underline", variable=self.varDict["underline"], onvalue=True, offvalue=False) @@ -583,7 +583,7 @@ def _getEditWdg(self): fontOptionWdg.pack(side="left") # set up a callback for each variable - for var in self.varDict.itervalues(): + for var in self.varDict.values(): var.trace_variable("w", self._editCallback) return frame @@ -607,7 +607,7 @@ def getEditValue(self): # with our limited font editor) with the edit values retValue = self.getCurrentValue() editValue = {} - for name, var in self.varDict.iteritems(): + for name, var in self.varDict.items(): editValue[name] = var.get() retValue.update(editValue) return retValue @@ -617,7 +617,7 @@ def showValue(self, valueDict): "family", "size" and ?. Unknown values are ignored. """ # set pop-up menus - for name, val in valueDict.iteritems(): + for name, val in valueDict.items(): if name in self.varDict: self.varDict[name].set(val) diff --git a/python/RO/Prefs/PrefVar.py b/python/RO/Prefs/PrefVar.py index 00f5c87..52259ea 100755 --- a/python/RO/Prefs/PrefVar.py +++ b/python/RO/Prefs/PrefVar.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Support for reading and writing preferences and preference files. Subclasses of PrefVar store preferences of various types and offer: @@ -97,8 +97,8 @@ import os.path import re import sys -import Tkinter -import tkFont +import tkinter +import tkinter.font import RO.Alg import RO.CnvUtil import RO.MathUtil @@ -279,7 +279,7 @@ def setDefValue (self, rawValue): def setValue (self, rawValue): """Accepts values of the correct type or a string representation""" - if isinstance(rawValue, basestring): + if isinstance(rawValue, str): value = self.asValue(rawValue) else: value = rawValue @@ -746,10 +746,10 @@ def addVar(self, option, prefVar): def setColor(self, *args): # if we haven't gotten a widget yet, now is the time if not self.wdg: - self.wdg = Tkinter.Label() + self.wdg = tkinter.Label() colorDict = {} - for option, var in self.varDict.iteritems(): + for option, var in self.varDict.items(): colorDict[option] = var.getValue() # background is required; make sure we have it @@ -776,7 +776,7 @@ def __init__(self, kargs = kargs.copy() # prevent modifying a passed-in dictionary # create an arbitrary Tk widget we can query to convert colors - self.colorCheckWdg = Tkinter.Label() + self.colorCheckWdg = tkinter.Label() kargs["formatStr"] = "%s" kargs["cnvFunc"] = str @@ -797,7 +797,7 @@ def locCheckValue(self, value): """ try: self.colorCheckWdg.winfo_rgb(value) - except Tkinter.TclError as e: + except tkinter.TclError as e: raise ValueError(RO.StringUtil.strFromException(e)) class FontPrefVar(PrefVar): @@ -844,7 +844,7 @@ def __init__(self, ): kargs = kargs.copy() # prevent modifying a passed-in dictionary - self.font = font or tkFont.Font() + self.font = font or tkinter.font.Font() kargs["formatStr"] = "%r" kargs["cnvFunc"] = dict # a function that parsed string representations of a dict would be nicer @@ -867,7 +867,7 @@ def __init__(self, netDefValue.update(font.configure()) if defWdg: # the following is the only way I know to obtain a font dictionary from a widget - wdgFontDict = tkFont.Font(font=defWdg.cget("font")).configure() + wdgFontDict = tkinter.font.Font(font=defWdg.cget("font")).configure() netDefValue.update(wdgFontDict) if defValue: # defValue is the only one likely to have a bogus value; check it before applying it @@ -884,7 +884,7 @@ def __init__(self, # if optionPatterns supplied, add font to option database for ptn in optionPatterns: - Tkinter.Label().option_add(ptn, self.font) + tkinter.Label().option_add(ptn, self.font) def getDefValue(self): """Return the current default value""" @@ -896,7 +896,7 @@ def getValue(self): def locCheckValue(self, value): """Test that the value is valid. """ - badKeys = [key for key in value.iterkeys() if key not in self._internalDefFontDict] + badKeys = [key for key in value.keys() if key not in self._internalDefFontDict] if badKeys: raise ValueError("Invalid key(s) %s in font dictionary %r" % (badKeys, value)) @@ -982,7 +982,7 @@ def __init__(self, ): kargs = kargs.copy() # prevent modifying a passed-in dictionary - self.font = tkFont.Font() + self.font = tkinter.font.Font() kargs["formatStr"] = "%s" kargs["cnvFunc"] = int @@ -992,7 +992,7 @@ def __init__(self, netDefValue = font.cget("size") if defWdg: # the following is the only way I know to obtain a font dictionary from a widget - netDefValue = tkFont.Font(font=defWdg.cget("font")).cget("size") + netDefValue = tkinter.font.Font(font=defWdg.cget("font")).cget("size") if defValue: # defValue is the only one likely to have a bogus value; check it before applying it self.locCheckValue(defValue) @@ -1007,7 +1007,7 @@ def __init__(self, # if optionPatterns supplied, add font to option database for ptn in optionPatterns: - Tkinter.Label().option_add(ptn, self.font) + tkinter.Label().option_add(ptn, self.font) def locCheckValue(self, value): """Test that the value is valid. @@ -1063,7 +1063,7 @@ def __init__(self, self.addPrefVar(prefVar) self.oldPrefDict = {} if oldPrefInfo: - for oldPrefName, newPrefName in oldPrefInfo.iteritems(): + for oldPrefName, newPrefName in oldPrefInfo.items(): if newPrefName: if newPrefName.lower() not in self.prefDict: raise RuntimeError("Invalid oldPrefInfo %s: %s; nonexistent new pref name" % @@ -1090,14 +1090,14 @@ def getCategoryDict(self): """ catDict = RO.Alg.OrderedDict() - for prefVar in self.prefDict.itervalues(): + for prefVar in self.prefDict.values(): catDict.setdefault(prefVar.category, []).append(prefVar) return catDict def restoreDefault(self): """Restores all preferences to their default value. """ - for pref in self.prefDict.itervalues(): + for pref in self.prefDict.values(): pref.restoreDefault() def readFromFile(self, fileName=None): @@ -1202,7 +1202,7 @@ def writeToFile(self, fileName=None, header=None, maskDefault=1): else: # line does not being with a comment; prepend "# " outFile.write("# %s\n" % headerLine) - for prefVar in self.prefDict.itervalues(): + for prefVar in self.prefDict.values(): if maskDefault and prefVar.value == prefVar.defValue: outFile.write("# %s = %r\n" % (prefVar.name, prefVar.getValue())) else: diff --git a/python/RO/Prefs/PrefWdg.py b/python/RO/Prefs/PrefWdg.py index b05f660..05a1580 100755 --- a/python/RO/Prefs/PrefWdg.py +++ b/python/RO/Prefs/PrefWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A window (Tk Toplevel widget) for setting preferences. To Do: @@ -37,9 +37,9 @@ """ __all__ = ["PrefWin", "PrefWdg"] -import Tkinter -import PrefVar -import PrefEditor +import tkinter +from . import PrefVar +from . import PrefEditor import RO.Constants import RO.Wdg @@ -53,10 +53,10 @@ def __init__(self, ): RO.Wdg.Toplevel.__init__(self, master, title=title, *args, **kwargs) self.prefWdg = PrefWdg(self, prefSet) - self.prefWdg.pack(fill=Tkinter.BOTH, expand=Tkinter.YES) + self.prefWdg.pack(fill=tkinter.BOTH, expand=tkinter.YES) -class PrefWdg(Tkinter.Frame): +class PrefWdg(tkinter.Frame): """Frame for editing preferences.""" def __init__(self, @@ -65,15 +65,15 @@ def __init__(self, helpURL = None, ): self.prefSet = prefSet - Tkinter.Frame.__init__(self, master) + tkinter.Frame.__init__(self, master) self.prefsByCat = self.prefSet.getCategoryDict() catList = self.getCategories() # create the list of categories - catListFrame = Tkinter.Frame(self) - catListScroll = Tkinter.Scrollbar(catListFrame, orient="vertical") - self.catListWdg = Tkinter.Listbox( + catListFrame = tkinter.Frame(self) + catListScroll = tkinter.Scrollbar(catListFrame, orient="vertical") + self.catListWdg = tkinter.Listbox( catListFrame, selectmode="browse", yscrollcommand = catListScroll.set, @@ -93,10 +93,10 @@ def __init__(self, self.statusBar.grid(row=1, column=0, columnspan=2, sticky="ew") # create the button panel - self.buttonWdg = Tkinter.Frame(self) + self.buttonWdg = tkinter.Frame(self) buttonList = ( self._getShowMenu(self.buttonWdg, helpURL=helpURL), - Tkinter.Frame(self.buttonWdg, width=10), + tkinter.Frame(self.buttonWdg, width=10), RO.Wdg.Button(self.buttonWdg, text="Apply", command=self.applyPrefs, helpURL=helpURL), RO.Wdg.Button(self.buttonWdg, text="Save", command=self.writeToFile, helpURL=helpURL), ) @@ -109,16 +109,16 @@ def __init__(self, # create a frame for displaying the preferences for a given category - self.editFrame = Tkinter.Frame(self, relief="ridge", border=1) + self.editFrame = tkinter.Frame(self, relief="ridge", border=1) self.editFrame.grid(row=0, column=1, sticky="nsew") # pack a tiny frame so it shrinks to fit - Tkinter.Frame(self.editFrame, height=0, width=0).pack() + tkinter.Frame(self.editFrame, height=0, width=0).pack() # self.editFrame.grid_rowconfigure(0, weight=1) # self.editFrame.grid_columnconfigure(0, weight=1) self.paneDict = {} self.prefEditorList = [] - for cat, prefs in self.prefsByCat.iteritems(): - prefFrame = Tkinter.Frame(self.editFrame) + for cat, prefs in self.prefsByCat.items(): + prefFrame = tkinter.Frame(self.editFrame) self.paneDict[cat] = prefFrame row = 0 column = 0 @@ -174,7 +174,7 @@ def applyPrefs(self, evt=None): def getCategories(self): """Return a list of preference categories""" - return self.prefsByCat.keys() + return list(self.prefsByCat.keys()) def showCategory(self, catName): """Show the specified category. @@ -227,7 +227,7 @@ def unappliedChanges(self): return result def _getShowMenu(self, master, helpURL=None): - mbut = Tkinter.Menubutton(master, + mbut = tkinter.Menubutton(master, indicatoron=1, direction="below", borderwidth=2, @@ -236,7 +236,7 @@ def _getShowMenu(self, master, helpURL=None): text="Show", ) RO.Wdg.addCtxMenu(mbut, helpURL=helpURL) - mnu = Tkinter.Menu(mbut, tearoff=0) + mnu = tkinter.Menu(mbut, tearoff=0) mnu.add_command(label="Current", command=self.showCurrentValue) mnu.add_command(label="Initial", command=self.showInitialValue) mnu.add_command(label="Default", command=self.showDefaultValue) @@ -248,9 +248,9 @@ def _getShowMenu(self, master, helpURL=None): from RO.Wdg.PythonTk import PythonTk root = PythonTk() - defMainWdg = Tkinter.Label() - entryWdg = Tkinter.Entry() - menuWdg = Tkinter.Menu() + defMainWdg = tkinter.Label() + entryWdg = tkinter.Entry() + menuWdg = tkinter.Menu() pvList = ( PrefVar.FontPrefVar( @@ -277,14 +277,14 @@ def _getShowMenu(self, master, helpURL=None): PrefVar.ColorPrefVar( name = "Background Color", category = "colors", - defValue = Tkinter.Label().cget("background"), + defValue = tkinter.Label().cget("background"), wdgOption = "background", helpText = "background color for most widgets", ), PrefVar.ColorPrefVar( name = "Foreground Color", category = "colors", - defValue = Tkinter.Label().cget("foreground"), + defValue = tkinter.Label().cget("foreground"), wdgOption = "foreground", helpText = "foreground color for most widgets", ), @@ -347,7 +347,7 @@ def _getShowMenu(self, master, helpURL=None): name = "Int4", category = "ints", defValue = 4, - validValues = range(8, -10, -2), + validValues = list(range(8, -10, -2)), minValue = -9, maxValue = 9, helpText = "int with range of [-9, 9]", @@ -428,7 +428,7 @@ def _getShowMenu(self, master, helpURL=None): print("could not read prefs:", e) testFrame = PrefWdg (root, prefSet = prefSet) - testFrame.pack(fill=Tkinter.BOTH, expand=Tkinter.YES) + testFrame.pack(fill=tkinter.BOTH, expand=tkinter.YES) testFrame.showCategory("colors") diff --git a/python/RO/SQLUtil.py b/python/RO/SQLUtil.py index 032a9cf..5aa39bd 100644 --- a/python/RO/SQLUtil.py +++ b/python/RO/SQLUtil.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """Utility functions for working with SQL databases and with data files in FMPro "merge" format. @@ -184,7 +184,7 @@ def insertRow(dbCursor, table, dataDict, fieldsToAdd=None, fieldsToCheck=None): raise RuntimeError("a matching entry already exists") if fieldsToAdd is None: - fieldsToAdd = dataDict.keys() + fieldsToAdd = list(dataDict.keys()) addFieldStr = ", ".join(fieldsToAdd) addValueList = ["%%(%s)s" % (fieldName,) for fieldName in fieldsToAdd] @@ -227,7 +227,7 @@ def insertMany(dbCursor, table, dataDict, arrayFields, scalarFields=None): # with values in the same order as allFields = scalarFields + arrayFields listOfLists = [[dataDict[fieldName]]*numEntries for fieldName in scalarFields] \ + [dataDict[fieldName] for fieldName in arrayFields] - zippedList = zip(*listOfLists) + zippedList = list(zip(*listOfLists)) allFields = scalarFields + arrayFields # set up the query as: @@ -253,7 +253,7 @@ def rowExists(dbCursor, table, dataDict, fieldsToCheck=None): - fieldsToCheck: list of fields to check; if None (default) then check all fields """ if fieldsToCheck is None: - fieldsToCheck = dataDict.keys() + fieldsToCheck = list(dataDict.keys()) # generate the sql command: # select * from table where (fieldName1=%(fieldName1)s, fieldName2=%(fieldName2)s,...) @@ -283,7 +283,7 @@ def __init__(self, db): def execute(self, sqlCmd, dataDict=None): print("%s.execute %s" % (self, sqlCmd)) if dataDict: - keys = dataDict.keys() + keys = list(dataDict.keys()) keys.sort() for key in keys: valStr = repr(dataDict[key]) diff --git a/python/RO/ScriptRunner.py b/python/RO/ScriptRunner.py index 15283df..e02d88b 100755 --- a/python/RO/ScriptRunner.py +++ b/python/RO/ScriptRunner.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Code to run scripts that can wait for various things without messing up the main event loop (and thus starving the rest of your program). @@ -92,7 +92,7 @@ import sys import threading -import Queue +import queue import traceback import RO.AddCallback import RO.Constants @@ -246,8 +246,8 @@ def runFunc(sr): which is needlessly inefficient. """ if self.master: - import Tkinter - self._privateWdg = Tkinter.Frame(self.master) + import tkinter + self._privateWdg = tkinter.Frame(self.master) self._privateWdg.bind("", self.__del__) if stateFunc: @@ -736,7 +736,7 @@ def _cmdFailCallback(self, msgType, msgDict, cmdVar): cmdDescr = "%s %s..." % (cmdVar.actor, cmdVar.cmdStr[0:MaxLen]) else: cmdDescr = "%s %s" % (cmdVar.actor, cmdVar.cmdStr) - for key, values in msgDict.get("data", {}).iteritems(): + for key, values in msgDict.get("data", {}).items(): if key.lower() in _ErrKeys: reason = values[0] break @@ -1168,7 +1168,7 @@ def __init__(self, scriptRunner, func, *args, **kargs): if not callable(func): raise ValueError("%r is not callable" % func) - self.queue = Queue.Queue() + self.queue = queue.Queue() self.func = func self.threadObj = threading.Thread(target=self.threadFunc, args=args, kwargs=kargs) @@ -1198,11 +1198,11 @@ def threadFunc(self, *args, **kargs): if __name__ == "__main__": - import Tkinter + import tkinter import RO.KeyDispatcher import time - root = Tkinter.Tk() + root = tkinter.Tk() dispatcher = RO.KeyDispatcher.KeyDispatcher() diff --git a/python/RO/SeqUtil.py b/python/RO/SeqUtil.py index 665136a..a7d566c 100755 --- a/python/RO/SeqUtil.py +++ b/python/RO/SeqUtil.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Utilities for non-string-like collections of objects. The following definitions are used in this module: @@ -30,7 +30,7 @@ 2007-04-24 ROwen Changed Numeric to numpy in a doc string. 2010-06-28 ROwen Modified to require Python 2.4 by assuming set is a builtin type. """ -import UserString +import collections import RO.MathUtil def asCollection(item): @@ -121,7 +121,7 @@ def isString(item): From Python Cookbook, 2nd ed. """ - return isinstance(item, (basestring, UserString.UserString)) + return isinstance(item, (str, collections.UserString)) def oneOrNAsList ( oneOrNVal, @@ -189,9 +189,9 @@ class OldStyleClass: (False, False), (5, False), (7.5, False), - (u'unicode string', False), + ('unicode string', False), ('regular string', False), - (UserString.UserString("user string"), False), + (collections.UserString("user string"), False), (dict(), False), (set(), False), (list(), True), @@ -203,9 +203,9 @@ class OldStyleClass: (False, False), (5, False), (7.5, False), - (u'unicode string', False), + ('unicode string', False), ('regular string', False), - (UserString.UserString("user string"), False), + (collections.UserString("user string"), False), (dict(), True), (set(), True), (list(), True), @@ -217,16 +217,16 @@ class OldStyleClass: (False, False), (5, False), (7.5, False), - (u'unicode string', True), + ('unicode string', True), ('regular string', True), - (UserString.UserString("user string"), True), + (collections.UserString("user string"), True), (dict(), False), (set(), False), (list(), False), ((), False), ), } - for func, dataList in dataDict.iteritems(): + for func, dataList in dataDict.items(): funcName = func.__name__ print("testing", funcName) for dataItem, expectTrue in dataList: @@ -236,5 +236,5 @@ class OldStyleClass: print("%s(%r) failed; should be %r" % (funcName, dataItem, expectTrue)) print("testing flatten") - f = (((),("abc",)), u"abc", ["a", "b", "c"]) - assert flatten(f) == ["abc", u"abc", "a", "b", "c"] + f = (((),("abc",)), "abc", ["a", "b", "c"]) + assert flatten(f) == ["abc", "abc", "a", "b", "c"] diff --git a/python/RO/StringUtil.py b/python/RO/StringUtil.py index 15bc868..a7e5859 100755 --- a/python/RO/StringUtil.py +++ b/python/RO/StringUtil.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """String utilities, with an emphasis on support for sexagesimal numbers (e.g. degrees:minutes:seconds). @@ -54,11 +54,11 @@ import re import numpy -AngstromStr = u"\N{ANGSTROM SIGN}" -DegStr = u"\N{DEGREE SIGN}" -DMSStr = DegStr + u"'\"" -LambdaStr = u"\u00c5" # for some reason this fails: u"\N{GREEK SMALL LETTER LAMBDA}" -MuStr = u"\N{GREEK SMALL LETTER MU}" +AngstromStr = "\N{ANGSTROM SIGN}" +DegStr = "\N{DEGREE SIGN}" +DMSStr = DegStr + "'\"" +LambdaStr = "\u00c5" # for some reason this fails: u"\N{GREEK SMALL LETTER LAMBDA}" +MuStr = "\N{GREEK SMALL LETTER MU}" def dmsStrFromDeg (decDeg, nFields=3, precision=1, omitExtraFields = False): """Convert a number to a sexagesimal string with 1-3 fields. @@ -334,7 +334,7 @@ def prettyDict(aDict, entrySepStr = "\n", keyValSepStr = ": "): Returns a string containing the pretty-printed dictionary """ - sortedKeys = aDict.keys() + sortedKeys = list(aDict.keys()) sortedKeys.sort() eltList = [] for aKey in sortedKeys: @@ -361,7 +361,7 @@ def splitDMSStr (dmsStr): error conditions: raises ValueError if the string cannot be parsed """ - assert isinstance(dmsStr, basestring) + assert isinstance(dmsStr, str) m = _DegRE.match(dmsStr) or _DegMinRE.match(dmsStr) or _DegMinSecRE.match(dmsStr) if m is None: raise ValueError("splitDMSStr cannot parse %s as a sexagesimal string" % (dmsStr)) @@ -446,7 +446,7 @@ def strFromException(exc): return str(exc) except Exception: try: - return ",".join([unicode(s) for s in exc.args]) + return ",".join([str(s) for s in exc.args]) except Exception: # in case exc is some unexpected type return repr(exc) diff --git a/python/RO/TkUtil.py b/python/RO/TkUtil.py index 07ad983..31ce185 100755 --- a/python/RO/TkUtil.py +++ b/python/RO/TkUtil.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Tkinter utilities History: @@ -28,7 +28,7 @@ import re import sys import traceback -import Tkinter +import tkinter import RO.OS # windowing system constants @@ -66,7 +66,7 @@ def colorOK(colorStr): try: tkWdg.winfo_rgb(colorStr) - except Tkinter.TclError: + except tkinter.TclError: return False return True @@ -126,7 +126,7 @@ def getWindowingSystem(): tkWdg = _getTkWdg() try: g_winSys = tkWdg.tk.call("tk", "windowingsystem") - except Tkinter.TclError: + except tkinter.TclError: # windowingsystem not supported; take a best guess if RO.OS.PlatformName == "win": g_winSys = "win32" @@ -216,7 +216,7 @@ def deregister(self): return try: self.tkApp.deletecommand(self.tclFuncName) - except Tkinter.TclError as e: + except tkinter.TclError as e: if self.debug: print("deregistering failed: %r" % (e,)) pass @@ -478,11 +478,11 @@ def _getTkWdg(): """Return a Tk widget""" global g_tkWdg if not g_tkWdg: - g_tkWdg = Tkinter.Frame() + g_tkWdg = tkinter.Frame() return g_tkWdg if __name__ == "__main__": - root = Tkinter.Tk() + root = tkinter.Tk() def setGeometry(geomStrList): if not geomStrList: diff --git a/python/RO/Wdg/BalloonHelp.py b/python/RO/Wdg/BalloonHelp.py index 30c42c1..5d9d8c1 100755 --- a/python/RO/Wdg/BalloonHelp.py +++ b/python/RO/Wdg/BalloonHelp.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Simple implementation of pop-up help. Call enableBalloonHelp to activate help for all widgets that have a helpText attribute. @@ -15,7 +15,7 @@ """ __all__ = ['enableBalloonHelp'] -import Tkinter +import tkinter from RO.TkUtil import Timer _HelpObj = None @@ -40,9 +40,9 @@ def __init__(self, delayMS = 600): self._delayMS = delayMS self._showTimer = Timer() self._leaveTimer = Timer() - self._msgWin = Tkinter.Toplevel() + self._msgWin = tkinter.Toplevel() self._msgWin.overrideredirect(True) - self._msgWdg = Tkinter.Message(self._msgWin, bg="light yellow") + self._msgWdg = tkinter.Message(self._msgWin, bg="light yellow") self._msgWdg.pack() self._msgWin.withdraw() self._msgWdg.bind_all('', self._start) @@ -125,20 +125,20 @@ def enableBalloonHelp(delayMS = 1000): if __name__ == '__main__': - import OptionMenu - root = Tkinter.Tk() + from . import OptionMenu + root = tkinter.Tk() - l0 = Tkinter.Label(text="Data") + l0 = tkinter.Label(text="Data") l0.grid(row=0, column=0, sticky="e") l0.helpText = "Help for the Data label" - e0 = Tkinter.Entry(width=10) + e0 = tkinter.Entry(width=10) e0.helpText = "A really long help string describing the data entry widget" e0.grid(row=0, column=1) - l1 = Tkinter.Label(text="No Help") + l1 = tkinter.Label(text="No Help") l1.grid(row=1, column=0) - e1 = Tkinter.Entry(width=10) + e1 = tkinter.Entry(width=10) e1.grid(row=1, column=1) - l2 = Tkinter.Label(text="Option Menu") + l2 = tkinter.Label(text="Option Menu") l2.helpText = "Help for the option menu label" l2.grid(row=2, column=0) m2 = OptionMenu.OptionMenu(root, diff --git a/python/RO/Wdg/Bindings.py b/python/RO/Wdg/Bindings.py index 5440c24..e6b3419 100755 --- a/python/RO/Wdg/Bindings.py +++ b/python/RO/Wdg/Bindings.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Sets up standard key bindings for each platform. Supplements Tk's defaults and handles readonly text widgets. @@ -43,7 +43,7 @@ """ __all__ = ['makeReadOnly', 'stdBindings', 'stopEvent'] -import Tkinter +import tkinter import RO.TkUtil def doQuit(evt): @@ -194,14 +194,14 @@ def _entryGoToRightEdge(evt): evt.widget.icursor("end") if __name__ == "__main__": - root = Tkinter.Tk() + root = tkinter.Tk() stdBindings(root, debug=1) - t = Tkinter.Text(root, width=20, height=5) - tr = Tkinter.Text(root, width=20, height=5) + t = tkinter.Text(root, width=20, height=5) + tr = tkinter.Text(root, width=20, height=5) tr.insert("end", "here is some test text for the read only text widget") makeReadOnly(tr) - e = Tkinter.Entry(root) + e = tkinter.Entry(root) t.pack() tr.pack() e.pack() diff --git a/python/RO/Wdg/Button.py b/python/RO/Wdg/Button.py index 0b6353b..a1d3b06 100644 --- a/python/RO/Wdg/Button.py +++ b/python/RO/Wdg/Button.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """Variants on buttons that add help. History: @@ -17,17 +17,18 @@ Button: removed special width handling for Aqua Tk as it is neither needed nor wanted for Aqua Tk 8.5.18. 2015-04-02 ROwen Added a simple workaround for cramped button text in Aqua Tk 8.5.18. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['Button', 'Radiobutton'] -import Tkinter +import tkinter import RO.AddCallback import RO.Constants import RO.TkUtil -import CtxMenu -from SeverityMixin import SeverityActiveMixin +from .CtxMenu import CtxMenu, CtxMenuMixin +from .SeverityMixin import SeverityActiveMixin -class Button(Tkinter.Button, RO.AddCallback.TkButtonMixin, CtxMenu.CtxMenuMixin, SeverityActiveMixin): +class Button(tkinter.Button, RO.AddCallback.TkButtonMixin, CtxMenuMixin, SeverityActiveMixin): def __init__(self, master, helpText = None, @@ -57,7 +58,7 @@ def __init__(self, kwArgs.setdefault("padx", 10) kwArgs.setdefault("pady", 3) - Tkinter.Button.__init__(self, master = master, **kwArgs) + tkinter.Button.__init__(self, master = master, **kwArgs) RO.AddCallback.TkButtonMixin.__init__(self, callFunc = callFunc, @@ -65,7 +66,7 @@ def __init__(self, command = command, ) - CtxMenu.CtxMenuMixin.__init__(self, helpURL = helpURL) + CtxMenuMixin.__init__(self, helpURL = helpURL) SeverityActiveMixin.__init__(self, severity) def setEnable(self, doEnable): @@ -77,19 +78,19 @@ def setEnable(self, doEnable): Warning: if you want the state to be "active" you must set that explicitly. """ if doEnable: - self["state"] = Tkinter.NORMAL + self["state"] = tkinter.NORMAL else: - self["state"] = Tkinter.DISABLED + self["state"] = tkinter.DISABLED def getEnable(self): """Return True if widget is enabled, False otherwise Enabled is defined as the state is not "disabled" (thus "enabled" or "active"). """ - return self["state"] != Tkinter.DISABLED + return self["state"] != tkinter.DISABLED -class Radiobutton(Tkinter.Radiobutton, CtxMenu.CtxMenuMixin, SeverityActiveMixin): +class Radiobutton(tkinter.Radiobutton, CtxMenuMixin, SeverityActiveMixin): def __init__(self, master, helpText = None, @@ -106,7 +107,7 @@ def __init__(self, """ self.helpText = helpText - Tkinter.Radiobutton.__init__(self, master = master, **kwArgs) - CtxMenu.CtxMenuMixin.__init__(self, helpURL = helpURL) + tkinter.Radiobutton.__init__(self, master = master, **kwArgs) + CtxMenuMixin.__init__(self, helpURL = helpURL) SeverityActiveMixin.__init__(self, severity) diff --git a/python/RO/Wdg/ChangedIndicator.py b/python/RO/Wdg/ChangedIndicator.py index 32d5f7b..f7394f2 100644 --- a/python/RO/Wdg/ChangedIndicator.py +++ b/python/RO/Wdg/ChangedIndicator.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """An indicator that shows if one or more ROEntry widgets have been set to nondefault values. @@ -12,14 +12,15 @@ 2004-08-11 ROwen Define __all__ to restrict import. 2004-09-14 ROwen Tweaked the imports. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['ChangedIndicator'] -import Tkinter +import tkinter import RO.SeqUtil -import CtxMenu +from .CtxMenu import CtxMenu, CtxMenuMixin -class ChangedIndicator (Tkinter.Label, CtxMenu.CtxMenuMixin): +class ChangedIndicator (tkinter.Label, CtxMenuMixin): def __init__(self, master, wdgOrSet, @@ -39,7 +40,7 @@ def __init__(self, - all remaining keyword arguments are used to configure the Menu """ if var is None: - var = Tkinter.StringVar() + var = tkinter.StringVar() self.__var = var self.__inputCont = None self.wdgSet = [] @@ -49,11 +50,11 @@ def __init__(self, kargs.setdefault("width", 1) - Tkinter.Label.__init__(self, + tkinter.Label.__init__(self, master = master, textvariable = self.__var, **kargs) - CtxMenu.CtxMenuMixin.__init__(self, + CtxMenuMixin.__init__(self, helpURL = helpURL, ) diff --git a/python/RO/Wdg/Checkbutton.py b/python/RO/Wdg/Checkbutton.py index 58e469f..1eb76e6 100755 --- a/python/RO/Wdg/Checkbutton.py +++ b/python/RO/Wdg/Checkbutton.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A variant on Checkbutton that add help, default handling and other niceties including a command callback that is called in more cases. @@ -72,16 +72,16 @@ """ __all__ = ['Checkbutton'] -import Tkinter +import tkinter import RO.AddCallback import RO.CnvUtil import RO.MathUtil import RO.TkUtil -from CtxMenu import CtxMenuMixin -from IsCurrentMixin import AutoIsCurrentMixin, IsCurrentCheckbuttonMixin -from SeverityMixin import SeverityActiveMixin +from .CtxMenu import CtxMenuMixin +from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentCheckbuttonMixin +from .SeverityMixin import SeverityActiveMixin -class Checkbutton (Tkinter.Checkbutton, RO.AddCallback.TkVarMixin, +class Checkbutton (tkinter.Checkbutton, RO.AddCallback.TkVarMixin, AutoIsCurrentMixin, IsCurrentCheckbuttonMixin, SeverityActiveMixin, CtxMenuMixin): """A Checkbutton with callback, help, isCurrent and severity support. @@ -150,7 +150,7 @@ def __init__(self, **kargs): self._defBool = False # just create the field for now if var is None: - var = Tkinter.StringVar() + var = tkinter.StringVar() elif defValue is None: defValue = var.get() self._var = var @@ -173,7 +173,7 @@ def __init__(self, kargs.setdefault("indicatoron", False) kargs["textvariable"] = self._var - Tkinter.Checkbutton.__init__(self, + tkinter.Checkbutton.__init__(self, master = master, variable = self._var, ) @@ -251,7 +251,7 @@ def getEnable(self): Enabled is defined as the state is not "disabled" (thus "enabled" or "active"). """ - return self["state"] != Tkinter.DISABLED + return self["state"] != tkinter.DISABLED def getVar(self): return self._var @@ -336,7 +336,7 @@ def setDefault(self, # if disabled and defIfDisabled, update display (which also triggers a callback) # otherwise leave the display alone and explicitly trigger a callback - if restoreDef or (self._defIfDisabled and self["state"] == Tkinter.DISABLED): + if restoreDef or (self._defIfDisabled and self["state"] == tkinter.DISABLED): self.restoreDefault() else: self._doCallbacks() @@ -371,7 +371,7 @@ def configure(self, argDict=None, **kargs): hasBitmap = bool(kargs.get("bitmap", self["bitmap"])), showIndicator = kargs.get("indicatoron", self["indicatoron"]), ) - Tkinter.Checkbutton.configure(self, **kargs) + tkinter.Checkbutton.configure(self, **kargs) def _computeCorrectedWidth(self, width, hasBitmap, showIndicator): """Compute corrected width to overcome Tcl/Tk bugs @@ -389,8 +389,8 @@ def _computeCorrectedWidth(self, width, hasBitmap, showIndicator): if __name__ == "__main__": - import PythonTk - from StatusBar import StatusBar + from . import PythonTk + from .StatusBar import StatusBar root = PythonTk.PythonTk() def btnCallback(btn): diff --git a/python/RO/Wdg/CmdWdg.py b/python/RO/Wdg/CmdWdg.py index 7b9cf2f..9183f46 100755 --- a/python/RO/Wdg/CmdWdg.py +++ b/python/RO/Wdg/CmdWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Entry widget for commands, with history. History: @@ -28,8 +28,8 @@ """ __all__ = ['CmdWdg'] -import Tkinter -import Entry +import tkinter +from . import Entry class CmdWdg (Entry.StrEntry): """Entry field for one-line text commands, with history. @@ -109,11 +109,11 @@ def _doHistDown(self, *args, **kargs): if self.histIndex > 0: self.histIndex -= 1 self.set(self.cmdHistory[self.histIndex]) - self.icursor(Tkinter.END) + self.icursor(tkinter.END) elif self.histIndex == 0: self.set(self.currText) self.histIndex = -1 - self.icursor(Tkinter.END) + self.icursor(tkinter.END) return "break" # prevent event from being propogated def _doHistUp(self, *args, **kargs): @@ -130,7 +130,7 @@ def _doHistUp(self, *args, **kargs): if self.histIndex < len(self.cmdHistory) - 1: self.histIndex += 1 self.set(self.cmdHistory[self.histIndex]) - self.icursor(Tkinter.END) + self.icursor(tkinter.END) else: self.histIndex = len(self.cmdHistory) self.set("") @@ -158,6 +158,6 @@ def doCmd(cmdStr): cmdFunc=doCmd, width = 40, ) - testFrame.pack(fill=Tkinter.BOTH, expand=Tkinter.YES) + testFrame.pack(fill=tkinter.BOTH, expand=tkinter.YES) root.mainloop() diff --git a/python/RO/Wdg/CtxMenu.py b/python/RO/Wdg/CtxMenu.py index 6a64a1b..a2baff9 100755 --- a/python/RO/Wdg/CtxMenu.py +++ b/python/RO/Wdg/CtxMenu.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Add contextual menu to a Tkinter widget, including automatic support for help. @@ -47,7 +47,7 @@ """ __all__ = ['CtxMenu', 'CtxMenuMixin', 'addCtxMenu'] -import Tkinter +import tkinter import RO.Comm.BrowseURL import RO.Constants import RO.OS @@ -126,7 +126,7 @@ def ctxGetMenu(self): Override to build your own menu from scratch. If you only want to add some entries, override ctxConfigMenu instead. """ - menu = Tkinter.Menu(master=self.__getWdg(), tearoff=0) + menu = tkinter.Menu(master=self.__getWdg(), tearoff=0) if self.__configMenuFunc(menu): helpURL = self.getHelpURL() if helpURL: @@ -207,15 +207,15 @@ def addCtxMenu( if __name__ == "__main__": - import Bindings - import PythonTk + from . import Bindings + from . import PythonTk root = PythonTk.PythonTk() # set up standard binding for <> Bindings.stdBindings(root) # add help to a standard Tkinter widget - stdLabel = Tkinter.Label(text="Standard label") + stdLabel = tkinter.Label(text="Standard label") addCtxMenu( wdg = stdLabel, helpURL = "http://brokenURL.html", @@ -223,9 +223,9 @@ def addCtxMenu( stdLabel.pack() # create a new label class that automatically has help: - class HelpLabel(Tkinter.Label, CtxMenuMixin): + class HelpLabel(tkinter.Label, CtxMenuMixin): def __init__(self, master, helpURL=None, **kargs): - Tkinter.Label.__init__(self, master=master, **kargs) + tkinter.Label.__init__(self, master=master, **kargs) CtxMenuMixin.__init__(self, helpURL) hLabel = HelpLabel(root, diff --git a/python/RO/Wdg/DropletApp.py b/python/RO/Wdg/DropletApp.py index 88f0dff..762c272 100755 --- a/python/RO/Wdg/DropletApp.py +++ b/python/RO/Wdg/DropletApp.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Run an application as a droplet (an application onto which you drop file) with a log window. To build a Mac droplet using py2app, in the PList specify the sorts of files that can be dropped, e.g.: @@ -45,13 +45,13 @@ import sys import traceback -import Tkinter +import tkinter import RO.OS import RO.Constants from RO.TkUtil import Timer -import LogWdg +from . import LogWdg -class DropletApp(Tkinter.Frame): +class DropletApp(tkinter.Frame): """Run an application as a droplet (an application onto which you drop files) You must subclass this class and override processFile. @@ -100,7 +100,7 @@ def __init__(self, If None then no final message is printed. If supplied then a final \n is also added. """ - Tkinter.Frame.__init__(self, master) + tkinter.Frame.__init__(self, master) self.printTraceback = bool(printTraceback) self.patterns = patterns self.exclPatterns = exclPatterns @@ -184,7 +184,7 @@ def _macOpenDocument(self, *filePathList): if filePathList and filePathList[0].startswith("-"): filePathList = filePathList[1:] - root = Tkinter.Tk() + root = tkinter.Tk() class TestApp(DropletApp): def __init__(self, master): diff --git a/python/RO/Wdg/DropletRunner.py b/python/RO/Wdg/DropletRunner.py index a1a6735..c8ab445 100755 --- a/python/RO/Wdg/DropletRunner.py +++ b/python/RO/Wdg/DropletRunner.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Run a script as a droplet (an application onto which you drop file) with a log window Deprecated. use DropletApp instead. @@ -62,11 +62,11 @@ import sys import os.path import subprocess -import Tkinter +import tkinter import RO.OS import RO.Constants from RO.TkUtil import Timer -import LogWdg +from . import LogWdg class DropletRunner(object): """Run a script as a droplet (an application onto which you drop file) with a log window. @@ -91,7 +91,7 @@ def __init__(self, scriptPath, title=None, initialText=None, **keyArgs): if not os.path.isfile(scriptPath): raise RuntimeError("Cannot find script %r" % (self.scriptPath,)) - self.tkRoot = Tkinter.Tk() + self.tkRoot = tkinter.Tk() self._timer = Timer() if title is None: @@ -129,8 +129,8 @@ def runFiles(self, filePathList): self.isRunning = True argList = [sys.executable, self.scriptPath] + list(filePathList) self.subProc = subprocess.Popen(argList, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - self.tkRoot.tk.createfilehandler(self.subProc.stderr, Tkinter.READABLE, self._readStdErr) - self.tkRoot.tk.createfilehandler(self.subProc.stdout, Tkinter.READABLE, self._readStdOut) + self.tkRoot.tk.createfilehandler(self.subProc.stderr, tkinter.READABLE, self._readStdErr) + self.tkRoot.tk.createfilehandler(self.subProc.stdout, tkinter.READABLE, self._readStdOut) self._poll() def _macOpenDocument(self, *filePathList): diff --git a/python/RO/Wdg/Entry.py b/python/RO/Wdg/Entry.py index 12d97cd..63f960f 100755 --- a/python/RO/Wdg/Entry.py +++ b/python/RO/Wdg/Entry.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Widgets for floating point, integer and sexagesimal input using Tkinter. These widgets have many useful features, including: - default values @@ -165,18 +165,18 @@ #import os import re -import Tkinter +import tkinter import RO.AddCallback import RO.CnvUtil import RO.SeqUtil import RO.StringUtil import RO.MathUtil -import Bindings -from CtxMenu import CtxMenuMixin -from IsCurrentMixin import AutoIsCurrentMixin, IsCurrentMixin -from SeverityMixin import SeveritySelectMixin +from . import Bindings +from .CtxMenu import CtxMenuMixin +from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentMixin +from .SeverityMixin import SeveritySelectMixin -class _BaseEntry (Tkinter.Entry, RO.AddCallback.BaseMixin, +class _BaseEntry (tkinter.Entry, RO.AddCallback.BaseMixin, AutoIsCurrentMixin, IsCurrentMixin, SeveritySelectMixin, CtxMenuMixin): """Base class for RO.Wdg entry widgets. @@ -269,7 +269,7 @@ def __init__ (self, **kargs): self.defValueStr = "" # just create the field for now if var is None: - var = Tkinter.StringVar() + var = tkinter.StringVar() self.var = var self.label = label self.helpText = helpText @@ -306,7 +306,7 @@ def __init__ (self, del(kargs["text"]) kargs["textvariable"] = self.var # overrides user attempt to set - Tkinter.Entry.__init__(self, master, **kargs) + tkinter.Entry.__init__(self, master, **kargs) self.currStrVal = "" self.var.trace_variable("w", self._checkVar) @@ -399,7 +399,7 @@ def ctxConfigMenu(self, menu): try: clipPresent = (self.selection_get(selection="CLIPBOARD") != "") - except Tkinter.TclError: + except tkinter.TclError: clipPresent = False if self._clearMenuName: @@ -471,7 +471,7 @@ def getEnable(self): """Returns False if the state is disabled, True otherwise (state is normal or active) """ - return self["state"] != Tkinter.DISABLED + return self["state"] != tkinter.DISABLED def getEntryError(self): """Returns the current validation error. @@ -967,7 +967,7 @@ def asNum(self, val): If val is "" or None, returns None Performs no range checking. """ - if isinstance(val, basestring): + if isinstance(val, str): return self.numFromStr(val) return val @@ -980,7 +980,7 @@ def asStr(self, If format is omitted, the default format is used. Performs no range checking. """ - if isinstance(val, basestring): + if isinstance(val, str): return val return self.strFromNum(val, format) @@ -1459,7 +1459,7 @@ def _setUnitsVar(self): if self.isHours: unitsStr = "%sh%sm%ss%s%s" % unitsSepTuple else: - unitsStr = u"%s\N{DEGREE SIGN}%s\'%s\"%s%s" % unitsSepTuple + unitsStr = "%s\N{DEGREE SIGN}%s\'%s\"%s%s" % unitsSepTuple self.unitsVar.set(unitsStr) # index = nFields*2-1 # use if there is a separator between characters, e.g. h:m:s @@ -1492,7 +1492,7 @@ def _optionKeyPress(self, evt): currVal = self.var.get() # try to select the previous field if self.selection_present(): - ind = self.index(Tkinter.SEL_FIRST) - 1 + ind = self.index(tkinter.SEL_FIRST) - 1 else: ind = self.index("insert") - 1 (leftInd, rightInd) = RO.StringUtil.findLeftNumber(currVal, ind) @@ -1505,7 +1505,7 @@ def _optionKeyPress(self, evt): # try to select the next digit currVal = self.var.get() if self.selection_present(): - ind = self.index(Tkinter.SEL_LAST) + ind = self.index(tkinter.SEL_LAST) else: ind = self.index("insert") (leftInd, rightInd) = RO.StringUtil.findRightNumber(currVal, ind) @@ -1519,7 +1519,7 @@ def _optionKeyPress(self, evt): if __name__ == "__main__": from RO.Wdg.PythonTk import PythonTk - import StatusBar + from . import StatusBar root = PythonTk() entryList = [] @@ -1531,10 +1531,10 @@ def fmtEntry(entry): return "%r" % (entry.getString(),) def addEntry(descr, entry, unitsLabel=None): - newFrame = Tkinter.Frame(root) + newFrame = tkinter.Frame(root) newFrame.lower() if descr: - Tkinter.Label(newFrame, text=descr).pack(side="left") + tkinter.Label(newFrame, text=descr).pack(side="left") entry.pack(in_=newFrame, side="left") if unitsLabel: unitsLabel.pack(in_=newFrame, side="left") @@ -1571,16 +1571,16 @@ def setDeg(*args): if isinstance(entry, DMSEntry): entry.setIsHours(False) - getButton = Tkinter.Button (root, command=doPrint, text="Print Values") + getButton = tkinter.Button (root, command=doPrint, text="Print Values") getButton.pack() - defButton = Tkinter.Button (root, command=doDefault, text="Default") + defButton = tkinter.Button (root, command=doDefault, text="Default") defButton.pack() - hrsButton = Tkinter.Button (root, command=setHours, text="DMS in hrs") + hrsButton = tkinter.Button (root, command=setHours, text="DMS in hrs") hrsButton.pack() - degButton = Tkinter.Button (root, command=setDeg, text="DMS in deg") + degButton = tkinter.Button (root, command=setDeg, text="DMS in deg") degButton.pack() statusBar = StatusBar.StatusBar(root) @@ -1646,7 +1646,7 @@ def doneFunc(wdg): ) - absUnitsVar = Tkinter.StringVar() + absUnitsVar = tkinter.StringVar() addEntry ( "Abs DMSEntry -90-90 deg", DMSEntry(root, @@ -1655,10 +1655,10 @@ def doneFunc(wdg): unitsVar=absUnitsVar, helpText = "d:m:s in the range -90-90", ), - Tkinter.Label(root, textvar=absUnitsVar, width=5), + tkinter.Label(root, textvar=absUnitsVar, width=5), ) - abs2UnitsVar = Tkinter.StringVar() + abs2UnitsVar = tkinter.StringVar() addEntry ( "Abs DMSEntry 25-180 deg", DMSEntry(root, @@ -1668,10 +1668,10 @@ def doneFunc(wdg): helpText = "d:m:s in the range 25-180", clearMenu = None, ), - Tkinter.Label(root, textvar=abs2UnitsVar, width=5), + tkinter.Label(root, textvar=abs2UnitsVar, width=5), ) - relUnitsVar = Tkinter.StringVar() + relUnitsVar = tkinter.StringVar() addEntry ( "Rel DMSEntry -90-90 sec", DMSEntry(root, @@ -1684,10 +1684,10 @@ def doneFunc(wdg): minMenu = "Minimum", maxMenu = "Maximum", ), - Tkinter.Label(root, textvar=relUnitsVar, width=5), + tkinter.Label(root, textvar=relUnitsVar, width=5), ) - rel2UnitsVar = Tkinter.StringVar() + rel2UnitsVar = tkinter.StringVar() addEntry ( "Rel DMSEntry 0-180 sec", DMSEntry(root, @@ -1700,7 +1700,7 @@ def doneFunc(wdg): minMenu = "Minimum", maxMenu = "Maximum", ), - Tkinter.Label(root, textvar=rel2UnitsVar, width=5), + tkinter.Label(root, textvar=rel2UnitsVar, width=5), ) statusBar.pack(side="top", expand="yes", fill="x") diff --git a/python/RO/Wdg/FTPLogWdg.py b/python/RO/Wdg/FTPLogWdg.py index 8b6ffbf..fd323ba 100755 --- a/python/RO/Wdg/FTPLogWdg.py +++ b/python/RO/Wdg/FTPLogWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """FTP download with Tkinter-based progress reporting Downloads files given the url and destination path. @@ -49,6 +49,7 @@ 2012-08-01 ROwen Updated for changes to FTPGet. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['FTPLogWdg'] @@ -56,15 +57,15 @@ import sys import traceback import weakref -import Bindings -import Tkinter +from . import Bindings +import tkinter import RO.AddCallback import RO.Constants import RO.MathUtil from RO.TkUtil import Timer from RO.Comm.FTPGet import FTPGet import RO.Wdg -import CtxMenu +from .CtxMenu import addCtxMenu _StatusInterval = 0.200 # time between status checks (sec) @@ -99,7 +100,7 @@ def clear(self): self.callFunc = None -class FTPLogWdg(Tkinter.Frame): +class FTPLogWdg(tkinter.Frame): """A widget to initiate file get via ftp, to display the status of the transfer and to allow users to abort the transfer. @@ -120,7 +121,7 @@ def __init__(self, maxLines = 500, helpURL = None, **kargs): - Tkinter.Frame.__init__(self, master = master, **kargs) + tkinter.Frame.__init__(self, master = master, **kargs) self._memDebugDict = {} self.maxLines = maxLines @@ -132,11 +133,11 @@ def __init__(self, self._timer = Timer() - self.yscroll = Tkinter.Scrollbar ( + self.yscroll = tkinter.Scrollbar ( master = self, orient = "vertical", ) - self.text = Tkinter.Text ( + self.text = tkinter.Text ( master = self, yscrollcommand = self.yscroll.set, wrap = "none", @@ -149,7 +150,7 @@ def __init__(self, self.yscroll.grid(row=0, column=1, sticky="ns") Bindings.makeReadOnly(self.text) if helpURL: - CtxMenu.addCtxMenu( + addCtxMenu( wdg = self.text, helpURL = helpURL + "#LogDisplay", ) @@ -157,7 +158,7 @@ def __init__(self, self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) - detFrame = Tkinter.Frame(self) + detFrame = tkinter.Frame(self) gr = RO.Wdg.Gridder(detFrame, sticky="ew") @@ -443,7 +444,7 @@ def _updDetailStatus(self): if __name__ == "__main__": - from PythonTk import PythonTk + from .PythonTk import PythonTk root = PythonTk() row = 0 @@ -454,9 +455,9 @@ def _updDetailStatus(self): testFrame.grid(row=row, column=0, columnspan=2, sticky="nsew") row += 1 - overwriteVar = Tkinter.BooleanVar() + overwriteVar = tkinter.BooleanVar() overwriteVar.set(True) - overwriteWdg = Tkinter.Checkbutton( + overwriteWdg = tkinter.Checkbutton( master=root, text="Overwrite", variable=overwriteVar, @@ -464,14 +465,14 @@ def _updDetailStatus(self): overwriteWdg.grid(row=row, column=1, sticky="w") row += 1 - Tkinter.Label(root, text="ToPath:").grid(row=row, column=0, sticky="e") - toPathWdg = Tkinter.Entry(root) + tkinter.Label(root, text="ToPath:").grid(row=row, column=0, sticky="e") + toPathWdg = tkinter.Entry(root) toPathWdg.insert(0, "tempfile") toPathWdg.grid(row=row, column=1, sticky="ew") row += 1 - Tkinter.Label(root, text="FromURL:").grid(row=row, column=0, sticky="e") - fromURLWdg = Tkinter.Entry(root) + tkinter.Label(root, text="FromURL:").grid(row=row, column=0, sticky="e") + fromURLWdg = tkinter.Entry(root) fromURLWdg.grid(row=row, column=1, sticky="ew") row += 1 diff --git a/python/RO/Wdg/GrayImageDispWdg.py b/python/RO/Wdg/GrayImageDispWdg.py index ae448ca..c8aaa6f 100755 --- a/python/RO/Wdg/GrayImageDispWdg.py +++ b/python/RO/Wdg/GrayImageDispWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Code to display a grayscale image. This attempts to emulate some of the more important features of ds9, @@ -170,11 +170,12 @@ 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. 2017-01-26 CSayres Improve compatibility with recent versions Pillow by casting image shape to a tuple when calling fromBuffer. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ["ann_Circle", "ann_Plus", "ann_X", "ann_Line", "ann_Text", "MaskInfo", "GrayImageWdg"] import weakref -import Tkinter +import tkinter import math import numpy try: @@ -189,10 +190,10 @@ import RO.Constants import RO.SeqUtil import RO.TkUtil -import Entry -import Label -import OptionMenu -import RadiobuttonSet +from . import Entry +from .Label import StrLabel, FloatLabel +from . import OptionMenu +from . import RadiobuttonSet _AnnTag = "_gs_ann_" _DragRectTag = "_gs_dragRect" @@ -232,7 +233,7 @@ def getBitmapDict(): _ModeZoom: "magnifier", } retDict = {} - for mode, bitmapName in modeDict.iteritems(): + for mode, bitmapName in modeDict.items(): retDict[mode] = "@%s.xbm" % os.path.join(bitmapDir, bitmapName) return retDict @@ -271,7 +272,7 @@ def __init__(self, self.wdg = None if not self.tkWdg: - self.tkWdg = Tkinter.Frame() + self.tkWdg = tkinter.Frame() self.setColor(color) @@ -413,7 +414,7 @@ def delete(self): """ self.gim.cnv.delete(self.idTag) -class GrayImageWdg(Tkinter.Frame, RO.AddCallback.BaseMixin): +class GrayImageWdg(tkinter.Frame, RO.AddCallback.BaseMixin): """Display a grayscale image. Inputs: @@ -439,7 +440,7 @@ def __init__(self, callFunc = None, defRange = "99.9%", **kargs): - Tkinter.Frame.__init__(self, master, **kargs) + tkinter.Frame.__init__(self, master, **kargs) RO.AddCallback.BaseMixin.__init__(self) if defRange not in self._RangeMenuItems: raise RuntimeError("invalid defRange") @@ -496,7 +497,7 @@ def __init__(self, self._memDebugDict = {} # tool bar - toolFrame = Tkinter.Frame(self) + toolFrame = tkinter.Frame(self) self.scaleMenuWdg = OptionMenu.OptionMenu( master = toolFrame, @@ -574,8 +575,8 @@ def __init__(self, self.toolFrame = toolFrame # add current position and current value widgets - posFrame = Tkinter.Frame(self) - Label.StrLabel( + posFrame = tkinter.Frame(self) + StrLabel( posFrame, text = " Cursor Pos: ", bd = 0, @@ -583,7 +584,7 @@ def __init__(self, helpText = "Cursor position (pix)", helpURL = helpURL, ).pack(side="left") - self.currXPosWdg = Label.FloatLabel( + self.currXPosWdg = FloatLabel( posFrame, width = 6, precision = 1, @@ -593,13 +594,13 @@ def __init__(self, helpURL = helpURL, ) self.currXPosWdg.pack(side="left") - Label.StrLabel( + StrLabel( posFrame, text=",", bd = 0, padx = 0, ).pack(side="left") - self.currYPosWdg = Label.FloatLabel( + self.currYPosWdg = FloatLabel( posFrame, width = 6, precision = 1, @@ -609,7 +610,7 @@ def __init__(self, helpURL = helpURL, ) self.currYPosWdg.pack(side="left") - Label.StrLabel( + StrLabel( posFrame, text = " Value: ", bd = 0, @@ -617,7 +618,7 @@ def __init__(self, helpText = "Value at cursor (ADUs)", helpURL = helpURL, ).pack(side="left") - self.currValWdg = Label.FloatLabel( + self.currValWdg = FloatLabel( posFrame, bd = 0, padx = 0, @@ -629,13 +630,13 @@ def __init__(self, posFrame.pack(side="bottom", anchor="nw") # set up scrolling panel to display canvas and error messages - self.scrollFrame = Tkinter.Frame(self, height=height, width=width) #, borderwidth=2, relief="sunken") + self.scrollFrame = tkinter.Frame(self, height=height, width=width) #, borderwidth=2, relief="sunken") self.scrollFrame.grid_propagate(False) - self.strMsgWdg = Label.StrLabel(self.scrollFrame) + self.strMsgWdg = StrLabel(self.scrollFrame) self.strMsgWdg.grid(row=0, column=0) self.strMsgWdg.grid_remove() - self.hsb = Tkinter.Scrollbar( + self.hsb = tkinter.Scrollbar( self.scrollFrame, orient="horizontal", width = 10, @@ -645,7 +646,7 @@ def __init__(self, self._hscrollbar = self.hsb self.hsb.set(0.0, 1.0) - self.vsb = Tkinter.Scrollbar( + self.vsb = tkinter.Scrollbar( self.scrollFrame, orient="vertical", width = 10, @@ -654,7 +655,7 @@ def __init__(self, self.vsb.grid(row=0, column=1, sticky="ns") self.vsb.set(0.0, 1.0) - self.cnv = Tkinter.Canvas( + self.cnv = tkinter.Canvas( master = self.scrollFrame, # cursor="tcross", bd = 0, @@ -1150,7 +1151,7 @@ def redisplay(self): self.applyRange(redisplay=False) # display annotations - for ann in self.annDict.itervalues(): + for ann in self.annDict.values(): ann.draw() except MemoryError: self.showMsg("Insufficient Memory!", severity=RO.Constants.sevError) @@ -1161,7 +1162,7 @@ def removeAnnotation(self, tag): """Remove all annotations (if any) with the specified tag. """ newDict = {} - for tags, ann in self.annDict.iteritems(): + for tags, ann in self.annDict.items(): if tag in tags: ann.delete() else: @@ -1509,8 +1510,8 @@ def limitZoomFac(desZoomFac): except ImportError: import pyfits import RO.DS9 - import PythonTk - import StatusBar + from . import PythonTk + from . import StatusBar root = PythonTk.PythonTk() root.geometry("450x450") diff --git a/python/RO/Wdg/Gridder.py b/python/RO/Wdg/Gridder.py index adc20c3..2cd3036 100755 --- a/python/RO/Wdg/Gridder.py +++ b/python/RO/Wdg/Gridder.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Tools for gridding widgets History: @@ -35,13 +35,14 @@ 2011-07-29 ROwen _BaseGridSet: added __getitem__, __len__ and __length__ to simplify access to widgets. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. 2015-11-05 ROwen Changed ==/!= True/False to is/is not True/False to modernize the code. +2020-02-10 DGatlin Updated imports to support Python 3 """ __all__ = ['Gridder'] -import Tkinter +import tkinter import RO.Alg import RO.SeqUtil -import Label +from .Label import Label, StrLabel class Gridder(object): def __init__(self, @@ -102,7 +103,7 @@ def addShowHideControl(self, cat, ctrl): # record show/hide controls self._showHideControlDict[cat] = ctrl - for ctrl in self._showHideControlDict.itervalues(): + for ctrl in self._showHideControlDict.values(): ctrl.addCallback(self._showHideWdgCallback) # add category, if necessary @@ -244,14 +245,14 @@ def showHideWdg(self, **kargs): Raises KeyError if a specified category does not already exist. """ # update _showHideCatDict - for cat, doShow in kargs.iteritems(): + for cat, doShow in kargs.items(): # make sure the category already exists self._showHideCatDict[cat] # set the category self._showHideCatDict[cat] = doShow # use _showHideCatDict to show or hide widgets - for wdg, catList in self._showHideWdgDict.iteritems(): + for wdg, catList in self._showHideWdgDict.items(): for cat in catList: if not self._showHideCatDict[cat]: wdg.grid_remove() @@ -283,7 +284,7 @@ def startNewCol(self, row=0, col=None, spacing=0): spaceCol = newDefCol - 1 if spaceCol < self._maxNextCol: raise ValueError("col too small; no room for spacer column") - Tkinter.Frame(self._master, width=spacing).grid(row=row, column=spaceCol) + tkinter.Frame(self._master, width=spacing).grid(row=row, column=spaceCol) self.setDefCol(newDefCol) @@ -302,7 +303,7 @@ def _basicKArgs(self, **kargs): def _showHideWdgCallback(self, wdg=None): """Called if any showHide widget changes state. """ - for cat, wdg in self._showHideControlDict.iteritems(): + for cat, wdg in self._showHideControlDict.items(): self._showHideCatDict[cat] = wdg.getBool() self.showHideWdg() @@ -381,20 +382,20 @@ def _makeWdg(self, wdgInfo): """ if wdgInfo in (None, False): return wdgInfo - elif isinstance(wdgInfo, Tkinter.Widget): + elif isinstance(wdgInfo, tkinter.Widget): # a widget; assume it's a Label widget of some kind return wdgInfo - if isinstance(wdgInfo, Tkinter.Variable): + if isinstance(wdgInfo, tkinter.Variable): # a Tkinter variable - wdg = Label.StrLabel( + wdg = StrLabel( master = self.master, textvariable = wdgInfo, helpText = self.helpText, helpURL = self.helpURL, ) else: - wdg = Label.StrLabel( + wdg = StrLabel( master = self.master, text = wdgInfo, helpText = self.helpText, @@ -494,35 +495,35 @@ def __init__ (self, self._gridWdg(self.unitsWdg, sticky="w", colSpan=1) if __name__ == "__main__": - import PythonTk + from . import PythonTk root = PythonTk.PythonTk() - wdgFrame = Tkinter.Frame(root) + wdgFrame = tkinter.Frame(root) gr = Gridder(wdgFrame) gr.gridWdg ( label = "Opt 1", - dataWdg = Tkinter.Entry(wdgFrame, width=5), + dataWdg = tkinter.Entry(wdgFrame, width=5), units = "mHz", ) - sv = Tkinter.StringVar() + sv = tkinter.StringVar() sv.set("Option 2") gs = gr.gridWdg ( label = sv, - dataWdg = Tkinter.Entry(wdgFrame, width=5), + dataWdg = tkinter.Entry(wdgFrame, width=5), units = "bars", ) gr.gridWdg ( - label = Tkinter.Label(wdgFrame, text="No Units"), - dataWdg = Tkinter.Entry(wdgFrame, width=5), + label = tkinter.Label(wdgFrame, text="No Units"), + dataWdg = tkinter.Entry(wdgFrame, width=5), ) gr.gridWdg ( label = "Blank Units", - dataWdg = Tkinter.Entry(wdgFrame, width=5), + dataWdg = tkinter.Entry(wdgFrame, width=5), units = "", ) gr.gridWdg ( label = "Pair", - dataWdg = [Tkinter.Entry(wdgFrame, width=5) for ii in range(2)], + dataWdg = [tkinter.Entry(wdgFrame, width=5) for ii in range(2)], ) wdgFrame.pack() diff --git a/python/RO/Wdg/HTTPGetWdg.py b/python/RO/Wdg/HTTPGetWdg.py index dccb4dd..4637eb7 100755 --- a/python/RO/Wdg/HTTPGetWdg.py +++ b/python/RO/Wdg/HTTPGetWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """HTTP download with Tkinter-based progress reporting Downloads files given the url and destination path. @@ -33,14 +33,14 @@ import sys import traceback import weakref -import Bindings -import Tkinter +from . import Bindings +import tkinter import RO.AddCallback import RO.Constants import RO.MathUtil import RO.Comm.HTTPGet as HTTPGet import RO.Wdg -import CtxMenu +from .CtxMenu import addCtxMenu _StatusInterval = 200 # ms between status checks @@ -75,7 +75,7 @@ def clear(self): self.callFunc = None -class HTTPGetWdg(Tkinter.Frame): +class HTTPGetWdg(tkinter.Frame): """A widget to initiate file get via http, to display the status of the transfer and to allow users to abort the transfer. @@ -96,7 +96,7 @@ def __init__(self, maxLines = 500, helpURL = None, **kargs): - Tkinter.Frame.__init__(self, master = master, **kargs) + tkinter.Frame.__init__(self, master = master, **kargs) self._memDebugDict = {} self.maxLines = maxLines @@ -106,11 +106,11 @@ def __init__(self, self.dispList = [] # list of displayed httpGets self.getQueue = [] # list of unfinished (httpGet, stateLabel) tuples - self.yscroll = Tkinter.Scrollbar ( + self.yscroll = tkinter.Scrollbar ( master = self, orient = "vertical", ) - self.text = Tkinter.Text ( + self.text = tkinter.Text ( master = self, yscrollcommand = self.yscroll.set, wrap = "none", @@ -123,7 +123,7 @@ def __init__(self, self.yscroll.grid(row=0, column=1, sticky="ns") Bindings.makeReadOnly(self.text) if helpURL: - CtxMenu.addCtxMenu( + addCtxMenu( wdg = self.text, helpURL = helpURL + "#LogDisplay", ) @@ -131,7 +131,7 @@ def __init__(self, self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) - detFrame = Tkinter.Frame(self) + detFrame = tkinter.Frame(self) gr = RO.Wdg.Gridder(detFrame, sticky="ew") @@ -377,7 +377,7 @@ def _updDetailStatus(self): if __name__ == "__main__": - from PythonTk import PythonTk + from .PythonTk import PythonTk root = PythonTk() row = 0 @@ -388,9 +388,9 @@ def _updDetailStatus(self): testFrame.grid(row=row, column=0, columnspan=2, sticky="nsew") row += 1 - overwriteVar = Tkinter.BooleanVar() + overwriteVar = tkinter.BooleanVar() overwriteVar.set(True) - overwriteWdg = Tkinter.Checkbutton( + overwriteWdg = tkinter.Checkbutton( master=root, text="Overwrite", variable=overwriteVar, @@ -398,14 +398,14 @@ def _updDetailStatus(self): overwriteWdg.grid(row=row, column=1, sticky="w") row += 1 - Tkinter.Label(root, text="ToPath:").grid(row=row, column=0, sticky="e") - toPathWdg = Tkinter.Entry(root) + tkinter.Label(root, text="ToPath:").grid(row=row, column=0, sticky="e") + toPathWdg = tkinter.Entry(root) toPathWdg.insert(0, "tempfile") toPathWdg.grid(row=row, column=1, sticky="ew") row += 1 - Tkinter.Label(root, text="FromURL:").grid(row=row, column=0, sticky="e") - fromURLWdg = Tkinter.Entry(root) + tkinter.Label(root, text="FromURL:").grid(row=row, column=0, sticky="e") + fromURLWdg = tkinter.Entry(root) fromURLWdg.grid(row=row, column=1, sticky="ew") row += 1 diff --git a/python/RO/Wdg/HistoryMenu.py b/python/RO/Wdg/HistoryMenu.py index 286c0ce..9ae36e0 100755 --- a/python/RO/Wdg/HistoryMenu.py +++ b/python/RO/Wdg/HistoryMenu.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A menu showing a history of recent events. Saves arbitrary data associated with each event and calls a user-specified callback when any item is selected. @@ -16,14 +16,15 @@ 2004-08-11 ROwen Define __all__ to restrict import. 2004-09-14 ROwen Test code no longer imports RO.Wdg to avoid circular import. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['HistoryMenu'] -import Tkinter +import tkinter import RO.Alg -import CtxMenu +from .CtxMenu import CtxMenu, CtxMenuMixin -class HistoryMenu (Tkinter.Menubutton, CtxMenu.CtxMenuMixin): +class HistoryMenu (tkinter.Menubutton, CtxMenuMixin): """A menu showing a history of recent events. Inputs: @@ -49,14 +50,14 @@ def __init__(self, helpText = None, helpURL = None, ): - Tkinter.Menubutton.__init__(self, + tkinter.Menubutton.__init__(self, master=master, text="History", indicatoron=1, relief="raised", # state="disabled", ) - CtxMenu.CtxMenuMixin.__init__(self, helpURL = helpURL) + CtxMenuMixin.__init__(self, helpURL = helpURL) self.__callFunc = callFunc self.__removeAdjDup = removeAdjDup @@ -65,7 +66,7 @@ def __init__(self, self.helpText = helpText # basic menu - self.__menu = Tkinter.Menu(self, tearoff=0) + self.__menu = tkinter.Menu(self, tearoff=0) self["menu"] = self.__menu self.dataDict = {} @@ -115,7 +116,7 @@ def nItems(self): if __name__ == "__main__": - import PythonTk + from . import PythonTk root = PythonTk.PythonTk() def doAdd(*args): @@ -126,9 +127,9 @@ def doAdd(*args): def doPrint(name, data): print("name=%r, data=%r" % (name, data)) - Tkinter.Label(root, text="Name of new entry (type to accept it):").pack() - nameVar = Tkinter.StringVar() - nameWdg = Tkinter.Entry(root, textvariable=nameVar) + tkinter.Label(root, text="Name of new entry (type to accept it):").pack() + nameVar = tkinter.StringVar() + nameWdg = tkinter.Entry(root, textvariable=nameVar) nameWdg.bind("", doAdd) nameWdg.pack() testFrame = HistoryMenu(root, diff --git a/python/RO/Wdg/InputContFrame.py b/python/RO/Wdg/InputContFrame.py index 08c1e17..b8374bb 100644 --- a/python/RO/Wdg/InputContFrame.py +++ b/python/RO/Wdg/InputContFrame.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """ History: @@ -14,9 +14,9 @@ """ __all__ = ['InputContFrame'] -import Tkinter +import tkinter -class InputContFrame(Tkinter.Frame): +class InputContFrame(tkinter.Frame): """A convenience class for widgets containing an RO.InputCont container class. You must store the container list in instance variable self.inputCont and all the important calls automatically work. @@ -25,7 +25,7 @@ class InputContFrame(Tkinter.Frame): changes in InputCont, but avoids cluttering up your class with attributes. """ def __init__(self, master, stateTracker=None, **kargs): - Tkinter.Frame.__init__(self, master, **kargs) + tkinter.Frame.__init__(self, master, **kargs) self._stateTracker = stateTracker def addCallback(self, callFunc, callNow=False): diff --git a/python/RO/Wdg/InputContPresetsWdg.py b/python/RO/Wdg/InputContPresetsWdg.py index c410a11..8d4aea7 100755 --- a/python/RO/Wdg/InputContPresetsWdg.py +++ b/python/RO/Wdg/InputContPresetsWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Widget to manage named presets of an input container list History: @@ -8,18 +8,19 @@ 2014-03-13 ROwen Bug fix: was not recording default values. The fix required an update to InputCont. 2014-03-14 ROwen Added helpText and helpURL arguments. 2014-05-07 ROwen Added autoUpdate argument and modified to use RO.Wdg.Menubutton +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ["InputContPresetsWdg"] import functools -import Tkinter +import tkinter import RO.TkUtil -import Entry -import Label -import InputDialog -import OptionMenu -import Menubutton +from . import Entry +from .Label import Label, StrLabel +from . import InputDialog +from . import OptionMenu +from . import Menubutton class InputContPresetsWdg(Menubutton.Menubutton): """Widget to manage named presets for an input container list @@ -83,9 +84,9 @@ def __init__(self, } wdgKArgs.update(kwargs) Menubutton.Menubutton.__init__(self, master, helpText=helpText, helpURL=helpURL, **wdgKArgs) - self._menu = Tkinter.Menu(self, tearoff=False) + self._menu = tkinter.Menu(self, tearoff=False) - editMenu = Tkinter.Menu( + editMenu = tkinter.Menu( self._menu, tearoff = False, ) @@ -218,12 +219,12 @@ def _getCurrPreset(self): if presetValDict and isSubDict(presetValDict, currValDict): return currPresetName, isUserPreset - for presetName, presetValDict in self._userPresets.iteritems(): + for presetName, presetValDict in self._userPresets.items(): # user presets are always complete, so no need to look for incomplete entries if presetValDict and presetValDict == currValDict: return presetName, True - for presetName, presetValDict in self._stdPresets.iteritems(): + for presetName, presetValDict in self._stdPresets.items(): # standard presets may be incomplete, so use isSubDict if isSubDict(presetValDict, currValDict): return presetName, False @@ -233,13 +234,13 @@ def _getCurrPreset(self): def _getStdPresetNames(self): """Get a sorted list of default preset names """ - return sorted(self._stdPresets.iterkeys()) + return sorted(self._stdPresets.keys()) def _getUserPresetNames(self): """Get a sorted list of current preset names """ preset = self._userPresetsDict.get(self._sysName, dict()) - return sorted(preset.iterkeys()) + return sorted(preset.keys()) def _updateDisplayedName(self, dumArg=None): """Update the displayed name @@ -291,7 +292,7 @@ def __init__(self, master, currNameList): InputDialog.ModalDialogBase.__init__(self, master=master, title="Save") def body(self, master): - Label.StrLabel(master=master, text="Save This Preset As:").grid(row=0, column=0, columnspan=5) + StrLabel(master=master, text="Save This Preset As:").grid(row=0, column=0, columnspan=5) # Tkinter.Label(master, text="Name:").grid(row=1, column=0) self.nameEntry = Entry.StrEntry(master) self.currNameWdg = OptionMenu.OptionMenu( @@ -324,7 +325,7 @@ def __init__(self, master, currNameList): InputDialog.ModalDialogBase.__init__(self, master=master, title="Save") def body(self, master): - Label.StrLabel(master=master, text="Rename Preset:").grid(row=0, column=0, columnspan=5) + StrLabel(master=master, text="Rename Preset:").grid(row=0, column=0, columnspan=5) # Tkinter.Label(master, text="Name:").grid(row=1, column=0) self.oldNameWdg = OptionMenu.OptionMenu( master = master, @@ -354,7 +355,7 @@ def __init__(self, master, currNameList): InputDialog.ModalDialogBase.__init__(self, master=master, title="Delete") def body(self, master): - Label.StrLabel(master=master, text="Delete Preseturation:").grid(row=0, column=0, columnspan=5) + StrLabel(master=master, text="Delete Preseturation:").grid(row=0, column=0, columnspan=5) self.currNameWdg = OptionMenu.OptionMenu( master = master, items = self._currNameList, @@ -370,7 +371,7 @@ class RestoreDefaultsDialog(InputDialog.ModalDialogBase): """Dialog box to confirm restoring defaults; result is True if restore wanted """ def body(self, master): - Label.StrLabel(master=master, text="Restore Default Presets?").grid(row=0, column=0) + StrLabel(master=master, text="Restore Default Presets?").grid(row=0, column=0) def setResult(self): self.result = True @@ -379,18 +380,18 @@ def setResult(self): if __name__ == '__main__': from RO.Alg import SavedDict import RO.InputCont - import Gridder - import InputContFrame + from .Gridder import Gridder + from .InputContFrame import InputContFrame - root = Tkinter.Tk() + root = tkinter.Tk() root.geometry("200x200") userPresetsDict = SavedDict("testPreset.json") - class TestFrame(InputContFrame.InputContFrame): + class TestFrame(InputContFrame): def __init__(self, master): - InputContFrame.InputContFrame.__init__(self, master, stateTracker=None) + InputContFrame.__init__(self, master, stateTracker=None) - gr = Gridder.Gridder(master=self) + gr = Gridder(master=self) self.wdg1 = Entry.StrEntry(self) gr.gridWdg("Widget 1", self.wdg1) diff --git a/python/RO/Wdg/InputDialog.py b/python/RO/Wdg/InputDialog.py index 1c92623..ef90fae 100755 --- a/python/RO/Wdg/InputDialog.py +++ b/python/RO/Wdg/InputDialog.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Basic dialog class(es). The dialog's window is shown when the object is created and destroyed when the user exits the dialog. The result is contained in dialog.result and is None if the dialog is cancelled. @@ -26,11 +26,11 @@ """ __all__ = ['ModalDialogBase'] -import Tkinter +import tkinter -import Button +from . import Button -class ModalDialogBase(Tkinter.Toplevel): +class ModalDialogBase(tkinter.Toplevel): """Base class for modal dialogs. The result is returned in self.result @@ -41,7 +41,7 @@ class ModalDialogBase(Tkinter.Toplevel): def __init__(self, master = None, title = None): """Create and display a modal dialog. """ - Tkinter.Toplevel.__init__(self, master) + tkinter.Toplevel.__init__(self, master) self.resizable(False, False) if title: @@ -49,16 +49,16 @@ def __init__(self, master = None, title = None): self.result = None - self.doneVar = Tkinter.BooleanVar() + self.doneVar = tkinter.BooleanVar() # widget that had focus before this dialog opened self.prevFocus = self.focus_get() or master - buttonFrame = Tkinter.Frame(self) + buttonFrame = tkinter.Frame(self) self.buttons(master = buttonFrame) buttonFrame.pack(side="bottom") - bodyFrame = Tkinter.Frame(self) + bodyFrame = tkinter.Frame(self) # create dialog body and save widget that should # initially get focus in this dialog self.initialFocus = self.body(master = bodyFrame) @@ -78,18 +78,18 @@ def __init__(self, master = None, title = None): # it's just a best-effort attempt to grab (make the dialog box modal). try: self.wait_visibility() - except Tkinter.TclError: + except tkinter.TclError: pass try: self.grab_set() - except Tkinter.TclError: + except tkinter.TclError: pass self.wait_variable(self.doneVar) try: self.grab_release() - except Tkinter.TclError: + except tkinter.TclError: pass if self.prevFocus: @@ -152,11 +152,11 @@ def setResult(self): class TestDialog(ModalDialogBase): def body(self, master): - Tkinter.Label(master, text="Name:").grid(row=0) - Tkinter.Label(master, text="Password:").grid(row=1) + tkinter.Label(master, text="Name:").grid(row=0) + tkinter.Label(master, text="Password:").grid(row=1) - self.e1 = Tkinter.Entry(master) - self.e2 = Tkinter.Entry(master, show="*") + self.e1 = tkinter.Entry(master) + self.e2 = tkinter.Entry(master, show="*") self.e1.grid(row=0, column=1) self.e2.grid(row=1, column=1) @@ -172,12 +172,12 @@ def doDialog(): l["text"] = "Result: %s" % (d.result,) print(d.result) - root = Tkinter.Tk() - e = Tkinter.Entry(root) + root = tkinter.Tk() + e = tkinter.Entry(root) e.pack() - l = Tkinter.Label(root) + l = tkinter.Label(root) l.pack() - b = Tkinter.Button(root, text="Dialog", command=doDialog) + b = tkinter.Button(root, text="Dialog", command=doDialog) b.pack() e.focus_set() diff --git a/python/RO/Wdg/IsCurrentMixin.py b/python/RO/Wdg/IsCurrentMixin.py index 488cc50..b05f04c 100755 --- a/python/RO/Wdg/IsCurrentMixin.py +++ b/python/RO/Wdg/IsCurrentMixin.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Mixin classes that add an "isCurrent" flag and adjust the widget background color based on that flag. @@ -22,7 +22,7 @@ """ __all__ = ["IsCurrentMixin", "IsCurrentActiveMixin", "IsCurrentCheckbuttonMixin", "AutoIsCurrentMixin"] -import WdgPrefs +from . import WdgPrefs class IsCurrentMixin(object): """Mixin classes that add an "isCurrent" flag @@ -226,33 +226,33 @@ def getIsCurrent(self): if __name__ == "__main__": - import Tkinter - import PythonTk + import tkinter + from . import PythonTk root = PythonTk.PythonTk() - class ColorButton(Tkinter.Button, IsCurrentActiveMixin): + class ColorButton(tkinter.Button, IsCurrentActiveMixin): def __init__(self, *args, **kargs): - Tkinter.Button.__init__(self, *args, **kargs) + tkinter.Button.__init__(self, *args, **kargs) IsCurrentActiveMixin.__init__(self) - class ColorCheckbutton(Tkinter.Checkbutton, IsCurrentActiveMixin): + class ColorCheckbutton(tkinter.Checkbutton, IsCurrentActiveMixin): def __init__(self, *args, **kargs): - Tkinter.Checkbutton.__init__(self, *args, **kargs) + tkinter.Checkbutton.__init__(self, *args, **kargs) IsCurrentActiveMixin.__init__(self) - class ColorEntry(Tkinter.Entry, IsCurrentMixin): + class ColorEntry(tkinter.Entry, IsCurrentMixin): def __init__(self, *args, **kargs): - Tkinter.Entry.__init__(self, *args, **kargs) + tkinter.Entry.__init__(self, *args, **kargs) IsCurrentMixin.__init__(self) - class ColorLabel(Tkinter.Label, IsCurrentMixin): + class ColorLabel(tkinter.Label, IsCurrentMixin): def __init__(self, *args, **kargs): - Tkinter.Label.__init__(self, *args, **kargs) + tkinter.Label.__init__(self, *args, **kargs) IsCurrentMixin.__init__(self) - class ColorOptionMenu(Tkinter.OptionMenu, IsCurrentActiveMixin): + class ColorOptionMenu(tkinter.OptionMenu, IsCurrentActiveMixin): def __init__(self, *args, **kargs): - Tkinter.OptionMenu.__init__(self, *args, **kargs) + tkinter.OptionMenu.__init__(self, *args, **kargs) IsCurrentActiveMixin.__init__(self) def setIsCurrent(*args): @@ -261,14 +261,14 @@ def setIsCurrent(*args): for wdg in wdgSet: wdg.setIsCurrent(isCurrent) - isCurrentVar = Tkinter.BooleanVar() + isCurrentVar = tkinter.BooleanVar() isCurrentVar.set(True) isCurrentVar.trace_variable("w", setIsCurrent) - stateVar = Tkinter.StringVar() + stateVar = tkinter.StringVar() stateVar.set("Normal") - entryVar = Tkinter.StringVar() + entryVar = tkinter.StringVar() entryVar.set("Entry") wdgSet = ( ColorCheckbutton(root, @@ -292,6 +292,6 @@ def setIsCurrent(*args): ), ) for wdg in wdgSet: - wdg.pack(fill=Tkinter.X) + wdg.pack(fill=tkinter.X) root.mainloop() diff --git a/python/RO/Wdg/Label.py b/python/RO/Wdg/Label.py index 88d9af3..a774382 100755 --- a/python/RO/Wdg/Label.py +++ b/python/RO/Wdg/Label.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """RO.Wdg.Label widgets are display widgets that store data in its most basic form, yet know how to format it for display. These widgets consider their data to be bad (and display it with a bad background color) if the value is None or the value is not current. @@ -51,19 +51,20 @@ 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. 2015-11-05 ROwen Stop using dangerous bare "except:". +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['Label', 'BoolLabel', 'StrLabel', 'IntLabel', 'FloatLabel', 'DMSLabel'] import sys -import Tkinter +import tkinter import RO.Constants import RO.MathUtil import RO.StringUtil -import CtxMenu -from SeverityMixin import SeverityMixin -from IsCurrentMixin import IsCurrentMixin +from .CtxMenu import CtxMenu, CtxMenuMixin +from .SeverityMixin import SeverityMixin +from .IsCurrentMixin import IsCurrentMixin -class Label(Tkinter.Label, CtxMenu.CtxMenuMixin, IsCurrentMixin, SeverityMixin): +class Label(tkinter.Label, CtxMenuMixin, IsCurrentMixin, SeverityMixin): """Base class for labels (display ROWdgs); do not use directly. Inputs: @@ -89,7 +90,7 @@ class Label(Tkinter.Label, CtxMenu.CtxMenuMixin, IsCurrentMixin, SeverityMixin): def __init__ (self, master, formatStr = None, - formatFunc = unicode, + formatFunc = str, helpText = None, helpURL = None, isCurrent = True, @@ -98,9 +99,9 @@ def __init__ (self, kargs.setdefault("anchor", "e") kargs.setdefault("justify", "right") - Tkinter.Label.__init__(self, master, **kargs) + tkinter.Label.__init__(self, master, **kargs) - CtxMenu.CtxMenuMixin.__init__(self, helpURL=helpURL) + CtxMenuMixin.__init__(self, helpURL=helpURL) IsCurrentMixin.__init__(self, isCurrent) @@ -354,7 +355,7 @@ def setCvtDegToHrs(self, cvtDegToHrs): if __name__ == "__main__": - import PythonTk + from . import PythonTk from RO.TkUtil import Timer root = PythonTk.PythonTk() @@ -392,7 +393,7 @@ def setCvtDegToHrs(self, cvtDegToHrs): ), ) for wdg in wdgSet: - wdg.pack(fill=Tkinter.X) + wdg.pack(fill=tkinter.X) # a list of (value, isCurrent) pairs testData = [ diff --git a/python/RO/Wdg/LogWdg.py b/python/RO/Wdg/LogWdg.py index 4c5241a..8c6e34f 100755 --- a/python/RO/Wdg/LogWdg.py +++ b/python/RO/Wdg/LogWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A widget to display a scrolling log of information. Log entries may be categorized and each category may be displayed in a different color. Each category may be individually shown or hidden. @@ -70,18 +70,18 @@ """ __all__ = ['LogWdg'] -import Tkinter +import tkinter import RO.Alg -import Text +from . import Text _AllTextTag = "__alltext" _SevTagDict = RO.Alg.OrderedDict( - (sev, "__sev_%s" % (name,)) for sev, name in RO.Constants.SevNameDict.iteritems()) + (sev, "__sev_%s" % (name,)) for sev, name in RO.Constants.SevNameDict.items()) _SevTagListDict = RO.Alg.OrderedDict( - (sev, _SevTagDict.values()[ind:]) for ind, sev in enumerate(_SevTagDict.iterkeys())) + (sev, list(_SevTagDict.values())[ind:]) for ind, sev in enumerate(_SevTagDict.keys())) -class LogWdg(Tkinter.Frame): +class LogWdg(tkinter.Frame): def __init__(self, master, @@ -106,12 +106,12 @@ def __init__(self, (if already at end of text) by default. - **kargs: additional keyword arguments for Frame """ - Tkinter.Frame.__init__(self, master=master, **kargs) + tkinter.Frame.__init__(self, master=master, **kargs) self.maxLineIndex = maxLines + 1 self.doAutoScroll = bool(doAutoScroll) - self.yscroll = Tkinter.Scrollbar ( + self.yscroll = tkinter.Scrollbar ( master = self, orient = "vertical", ) @@ -134,7 +134,7 @@ def __init__(self, # set up severity tags and tie them to color preferences self._severityPrefDict = RO.Wdg.WdgPrefs.getSevPrefDict() - for sev, sevTag in _SevTagDict.iteritems(): + for sev, sevTag in _SevTagDict.items(): pref = self._severityPrefDict[sev] if sev == RO.Constants.sevNormal: # normal color is already automatically updated @@ -143,7 +143,7 @@ def __init__(self, continue pref.addCallback(RO.Alg.GenericCallback(self._updSevTagColor, sevTag), callNow=True) - self.findCountVar = Tkinter.IntVar() + self.findCountVar = tkinter.IntVar() self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) @@ -507,7 +507,7 @@ def _updSevTagColor(self, sevTag, color, colorPref): if __name__ == '__main__': import random import sys - import PythonTk + from . import PythonTk root = PythonTk.PythonTk() testFrame = LogWdg ( @@ -516,9 +516,9 @@ def _updSevTagColor(self, sevTag, color, colorPref): ) testFrame.grid(row=0, column=0, sticky="nsew") - severityList = RO.Constants.SevNameDict.keys() + severityList = list(RO.Constants.SevNameDict.keys()) - entry = Tkinter.Entry(root) + entry = tkinter.Entry(root) entry.grid(row=1, column=0, sticky="nsew") def addMsg(msgStr): diff --git a/python/RO/Wdg/Menubutton.py b/python/RO/Wdg/Menubutton.py index cc969db..844b334 100644 --- a/python/RO/Wdg/Menubutton.py +++ b/python/RO/Wdg/Menubutton.py @@ -1,17 +1,18 @@ -from __future__ import division, print_function + """Variant on Menubutton that adds callback and severity functionality History: 2014-05-08 ROwen 2015-03-18 ROwen Removed Aqua 8.5 width bug workarounds because they are not wanted for Tcl/Tk 8.5.18 +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['Menubutton'] -import Tkinter +import tkinter import RO.Constants -import CtxMenu +from .CtxMenu import CtxMenu, CtxMenuMixin -class Menubutton(Tkinter.Menubutton, CtxMenu.CtxMenuMixin): +class Menubutton(tkinter.Menubutton, CtxMenuMixin): def __init__(self, master, helpText = None, @@ -33,9 +34,9 @@ def __init__(self, """ self.helpText = helpText - Tkinter.Menubutton.__init__(self, master = master, **kwArgs) + tkinter.Menubutton.__init__(self, master = master, **kwArgs) - CtxMenu.CtxMenuMixin.__init__(self, helpURL = helpURL) + CtxMenuMixin.__init__(self, helpURL = helpURL) def setEnable(self, doEnable): """Enable or disable widget @@ -46,13 +47,13 @@ def setEnable(self, doEnable): Warning: if you want the state to be "active" you must set that explicitly. """ if doEnable: - self["state"] = Tkinter.NORMAL + self["state"] = tkinter.NORMAL else: - self["state"] = Tkinter.DISABLED + self["state"] = tkinter.DISABLED def getEnable(self): """Return True if widget is enabled, False otherwise Enabled is defined as the state is not "disabled" (thus "enabled" or "active"). """ - return self["state"] != Tkinter.DISABLED + return self["state"] != tkinter.DISABLED diff --git a/python/RO/Wdg/OptionButtons.py b/python/RO/Wdg/OptionButtons.py index 4c09ffd..1fda27f 100755 --- a/python/RO/Wdg/OptionButtons.py +++ b/python/RO/Wdg/OptionButtons.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ A widget showing a set of options as checkbuttons. @@ -32,16 +32,17 @@ 2005-06-03 ROwen Fixed one indentation quirk (space tab -> tab). 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-05 ROwen Changed ==/!= True/False to is/is not True/False to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['OptionButtons'] import RO.InputCont -import Button -import Checkbutton -import InputContFrame -import Label +from . import Button +from . import Checkbutton +from .InputContFrame import InputContFrame +from .Label import Label -class OptionButtons(InputContFrame.InputContFrame): +class OptionButtons(InputContFrame): def __init__ (self, master, name, @@ -90,14 +91,14 @@ def __init__ (self, The default format is RO.InputCont.BasicFmt. **kargs: keyword arguments for Frame """ - InputContFrame.InputContFrame.__init__(self, master, **kargs) + InputContFrame.__init__(self, master, **kargs) # optional header if headerText: helpURL = helpURLPrefix if helpURL and helpURL.endswith("#"): helpURL = helpURL[:-1] - Label.Label( + Label( master = self, text = headerText, helpURL = helpURL, @@ -178,7 +179,7 @@ def listGet(aList, ind, defVal=None): wdg.pack(side="top", anchor="nw") if __name__ == "__main__": - import PythonTk + from . import PythonTk root = PythonTk.PythonTk() def doPrint(): diff --git a/python/RO/Wdg/OptionMenu.py b/python/RO/Wdg/OptionMenu.py index 5e37142..a1fdd5c 100755 --- a/python/RO/Wdg/OptionMenu.py +++ b/python/RO/Wdg/OptionMenu.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A variant of Tkinter.OptionMenu that adds many features. Extra features include: help, default handling, the ability to change menu items @@ -104,16 +104,17 @@ 2014-02-10 ROwen Added forceValid argument to set. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['OptionMenu'] -import Tkinter +import tkinter import RO.AddCallback import RO.Alg import RO.SeqUtil -from IsCurrentMixin import AutoIsCurrentMixin, IsCurrentActiveMixin -from SeverityMixin import SeverityActiveMixin -from Menubutton import Menubutton +from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentActiveMixin +from .SeverityMixin import SeverityActiveMixin +from .Menubutton import Menubutton class _DoItem: def __init__(self, var, value): @@ -190,7 +191,7 @@ def __init__(self, **kargs): showDefault = not (var and defValue is None) if var is None: - var = Tkinter.StringVar() + var = tkinter.StringVar() self._tempValue = None self._items = [] self.defValue = None @@ -224,7 +225,7 @@ def __init__(self, wdgKArgs["textvariable"] = var self.label = label Menubutton.__init__(self, master = master, helpURL = helpURL, **wdgKArgs) - self._menu = Tkinter.Menu(self, tearoff = False, postcommand = postCommand) + self._menu = tkinter.Menu(self, tearoff = False, postcommand = postCommand) self["menu"] = self._menu RO.AddCallback.TkVarMixin.__init__(self, var) @@ -544,9 +545,9 @@ def _doCallbacks(self): if __name__ == "__main__": - import Label - import PythonTk - import StatusBar + from .Label import Label + from . import PythonTk + from . import StatusBar root = PythonTk.PythonTk() def callFunc(wdg): @@ -605,7 +606,7 @@ def callFunc(wdg): menu5["width"] = 12 menu5.grid(row=1, column=2, sticky="w") - label = Label.Label(root, width=20, anchor="w", helpText="most recently selected value") + label = Label(root, width=20, anchor="w", helpText="most recently selected value") label.grid(row=2, column=0, columnspan=4, sticky="w") statusBar = StatusBar.StatusBar(root, width=20) diff --git a/python/RO/Wdg/OptionPanelControl.py b/python/RO/Wdg/OptionPanelControl.py index e7446f3..ce95536 100755 --- a/python/RO/Wdg/OptionPanelControl.py +++ b/python/RO/Wdg/OptionPanelControl.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ A set of checkbuttons that hides or shows widgets, e.g. option setting panels. @@ -27,9 +27,9 @@ """ __all__ = ['OptionPanelControl'] -import Tkinter -from Checkbutton import Checkbutton -from CtxMenu import CtxMenuMixin +import tkinter +from .Checkbutton import Checkbutton +from .CtxMenu import CtxMenuMixin class _WdgButton(Checkbutton): """A checkbutton that shows or hides a gridded widget. @@ -52,7 +52,7 @@ def __init__(self, try: var = wdg.getShowVar() except AttributeError: - var = Tkinter.BooleanVar() + var = tkinter.BooleanVar() Checkbutton.__init__(self, master = master, @@ -82,7 +82,7 @@ def setEnable(self, doEnable): self._updVisible() -class OptionPanelControl(Tkinter.Frame, CtxMenuMixin): +class OptionPanelControl(tkinter.Frame, CtxMenuMixin): def __init__ (self, master, wdgList, @@ -105,15 +105,15 @@ def __init__ (self, (i.e. packing or gridding). This widget displays checkbuttons which will automatically show or hide (by gridding or ungridding) the widgets within their master frame. """ - Tkinter.Frame.__init__(self, master, **kargs) + tkinter.Frame.__init__(self, master, **kargs) CtxMenuMixin.__init__(self) self._btnDict = {} if labelText is not None: - Tkinter.Label(self, text=labelText).pack(side="top", anchor="nw") + tkinter.Label(self, text=labelText).pack(side="top", anchor="nw") wdgMaster = wdgList[0][1].master - emptyFrame = Tkinter.Frame(wdgMaster) + emptyFrame = tkinter.Frame(wdgMaster) emptyFrame.grid(row=0, column=0) for ind in range(len(wdgList)): @@ -175,12 +175,12 @@ def setBool(self, wdgName, doShow): root = PythonTk() # frame for the set of hideable widgets - wdgFrame = Tkinter.Frame(root, bg="red", relief="ridge") + wdgFrame = tkinter.Frame(root, bg="red", relief="ridge") # hideable widgets - wdgA = Tkinter.Label(wdgFrame, text="Wdg A") - wdgB = Tkinter.Label(wdgFrame, text="Wdg B") - wdgC = Tkinter.Label(wdgFrame, text="Wdg C") + wdgA = tkinter.Label(wdgFrame, text="Wdg A") + wdgB = tkinter.Label(wdgFrame, text="Wdg B") + wdgC = tkinter.Label(wdgFrame, text="Wdg C") extFrame = OptionPanelControl( root, diff --git a/python/RO/Wdg/PatchedCanvas.py b/python/RO/Wdg/PatchedCanvas.py index 7c291c3..c3166e7 100755 --- a/python/RO/Wdg/PatchedCanvas.py +++ b/python/RO/Wdg/PatchedCanvas.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """A version of the Canvas class that draws correctly on unix, MacOS and MacOS X. @@ -15,11 +15,11 @@ __all__ = ['PatchedCanvas'] import warnings -import Tkinter +import tkinter -class PatchedCanvas(Tkinter.Canvas): +class PatchedCanvas(tkinter.Canvas): def __init__(self, *args, **kargs): - Tkinter.Canvas.__init__(self, *args, **kargs) + tkinter.Canvas.__init__(self, *args, **kargs) warnings.warn("RO.Wdg.PatchedCanvas is obsolete; please use Tkinter.Canvas instead.", category = DeprecationWarning, @@ -28,7 +28,7 @@ def __init__(self, *args, **kargs): if __name__ == "__main__": - root = Tkinter.Tk() + root = tkinter.Tk() c = PatchedCanvas(root, width=200, height=200) c.pack() diff --git a/python/RO/Wdg/PathWdg.py b/python/RO/Wdg/PathWdg.py index 9a39c76..bbd3906 100755 --- a/python/RO/Wdg/PathWdg.py +++ b/python/RO/Wdg/PathWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Widgets for selecting files and directories. To do: @@ -22,18 +22,19 @@ 2012-07-09 ROwen Modified to treat path="" as path=None. This fixes a problem with file and path prefs. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ["DirWdg", "FileWdg"] import os -import Tkinter -import tkFileDialog +import tkinter +import tkinter.filedialog import RO.AddCallback import RO.Constants -import CtxMenu -from SeverityMixin import SeverityActiveMixin +from .CtxMenu import CtxMenu, CtxMenuMixin +from .SeverityMixin import SeverityActiveMixin -class BasePathWdg (Tkinter.Button, RO.AddCallback.BaseMixin, CtxMenu.CtxMenuMixin, +class BasePathWdg (tkinter.Button, RO.AddCallback.BaseMixin, CtxMenuMixin, SeverityActiveMixin): def __init__(self, master, @@ -71,14 +72,14 @@ def __init__(self, self.leftChar = 0 self.rightChar = (self.maxChar - self.leftChar) - 1 - Tkinter.Button.__init__(self, + tkinter.Button.__init__(self, master = master, command = self._doChoose, **kargs) RO.AddCallback.BaseMixin.__init__(self) - CtxMenu.CtxMenuMixin.__init__(self, + CtxMenuMixin.__init__(self, helpURL = helpURL, ) SeverityActiveMixin.__init__(self, severity) @@ -123,16 +124,16 @@ def setEnable(self, doEnable): Warning: if you want the state to be "active" you must set that explicitly. """ if doEnable: - self["state"] = Tkinter.NORMAL + self["state"] = tkinter.NORMAL else: - self["state"] = Tkinter.DISABLED + self["state"] = tkinter.DISABLED def getEnable(self): """Return True if widget is enabled, False otherwise Enabled is defined as the state is not "disabled" (thus "enabled" or "active"). """ - return self["state"] != Tkinter.DISABLED + return self["state"] != tkinter.DISABLED def setPath(self, path): """Set self.path to normalized version of path. @@ -151,7 +152,7 @@ def setPath(self, path): if len(path) > self.maxChar: dispStr = "".join(( path[0:self.leftChar], - u"\N{HORIZONTAL ELLIPSIS}", + "\N{HORIZONTAL ELLIPSIS}", path[-self.rightChar:], )) else: @@ -222,7 +223,7 @@ def _doChoose(self): kargs = {} if self.fileTypes: kargs["filetypes"] = self.fileTypes - newPath = tkFileDialog.askdirectory( + newPath = tkinter.filedialog.askdirectory( initialdir = startDir, mustexist = True, title = self.helpText, @@ -267,7 +268,7 @@ def _doChoose(self): kargs = {} if self.fileTypes: kargs["filetypes"] = self.fileTypes - newPath = tkFileDialog.askopenfilename( + newPath = tkinter.filedialog.askopenfilename( initialdir = startDir, initialfile = startFile, title = self.helpText, diff --git a/python/RO/Wdg/ProgressBar.py b/python/RO/Wdg/ProgressBar.py index d134482..94482fb 100755 --- a/python/RO/Wdg/ProgressBar.py +++ b/python/RO/Wdg/ProgressBar.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ A basic widget for showing the progress being made in a task. Includes a countdown timer RemainingTime. @@ -26,19 +26,20 @@ 2012-07-10 ROwen Modified to use RO.TkUtil.Timer. Removed use of update_idletasks. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['ProgressBar', 'TimeBar'] import time import RO.SeqUtil from RO.TkUtil import Timer -import Tkinter -import Button -import Entry -import Gridder -import Label +import tkinter +from . import Button +from . import Entry +from .Gridder import Gridder +from .Label import Label, StrLabel -class ProgressBar (Tkinter.Frame): +class ProgressBar (tkinter.Frame): """A bar graph showing a value or fraction of a task performed. Contains three widgets: @@ -94,7 +95,7 @@ def __init__ (self, helpURL = None, **kargs): # handle defaults for background, borderwidth and relief - e = Tkinter.Entry() + e = tkinter.Entry() for item in ("background", "borderwidth", "relief"): kargs.setdefault(item, e[item]) @@ -102,7 +103,7 @@ def __init__ (self, for item in ("selectborderwidth", "highlightthickness"): kargs.setdefault(item, 0) - Tkinter.Frame.__init__(self, master) + tkinter.Frame.__init__(self, master) # basics self.constrainValue = constrainValue @@ -148,7 +149,7 @@ def __init__ (self, self.labelWdg.pack(side = packSide) # create canvas for bar graph - self.cnv = Tkinter.Canvas(self, + self.cnv = tkinter.Canvas(self, width = cnvWidth, height = cnvHeight, **kargs) @@ -168,7 +169,7 @@ def __init__ (self, # handle numeric value display if self.valueFormat[0]: - self.numWdg = Label.StrLabel(self, + self.numWdg = StrLabel(self, anchor = numAnchor, formatStr = self.valueFormat[0], helpText = self.helpText, @@ -178,7 +179,7 @@ def __init__ (self, # use an empty label to force bar thickness def nullFormat(astr): return "" - self.numWdg = Label.StrLabel(self, formatFunc = nullFormat) + self.numWdg = StrLabel(self, formatFunc = nullFormat) else: self.numWdg = None if self.numWdg is not None: @@ -316,7 +317,7 @@ def _makeWdg(self, wdgInfo, **kargs): """ if wdgInfo is None: return wdgInfo - elif isinstance(wdgInfo, Tkinter.Widget): + elif isinstance(wdgInfo, tkinter.Widget): # a widget; assume it's a Label widget of some kind return wdgInfo @@ -324,12 +325,12 @@ def _makeWdg(self, wdgInfo, **kargs): # set up the keyword arguments kargs.setdefault("helpText", self.helpText) kargs.setdefault("helpURL", self.helpURL) - if isinstance(wdgInfo, Tkinter.Variable): + if isinstance(wdgInfo, tkinter.Variable): kargs["textvariable"] = wdgInfo else: kargs["text"] = wdgInfo - return Label.StrLabel(self, **kargs) + return StrLabel(self, **kargs) def _setSize(self): """Compute or recompute bar size and associated values.""" @@ -493,7 +494,7 @@ def _updateTime(self, reschedule = True): if __name__ == "__main__": - import PythonTk + from . import PythonTk root = PythonTk.PythonTk() # horizontal and vertical progress bars diff --git a/python/RO/Wdg/PythonTk.py b/python/RO/Wdg/PythonTk.py index dec4a04..a9a0688 100755 --- a/python/RO/Wdg/PythonTk.py +++ b/python/RO/Wdg/PythonTk.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """ A wrapper around Tkinter.Tk that puts up a separate Python debugging window and then returns root. Optionally reads options @@ -26,11 +26,11 @@ """ __all__ = ['PythonTk'] -import Tkinter -import Bindings -import PythonWdg +import tkinter +from . import Bindings +from . import PythonWdg -class PythonTk (Tkinter.Tk): +class PythonTk (tkinter.Tk): """Creates a Tkinter application with standard menus and such""" def __init__(self, **kargs): """Creates a new application with some standard menus and such @@ -49,12 +49,12 @@ def __init__(self, **kargs): # first parse PythonTk-specific options # but do not try to apply them yet if they require Tk to be initialized optionfile = None - if kargs and kargs.has_key("optionfile"): + if kargs and "optionfile" in kargs: optionfile = kargs["optionfile"] del(kargs["optionfile"]) # basic initialization - Tkinter.Tk.__init__(self, **kargs) + tkinter.Tk.__init__(self, **kargs) # if the user supplied an option file, load it if optionfile: @@ -64,11 +64,11 @@ def __init__(self, **kargs): print("cannot read option file; error:", e) # create and display a Python script window - self.pyToplevel = Tkinter.Toplevel() + self.pyToplevel = tkinter.Toplevel() self.pyToplevel.geometry("+0+450") self.pyToplevel.title("Python") pyFrame = PythonWdg.PythonWdg(self.pyToplevel) - pyFrame.pack(expand=Tkinter.YES, fill=Tkinter.BOTH) + pyFrame.pack(expand=tkinter.YES, fill=tkinter.BOTH) # set up standard bindings Bindings.stdBindings(self) @@ -76,12 +76,12 @@ def __init__(self, **kargs): if __name__ == "__main__": root = PythonTk() - aText = Tkinter.Text(root, width=30, height=2) - aText.insert(Tkinter.END, "some text to manipulate") - aText.grid(row=0, column=0, sticky=Tkinter.NSEW) - anEntry = Tkinter.Entry(root) + aText = tkinter.Text(root, width=30, height=2) + aText.insert(tkinter.END, "some text to manipulate") + aText.grid(row=0, column=0, sticky=tkinter.NSEW) + anEntry = tkinter.Entry(root) anEntry.insert(0, "more text") - anEntry.grid(row=1, column=0, sticky=Tkinter.EW) + anEntry.grid(row=1, column=0, sticky=tkinter.EW) root.grid_rowconfigure(0, weight=1) root.grid_columnconfigure(0, weight=1) root.mainloop() diff --git a/python/RO/Wdg/PythonWdg.py b/python/RO/Wdg/PythonWdg.py index b252e18..6206266 100755 --- a/python/RO/Wdg/PythonWdg.py +++ b/python/RO/Wdg/PythonWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """An interactive Python session and simple script file editor/runner that may be used from Tkinter scripts. Before running a script,x=Tk() is replaced with x=Toplevel() and mainloop() is eliminated. Hence some Tk scripts may be safely run. Presumably there are limitations. I suspect that mucking about @@ -41,13 +41,13 @@ import os import re -import Tkinter -import tkFileDialog +import tkinter +import tkinter.filedialog import RO.CnvUtil import RO.OS -import Text +from . import Text -class PythonWdg(Tkinter.Frame): +class PythonWdg(tkinter.Frame): """A frame containing text window into which you may enter Python code. Inputs: @@ -60,7 +60,7 @@ def __init__ (self, filePath = None, helpURL = None, **kargs): - Tkinter.Frame.__init__(self, master, **kargs) + tkinter.Frame.__init__(self, master, **kargs) self.master=master self.filePath = filePath @@ -71,39 +71,39 @@ def __init__ (self, height = 10, helpURL = helpURL ) - self.inputWdg.grid(row=0, column=0, sticky=Tkinter.NSEW) + self.inputWdg.grid(row=0, column=0, sticky=tkinter.NSEW) self.inputWdg.bind("", self.run) - self.scroll = Tkinter.Scrollbar(self, command=self.inputWdg.yview) + self.scroll = tkinter.Scrollbar(self, command=self.inputWdg.yview) self.inputWdg.configure(yscrollcommand=self.scroll.set) - self.scroll.grid(row=0, column=1, sticky=Tkinter.NS) + self.scroll.grid(row=0, column=1, sticky=tkinter.NS) if self.filePath: fd = RO.OS.openUniv(self.filePath) try: - self.inputWdg.delete(1.0, Tkinter.END) + self.inputWdg.delete(1.0, tkinter.END) for line in fd.readlines(): - self.inputWdg.insert(Tkinter.END, line) + self.inputWdg.insert(tkinter.END, line) finally: fd.close() - self.cmdbar = Tkinter.Frame(self, borderwidth=2, relief=Tkinter.SUNKEN) - self.open = Tkinter.Button(self.cmdbar, text='Open...', command=self.open) - self.open.pack(side=Tkinter.LEFT, expand=0, padx=3, pady=3) - self.save = Tkinter.Button(self.cmdbar, text='Save...', command=self.save) - self.save.pack(side=Tkinter.LEFT, expand=0, padx=3, pady=3) - self.clr = Tkinter.Button(self.cmdbar, text='Clear', command=self.clr) - self.clr.pack(side=Tkinter.LEFT, expand=0, padx=3, pady=3) - self.run =Tkinter.Button(self.cmdbar, text='Run', command=self.run) - self.run.pack(side=Tkinter.RIGHT, expand=0, padx=3, pady=3) - self.cmdbar.grid(row=1, column=0, columnspan=2, sticky=Tkinter.EW) + self.cmdbar = tkinter.Frame(self, borderwidth=2, relief=tkinter.SUNKEN) + self.open = tkinter.Button(self.cmdbar, text='Open...', command=self.open) + self.open.pack(side=tkinter.LEFT, expand=0, padx=3, pady=3) + self.save = tkinter.Button(self.cmdbar, text='Save...', command=self.save) + self.save.pack(side=tkinter.LEFT, expand=0, padx=3, pady=3) + self.clr = tkinter.Button(self.cmdbar, text='Clear', command=self.clr) + self.clr.pack(side=tkinter.LEFT, expand=0, padx=3, pady=3) + self.run =tkinter.Button(self.cmdbar, text='Run', command=self.run) + self.run.pack(side=tkinter.RIGHT, expand=0, padx=3, pady=3) + self.cmdbar.grid(row=1, column=0, columnspan=2, sticky=tkinter.EW) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.inputWdg.focus_set() def run(self, evt=None, globs=None, locs=None): - script = self.inputWdg.get(1.0, Tkinter.END) + script = self.inputWdg.get(1.0, tkinter.END) # replace x = Tk() with x = Toplevel() tkPat = re.compile(r"^(.*=\s*)(:?ROStd)?Tk\(\)(.*)$", re.MULTILINE) @@ -118,26 +118,26 @@ def run(self, evt=None, globs=None, locs=None): globs = __main__.__dict__ if locs is None: locs = globs - exec script in globs, locs + exec(script, globs, locs) def open(self): - filePath = tkFileDialog.askopenfilename() + filePath = tkinter.filedialog.askopenfilename() if not filePath: return filePath = RO.CnvUtil.asStr(filePath) - top = Tkinter.Toplevel(self.master, ) + top = tkinter.Toplevel(self.master, ) top.title(os.path.basename(filePath)) frame = PythonWdg(top, filePath=filePath) - frame.pack(expand=Tkinter.YES, fill=Tkinter.BOTH) + frame.pack(expand=tkinter.YES, fill=tkinter.BOTH) def save(self, forPrt=None): - script = self.inputWdg.get(1.0, Tkinter.END) + script = self.inputWdg.get(1.0, tkinter.END) if not script: return if forPrt: filePath = 'prt.tmp' else: - filePath = tkFileDialog.asksaveasfilename(initialfile=self.filePath) + filePath = tkinter.filedialog.asksaveasfilename(initialfile=self.filePath) if not filePath: return self.filePath = RO.CnvUtil.asStr(filePath) @@ -152,10 +152,10 @@ def clr(self): if __name__ == '__main__': - root = Tkinter.Tk() + root = tkinter.Tk() testFrame = PythonWdg(root) root.geometry("+0+450") - testFrame.pack(expand=Tkinter.YES, fill=Tkinter.BOTH) + testFrame.pack(expand=tkinter.YES, fill=tkinter.BOTH) root.mainloop() diff --git a/python/RO/Wdg/RadiobuttonSet.py b/python/RO/Wdg/RadiobuttonSet.py index 9b83479..8e721df 100755 --- a/python/RO/Wdg/RadiobuttonSet.py +++ b/python/RO/Wdg/RadiobuttonSet.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Creates a set of Tkinter Radiobuttons that have help, default handling and other niceties. The set can be used in an RO.Wdg input container (and it implements just enough of the Tkinter standard widget interface @@ -45,14 +45,14 @@ """ __all__ = ['RadiobuttonSet'] -import Tkinter +import tkinter import RO.AddCallback import RO.Alg import RO.SeqUtil import RO.StringUtil import RO.TkUtil -import Button -from IsCurrentMixin import AutoIsCurrentMixin, IsCurrentActiveMixin +from . import Button +from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentActiveMixin class RadiobuttonSet (RO.AddCallback.TkVarMixin, AutoIsCurrentMixin, IsCurrentActiveMixin): @@ -145,7 +145,7 @@ def __init__(self, self._valueList = valueList if var is None: - var = Tkinter.StringVar() + var = tkinter.StringVar() self._var = var self._defIfBlank = defIfBlank @@ -311,11 +311,11 @@ def winfo_ismapped(self): return self.wdgSet[0].winfo_ismapped() if __name__ == "__main__": - import PythonTk - from StatusBar import StatusBar + from . import PythonTk + from .StatusBar import StatusBar root = PythonTk.PythonTk() - rbFrame1 = Tkinter.Frame() + rbFrame1 = tkinter.Frame() rbs1 = RadiobuttonSet( master = rbFrame1, textList = ("Foo", "Bar", "Baz"), @@ -330,7 +330,7 @@ def winfo_ismapped(self): wdg.pack(side="left") rbFrame1.pack(side="top") - rbFrame2 = Tkinter.Frame() + rbFrame2 = tkinter.Frame() rbs2 = RadiobuttonSet( master = rbFrame2, textList = ("MmmmmNnnnn A", "MmmmmNnnnn B", "MmmmmNnnnn C"), @@ -344,7 +344,7 @@ def winfo_ismapped(self): wdg.pack(side="left") rbFrame2.pack(side="top") - rbFrame3 = Tkinter.Frame() + rbFrame3 = tkinter.Frame() rbs3 = RadiobuttonSet( master = rbFrame3, textList = ("MmmmmNnnnn A", "MmmmmNnnnn B", "MmmmmNnnnn C"), @@ -364,7 +364,7 @@ def doPrint(): print("2 value = %r; default = %r" % (rbs2.getString(), rbs2.getDefault())) print("3 value = %r; default = %r" % (rbs3.getString(), rbs3.getDefault())) - enableVar = Tkinter.IntVar() + enableVar = tkinter.IntVar() enableVar.set(True) def setEnable(): rbs1.setEnable(enableVar.get()) @@ -373,9 +373,9 @@ def setEnable(): StatusBar(root).pack(side="top", fill="x", expand=True) - cmdFrame = Tkinter.Frame() - Tkinter.Button(cmdFrame, text="Print Value", command=doPrint).pack(side="left") - Tkinter.Checkbutton(cmdFrame, text="Enable", command=setEnable, variable=enableVar).pack(side="left") + cmdFrame = tkinter.Frame() + tkinter.Button(cmdFrame, text="Print Value", command=doPrint).pack(side="left") + tkinter.Checkbutton(cmdFrame, text="Enable", command=setEnable, variable=enableVar).pack(side="left") cmdFrame.pack(side="top") root.mainloop() diff --git a/python/RO/Wdg/ResizableRect.py b/python/RO/Wdg/ResizableRect.py index 9bae8c1..d8c9f23 100755 --- a/python/RO/Wdg/ResizableRect.py +++ b/python/RO/Wdg/ResizableRect.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A rectangle that the user can resize or drag around. Tkinter implementation of Keith Vetter's "PrintBox" with some refinements. @@ -29,7 +29,7 @@ """ __all__ = ["ResizableRect"] -import Tkinter +import tkinter import RO.SeqUtil import RO.AddCallback from RO.Alg import GenericCallback @@ -129,7 +129,7 @@ def __init__(self, tags = tags, ) - for regionName, cursor in self.cursorDict.iteritems(): + for regionName, cursor in self.cursorDict.items(): regionID = self.idDict[regionName] self.cnv.tag_bind(regionID, "", GenericCallback(self._setCursor, cursor)) self.cnv.tag_bind(regionID, "", self._restoreDefaultCursor) @@ -329,10 +329,10 @@ def _setRegionCoords(self, regionName, x0, y0, x1, y1): if __name__ == "__main__": - import PythonTk + from . import PythonTk root = PythonTk.PythonTk() - cnvFrame = Tkinter.Frame(root, borderwidth=2, relief="solid") - cnv = Tkinter.Canvas( + cnvFrame = tkinter.Frame(root, borderwidth=2, relief="solid") + cnv = tkinter.Canvas( cnvFrame, selectborderwidth = 0, highlightthickness = 0, diff --git a/python/RO/Wdg/ScriptWdg.py b/python/RO/Wdg/ScriptWdg.py index 7ceedbd..2fdf078 100755 --- a/python/RO/Wdg/ScriptWdg.py +++ b/python/RO/Wdg/ScriptWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division + """Widgets to load and run RO.ScriptRunner scripts. ScriptModuleWdg loads a script from a specified module. @@ -34,12 +34,13 @@ __all__ = ['BasicScriptWdg', 'ScriptModuleWdg', 'ScriptFileWdg'] import os.path -import Tkinter +import tkinter import RO.Constants import RO.AddCallback import RO.ScriptRunner -import Button -import StatusBar +from . import Button +from . import StatusBar +import importlib # compute _StateSevDict which contains # state:severity for non-normal severities @@ -231,7 +232,7 @@ def _doCallbacks(self): self._basicDoCallbacks(self.scriptRunner) -class _BaseUserScriptWdg(Tkinter.Frame, BasicScriptWdg): +class _BaseUserScriptWdg(tkinter.Frame, BasicScriptWdg): """Base class widget that runs a function via a ScriptRunner. Subclasses must override _getScriptFuncs. @@ -248,7 +249,7 @@ def __init__(self, name, dispatcher = None, **kargs): - Tkinter.Frame.__init__(self, master, **kargs) + tkinter.Frame.__init__(self, master, **kargs) srArgs = self._getScriptFuncs(isFirst=True) @@ -256,7 +257,7 @@ def __init__(self, row = 0 - self.scriptFrame = Tkinter.Frame(self) + self.scriptFrame = tkinter.Frame(self) self.scriptFrame.grid(row=row, column=0, sticky="news") self.scriptFrameRow = row self.rowconfigure(row, weight=1) @@ -281,7 +282,7 @@ def __init__(self, cmdStatusBar.grid(row=row, column=0, sticky="ew") row += 1 - buttonFrame = Tkinter.Frame(self) + buttonFrame = tkinter.Frame(self) startButton = Button.Button( master = buttonFrame, text = "Start", @@ -338,7 +339,7 @@ def reload(self): self.scriptFrame.destroy() self.scriptRunner = None - self.scriptFrame = Tkinter.Frame(self) + self.scriptFrame = tkinter.Frame(self) self.scriptFrame.grid(row=self.scriptFrameRow, column=0, sticky="news") self._makeScriptRunner(self.scriptFrame, **srArgs) self.scriptStatusBar.setMsg("Reloaded", RO.Constants.sevNormal) @@ -429,7 +430,7 @@ def _getScriptFuncs(self, isFirst): it may also contain HelpURL. """ if not isFirst: - reload(self.module) + importlib.reload(self.module) scriptClass = getattr(self.module, "ScriptClass", None) if scriptClass: @@ -517,7 +518,7 @@ def _getScriptFuncs(self, isFirst=None): """ # print "_getScriptFuncs(%s)" % isFirst scriptLocals = {"__file__": self.fullPath} - execfile(self.filename, scriptLocals) + exec(compile(open(self.filename, "rb").read(), self.filename, 'exec'), scriptLocals) retDict = {} helpURL = scriptLocals.get("HelpURL") @@ -540,8 +541,8 @@ def _getScriptFuncs(self, isFirst=None): if __name__ == "__main__": import RO.KeyDispatcher - import PythonTk - import TestScriptWdg + from . import PythonTk + from . import TestScriptWdg root = PythonTk.PythonTk() root.title('Script 1 (root)') @@ -558,7 +559,7 @@ def _getScriptFuncs(self, isFirst=None): testTL1.resizable(False, False) - testTL2 = Tkinter.Toplevel() + testTL2 = tkinter.Toplevel() sr2 = ScriptFileWdg( master = testTL2, filename = 'TestScriptWdg.py', diff --git a/python/RO/Wdg/ScrolledWdg.py b/python/RO/Wdg/ScrolledWdg.py index a4a68c8..6f80aea 100755 --- a/python/RO/Wdg/ScrolledWdg.py +++ b/python/RO/Wdg/ScrolledWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A container that scrolls a widget. History: @@ -12,9 +12,9 @@ """ __all__ = ['ScrolledWdg'] -import Tkinter +import tkinter -class ScrolledWdg(Tkinter.Frame): +class ScrolledWdg(tkinter.Frame): """Scroll a widget such as a frame. Due to quirks in tk or Tkinter this requires three steps: @@ -39,7 +39,7 @@ def __init__ (self, height = 0, **kargs): - Tkinter.Frame.__init__(self, master, **kargs) + tkinter.Frame.__init__(self, master, **kargs) self._hscroll = bool(hscroll) self._vscroll = bool(vscroll) @@ -48,12 +48,12 @@ def __init__ (self, self._vincr = None # create the canvas - self._cnv = Tkinter.Canvas(self, height=height, highlightthickness=0, selectborderwidth=0) + self._cnv = tkinter.Canvas(self, height=height, highlightthickness=0, selectborderwidth=0) self._cnv.grid(row=0, column=0, sticky="nsew") # create the scrollbars and connect them up if hscroll: - hsb = Tkinter.Scrollbar(self, orient="horizontal", command=self._cnv.xview) + hsb = tkinter.Scrollbar(self, orient="horizontal", command=self._cnv.xview) self._cnv.configure(xscrollcommand = hsb.set) hsb.grid(row=1, column=0, sticky="ew") else: @@ -61,7 +61,7 @@ def __init__ (self, self._hscrollbar = hsb if vscroll: - vsb = Tkinter.Scrollbar(self, orient="vertical", command=self._cnv.yview) + vsb = tkinter.Scrollbar(self, orient="vertical", command=self._cnv.yview) self._cnv.configure(yscrollcommand = vsb.set) vsb.grid(row=0, column=1, sticky="ns") else: @@ -162,7 +162,7 @@ def _configVIncr(self, evt=None): if __name__ == '__main__': - import PythonTk + from . import PythonTk root = PythonTk.PythonTk() root.resizable(False, True) @@ -177,11 +177,11 @@ def _configVIncr(self, evt=None): ) labelDict = {} - testFrame = Tkinter.Frame(scFrame.getWdgParent()) + testFrame = tkinter.Frame(scFrame.getWdgParent()) for row in range(NRows): for col in range(NCol): ind = (row, col) - label = Tkinter.Label(testFrame, text="%s" % (ind,)) + label = tkinter.Label(testFrame, text="%s" % (ind,)) label.grid(row = row, column=col) labelDict[ind] = label diff --git a/python/RO/Wdg/SeverityMixin.py b/python/RO/Wdg/SeverityMixin.py index 9f489f0..0554b40 100755 --- a/python/RO/Wdg/SeverityMixin.py +++ b/python/RO/Wdg/SeverityMixin.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Adjust widget foreground color as a function of severity, meaning one of the RO.Constant.sev constants: sevNormal @@ -22,7 +22,7 @@ __all__ = ["SeverityMixin", "SeverityActiveMixin", "SeveritySelectMixin"] import RO.Constants -import WdgPrefs +from . import WdgPrefs class SeverityMixin(object): """Mixin class that adds a severity attribute @@ -70,7 +70,7 @@ def setSeverity(self, severity): # set severityPrefDict and subscribe to prefs; # then test severity again self._severityPrefDict = WdgPrefs.getSevPrefDict() - for iterseverity, pref in self._severityPrefDict.iteritems(): + for iterseverity, pref in self._severityPrefDict.items(): if iterseverity == RO.Constants.sevNormal: # normal foreground color is already automatically updated continue @@ -111,33 +111,33 @@ def _updateSeverityColor(self, *args): if __name__ == "__main__": - import Tkinter - import PythonTk + import tkinter + from . import PythonTk root = PythonTk.PythonTk() - class ColorButton(Tkinter.Button, SeverityActiveMixin): + class ColorButton(tkinter.Button, SeverityActiveMixin): def __init__(self, *args, **kargs): - Tkinter.Button.__init__(self, *args, **kargs) + tkinter.Button.__init__(self, *args, **kargs) SeverityActiveMixin.__init__(self) - class ColorCheckbutton(Tkinter.Checkbutton, SeverityActiveMixin): + class ColorCheckbutton(tkinter.Checkbutton, SeverityActiveMixin): def __init__(self, *args, **kargs): - Tkinter.Checkbutton.__init__(self, *args, **kargs) + tkinter.Checkbutton.__init__(self, *args, **kargs) SeverityActiveMixin.__init__(self) - class ColorEntry(Tkinter.Entry, SeveritySelectMixin): + class ColorEntry(tkinter.Entry, SeveritySelectMixin): def __init__(self, *args, **kargs): - Tkinter.Entry.__init__(self, *args, **kargs) + tkinter.Entry.__init__(self, *args, **kargs) SeveritySelectMixin.__init__(self) - class ColorLabel(Tkinter.Label, SeverityMixin): + class ColorLabel(tkinter.Label, SeverityMixin): def __init__(self, *args, **kargs): - Tkinter.Label.__init__(self, *args, **kargs) + tkinter.Label.__init__(self, *args, **kargs) SeverityMixin.__init__(self) - class ColorOptionMenu(Tkinter.OptionMenu, SeverityActiveMixin): + class ColorOptionMenu(tkinter.OptionMenu, SeverityActiveMixin): def __init__(self, *args, **kargs): - Tkinter.OptionMenu.__init__(self, *args, **kargs) + tkinter.OptionMenu.__init__(self, *args, **kargs) SeverityActiveMixin.__init__(self) def setSeverity(*args): @@ -150,11 +150,11 @@ def setSeverity(*args): for wdg in wdgSet: wdg.setSeverity(severity) - severityVar = Tkinter.StringVar() + severityVar = tkinter.StringVar() severityVar.set("Normal") severityVar.trace_variable("w", setSeverity) - entryVar = Tkinter.StringVar() + entryVar = tkinter.StringVar() entryVar.set("Entry") wdgSet = ( ColorOptionMenu(root, severityVar, "Normal", "Warning", "Error", @@ -177,6 +177,6 @@ def setSeverity(*args): ), ) for wdg in wdgSet: - wdg.pack(fill=Tkinter.X) + wdg.pack(fill=tkinter.X) root.mainloop() diff --git a/python/RO/Wdg/Sound.py b/python/RO/Wdg/Sound.py index f75d45b..8adeaca 100644 --- a/python/RO/Wdg/Sound.py +++ b/python/RO/Wdg/Sound.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """Simple sound players. All sound players are based on Tkinter and some will use @@ -18,7 +18,7 @@ import os import sys -import Tkinter +import tkinter import RO.StringUtil try: import pygame.mixer @@ -43,7 +43,7 @@ def bell(num=1, delay=100): """ global _TkWdg if not _TkWdg: - _TkWdg = Tkinter.Frame() + _TkWdg = tkinter.Frame() _TkWdg.bell() if num > 1: _TkWdg.after(int(delay), bell, int(num)-1, int(delay)) diff --git a/python/RO/Wdg/StateTracker.py b/python/RO/Wdg/StateTracker.py index fb47221..c202f4a 100644 --- a/python/RO/Wdg/StateTracker.py +++ b/python/RO/Wdg/StateTracker.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function + """Track the state of a collection of widgets Intended for use with RO.Wdg.Toplevel in saving and restoring state @@ -98,7 +98,7 @@ def trackItem(self, name, getFunc=None, setFunc=None): def getState(self): """Get the state of all items as a dictionary of name: value """ - stateDict = dict((name, item.getFunc()) for name, item in self._itemDict.iteritems()) + stateDict = dict((name, item.getFunc()) for name, item in self._itemDict.items()) return stateDict def setState(self, stateDict): @@ -107,7 +107,7 @@ def setState(self, stateDict): Unknown and missing keys are ignored. If there is an error setting the state of an item a message is printed using logFunc. """ - for name, val in stateDict.iteritems(): + for name, val in stateDict.items(): item = self._itemDict.get(name) if item is not None: try: diff --git a/python/RO/Wdg/StatusBar.py b/python/RO/Wdg/StatusBar.py index 34c0d6a..36851b4 100644 --- a/python/RO/Wdg/StatusBar.py +++ b/python/RO/Wdg/StatusBar.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """Displays hot help, error messages and monitors the progress of commands of the class RO.KeyVariable.cmdVar @@ -65,14 +65,14 @@ __all__ = ['StatusBar'] import sys -import Tkinter +import tkinter import RO.Alg import RO.Constants import RO.KeyVariable import RO.Prefs.PrefVar from RO.TkUtil import Timer -import Sound -import Entry +from . import Sound +from . import Entry def _getSound(playCmdSounds, prefs, prefName): noPlay = Sound.NoPlay() @@ -88,7 +88,7 @@ def _getSound(playCmdSounds, prefs, prefName): return soundPref -class StatusBar(Tkinter.Frame): +class StatusBar(tkinter.Frame): """Display hot help and error messages and execute commands and display their progress. @@ -124,7 +124,7 @@ def __init__(self, self.cmdFailedSound = _getSound(playCmdSounds, prefs, "Command Failed") self.tempIDGen = RO.Alg.IDGen(1, sys.maxsize) - Tkinter.Frame.__init__(self, master, **kargs) + tkinter.Frame.__init__(self, master, **kargs) self.displayWdg = Entry.StrEntry( master = self, readOnly = True, diff --git a/python/RO/Wdg/StatusConfigGridder.py b/python/RO/Wdg/StatusConfigGridder.py index 77347ed..92add93 100644 --- a/python/RO/Wdg/StatusConfigGridder.py +++ b/python/RO/Wdg/StatusConfigGridder.py @@ -1,4 +1,4 @@ -from __future__ import division, print_function + """Tools for gridding widgets History: @@ -23,14 +23,15 @@ 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. 2015-11-05 ROwen Changed ==/!= True/False to is/is not True/False to modernize the code. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['StatusConfigGridder'] -import Gridder +from .Gridder import Gridder, _BaseGridSet ConfigCat = "config" -class StatusConfigGridder(Gridder.Gridder): +class StatusConfigGridder(Gridder): ConfigCat = ConfigCat def __init__(self, master, @@ -53,7 +54,7 @@ def __init__(self, and your code will still work if you add status widgets that use more columns. """ - Gridder.Gridder.__init__(self, + Gridder.__init__(self, master = master, row = row, col = col, @@ -123,7 +124,7 @@ def gridWdg(self, return gs -class _StatusConfigGridSet(Gridder._BaseGridSet): +class _StatusConfigGridSet(_BaseGridSet): def __init__ (self, master, label = None, @@ -187,7 +188,7 @@ def __init__ (self, if numStatusCols is not None: numStatusCols = int(numStatusCols) - Gridder._BaseGridSet.__init__(self, + _BaseGridSet.__init__(self, master, row, col, diff --git a/python/RO/Wdg/StripChartWdg.py b/python/RO/Wdg/StripChartWdg.py index e0116c6..db1f701 100755 --- a/python/RO/Wdg/StripChartWdg.py +++ b/python/RO/Wdg/StripChartWdg.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """A widget to display changing values in real time as a strip chart Known issues: @@ -81,13 +81,13 @@ import time import numpy -import Tkinter +import tkinter import matplotlib import matplotlib.dates from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from RO.TkUtil import Timer -class StripChartWdg(Tkinter.Frame): +class StripChartWdg(tkinter.Frame): """A widget to changing values in real time as a strip chart Usage Hints: @@ -141,7 +141,7 @@ def __init__(self, - cnvTimeFunc: a function that takes a POSIX timestamp (e.g. time.time()) and returns matplotlib days; typically an instance of TimeConverter; defaults to TimeConverter(useUTC=False) """ - Tkinter.Frame.__init__(self, master) + tkinter.Frame.__init__(self, master) self._timeRange = timeRange self._isVisible = self.winfo_ismapped() @@ -484,7 +484,7 @@ def __call__(self, unixSec): if __name__ == "__main__": import RO.Alg - root = Tkinter.Tk() + root = tkinter.Tk() stripChart = StripChartWdg( master = root, timeRange = 60, @@ -507,7 +507,7 @@ def __call__(self, unixSec): stripChart.subplotArr[1].legend(loc=3) # stop major time ticks from jumping around as time advances: - stripChart.xaxis.set_major_locator(matplotlib.dates.SecondLocator(bysecond=range(0,60,10))) + stripChart.xaxis.set_major_locator(matplotlib.dates.SecondLocator(bysecond=list(range(0,60,10)))) varDict = { countsLine: RO.Alg.ConstrainedGaussianRandomWalk(1, 0.2, 0, 2.8), @@ -530,10 +530,10 @@ def addRandomValues(line, interval=0.1): def deleteSatConstLine(): stripChart.removeLine(satConstLine) - Tkinter.Button(root, text="Delete Saturated Counts", command=deleteSatConstLine).pack() + tkinter.Button(root, text="Delete Saturated Counts", command=deleteSatConstLine).pack() def deleteWalk1(): stripChart.removeLine(walk1Line) - Tkinter.Button(root, text="Delete Walk 1", command=deleteWalk1).pack() + tkinter.Button(root, text="Delete Walk 1", command=deleteWalk1).pack() root.mainloop() diff --git a/python/RO/Wdg/Text.py b/python/RO/Wdg/Text.py index 15b4f18..b86c22e 100755 --- a/python/RO/Wdg/Text.py +++ b/python/RO/Wdg/Text.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Variant of Tkinter.Text that includes a few extra features, including: - read-only support (can still copy data) - contextual menu with cut/copy/paste and URL-based help @@ -12,18 +12,21 @@ 2005-01-05 ROwen Changed _statePrefDict to _sevPrefDict. 2006-10-24 ROwen Added search method with elide argument because Tkinter's Text.search doesn't yet support elide. +2020-02-10 DGatlin Modified imports for Python 3 """ __all__ = ['Text'] -import Tkinter +import tkinter + import RO.CnvUtil -import RO.StringUtil import RO.MathUtil -import Bindings -import CtxMenu -import WdgPrefs +import RO.StringUtil +from . import Bindings +from . import WdgPrefs +from .CtxMenu import CtxMenuMixin + -class Text (Tkinter.Text, CtxMenu.CtxMenuMixin): +class Text (tkinter.Text, CtxMenuMixin): """Text widget Inputs: @@ -52,9 +55,9 @@ def __init__ (self, self._readOnly = readOnly self._isCurrent = bool(isCurrent) - Tkinter.Text.__init__(self, master, **kargs) + tkinter.Text.__init__(self, master, **kargs) - CtxMenu.CtxMenuMixin.__init__(self, helpURL = helpURL) + CtxMenuMixin.__init__(self, helpURL = helpURL) self._prefDict = WdgPrefs.getWdgPrefDict() self._sevPrefDict = WdgPrefs.getSevPrefDict() @@ -70,7 +73,7 @@ def __init__ (self, self._updateBGColor() if useStateTags: - for severity, pref in self._sevPrefDict.iteritems(): + for severity, pref in self._sevPrefDict.items(): if severity == RO.Constants.sevNormal: # normal foreground color is already automatically updated continue @@ -91,7 +94,7 @@ def ctxConfigMenu(self, menu): dataPresent = (self.get("1.0", "3.0") not in ("\n", "")) try: selPresent = (self.get("sel.first", "sel.last") != "") - except Tkinter.TclError: + except tkinter.TclError: selPresent = False if self._readOnly or not self.getEnable(): menu.add_command( @@ -103,7 +106,7 @@ def ctxConfigMenu(self, menu): try: clipPresent = (self.selection_get(selection="CLIPBOARD") != "") - except Tkinter.TclError: + except tkinter.TclError: clipPresent = False menu.add_command( @@ -157,7 +160,7 @@ def getEnable(self): """Returns False if the state is disabled, True otherwise (state is normal or active) """ - return self["state"] != Tkinter.DISABLED + return self["state"] != tkinter.DISABLED def getIsCurrent(self): """Return True if value is current, False otherwise. @@ -227,7 +230,7 @@ def _updateStateTagColors(self, *args): if __name__ == "__main__": from RO.Wdg.PythonTk import PythonTk - import StatusBar + from . import StatusBar root = PythonTk() text1 = Text(root, "text widget", height=5, width=20) diff --git a/python/RO/Wdg/Toplevel.py b/python/RO/Wdg/Toplevel.py index 7156a0e..b25ebf2 100755 --- a/python/RO/Wdg/Toplevel.py +++ b/python/RO/Wdg/Toplevel.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """RO.Wdg.Toplevel wdigets are windows with some enhanced functionality, including: - Remembers last geometry if closed or iconified - Can record geometry, visibility and widget state in a file @@ -69,7 +69,7 @@ import os.path import sys import traceback -import Tkinter +import tkinter import RO.CnvUtil import RO.OS import RO.SeqUtil @@ -81,7 +81,7 @@ tl_CloseWithdraws = 1 tl_CloseDisabled = 2 -class Toplevel(Tkinter.Toplevel): +class Toplevel(tkinter.Toplevel): def __init__(self, master=None, geometry="", @@ -123,7 +123,7 @@ def __init__(self, An alternative solution is to create a variant of GenericCallback that is specialized for Tk widgets or at least puts unnamed dynamic arguments first. """ - Tkinter.Toplevel.__init__(self, master) + tkinter.Toplevel.__init__(self, master) self.wm_withdraw() resizable = RO.SeqUtil.oneOrNAsList(resizable, 2, valDescr = "resizable") @@ -378,7 +378,7 @@ def __init__(self, self.defGeomDict = {} self.defVisDict = {} if defGeomVisDict: - for name, geomVis in defGeomVisDict.iteritems(): + for name, geomVis in defGeomVisDict.items(): geom, vis = geomVis if geom: self.defGeomDict[name] = geom @@ -498,7 +498,7 @@ def getNames(self, prefix=""): The names are in alphabetical order, ignoring case. The list includes toplevels that have been destroyed. """ - nameList = self.tlDict.keys() + nameList = list(self.tlDict.keys()) nameList.sort(key=lambda s: s.lower()) if not prefix: return nameList @@ -509,7 +509,7 @@ def getNamesInGeomFile(self, prefix=""): (or all names if prefix omitted). The names are in alphabetical order (though someday that may change to the order in which windows are added). """ - nameList = sorted(self.fileGeomDict.iterkeys()) + nameList = sorted(self.fileGeomDict.keys()) if not prefix: return nameList return [name for name in nameList if name.startswith(prefix)] @@ -679,7 +679,7 @@ def writeGeomVisFile(self, fileName=None, readFirst = True): resizable=(False, True), geometry = "40x40+150+50" ) - l = Tkinter.Label(testWin, text="This is a label") + l = tkinter.Label(testWin, text="This is a label") l.pack() def printInfo(): @@ -689,7 +689,7 @@ def printInfo(): print("req width, req height = %r, %r" % (testWin.winfo_reqwidth(), testWin.winfo_reqheight())) print("") - b = Tkinter.Button(root, text="Window Info", command=printInfo) + b = tkinter.Button(root, text="Window Info", command=printInfo) b.pack() root.mainloop() diff --git a/python/RO/Wdg/WdgPrefs.py b/python/RO/Wdg/WdgPrefs.py index fa56ba2..53ac999 100755 --- a/python/RO/Wdg/WdgPrefs.py +++ b/python/RO/Wdg/WdgPrefs.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Preferences for the RO.Wdg package. Note: call @@ -22,7 +22,7 @@ """ __all__ = [] -import Tkinter +import tkinter import RO.Constants import RO.TkUtil import RO.Prefs.PrefVar @@ -118,7 +118,7 @@ class WdgPrefs(object): """ def __init__(self, prefSet = None): # use a widget that has the activebackground attribute - self._tkWdg = Tkinter.Button() + self._tkWdg = tkinter.Button() self.prefDict = {} self._activeBackScale = 1.0 @@ -151,7 +151,7 @@ def getColorPref(prefName, defColor): sevNamePrefNameDict = {"normal": "foreground"} self.sevPrefDict = RO.Alg.OrderedDict( (sev, self.prefDict["%s Color" % sevNamePrefNameDict.get(sevName, sevName).title()]) - for sev, sevName in RO.Constants.SevNameDict.iteritems()) + for sev, sevName in RO.Constants.SevNameDict.items()) # add activebackground color (could do the same for activeforeground, # but it doesn't seem to be used). @@ -229,7 +229,7 @@ def _updActBadBackPref(self, badBackColor, *args): print() print("sevPrefDict:") sevPrefDict = getSevPrefDict() - severities = sevPrefDict.keys() + severities = list(sevPrefDict.keys()) severities.sort() for severity in severities: print(" %s: %r" % (severity, sevPrefDict[severity].getValue())) diff --git a/python/RO/Wdg/__init__.py b/python/RO/Wdg/__init__.py index da7b67e..61a7ae7 100644 --- a/python/RO/Wdg/__init__.py +++ b/python/RO/Wdg/__init__.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + """Various enhancements to Tkinter """ from .BalloonHelp import * from .Bindings import * diff --git a/python/RO/Wdg/sampleDroplet.py b/python/RO/Wdg/sampleDroplet.py index c28e507..b857116 100755 --- a/python/RO/Wdg/sampleDroplet.py +++ b/python/RO/Wdg/sampleDroplet.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Run a script as a droplet (an application onto which you drop file) with a log window On Mac OS X additional files may be dropped on the application icon once the first batch is processed. diff --git a/python/RO/__init__.py b/python/RO/__init__.py index a26718b..43f216f 100644 --- a/python/RO/__init__.py +++ b/python/RO/__init__.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import + """Various utilities written, adapted or borrowed by Russell Owen See ../README.txt and ../docs of source code diff --git a/python/RO/procFiles.py b/python/RO/procFiles.py index 0f0741d..08bcb31 100755 --- a/python/RO/procFiles.py +++ b/python/RO/procFiles.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """procFiles calls a user-supplied function "func" to process a set of files one by one. The processed data is typically concatenated into one output file, but this behavior is controlled by outPath. @@ -161,7 +161,7 @@ def procFiles ( ): # make sure func is callable if not callable(func): - raise RuntimeError, "supplied function is not callable" + raise RuntimeError("supplied function is not callable") # handle case of inPathList being a single string inPathList = RO.SeqUtil.asSequence(inPathList) @@ -212,7 +212,7 @@ def procFiles ( sys.stdout = file(outPath, 'w') except ImportError: # unknown platform; use standard prompt - outFile = raw_input( + outFile = input( "output file relative to %r [stdout]: " % outDir) # generate outPath, and if it's a file, open it and redirect stdout diff --git a/releaseNewVersion.py b/releaseNewVersion.py index 053f526..35512d8 100755 --- a/releaseNewVersion.py +++ b/releaseNewVersion.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """A script to release a new version of RO Python Package and upload it to PyPI To use: @@ -18,7 +18,7 @@ sys.path.insert(0, PkgDir) import Version queryStr = "Version from RO.Version = %s; is this OK? (y/[n]) " % (Version.__version__,) -versOK = raw_input(queryStr) +versOK = input(queryStr) if not versOK.lower() == "y": sys.exit(0) @@ -39,7 +39,7 @@ subprocess.call(["git", "status"]) -versOK = raw_input("Is the git repository up to date? (y/[n]) ") +versOK = input("Is the git repository up to date? (y/[n]) ") if not versOK.lower() == "y": sys.exit(0) diff --git a/setup.py b/setup.py index 22fc9c0..1ac1f2f 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Install the RO package. Requires setuptools. To use: diff --git a/tests/Comm/testTkSocket.py b/tests/Comm/testTkSocket.py index ffe8734..06a070f 100644 --- a/tests/Comm/testTkSocket.py +++ b/tests/Comm/testTkSocket.py @@ -1,12 +1,12 @@ # -*- test-case-name: tests.Comm.testTkSocket -*- -from __future__ import absolute_import, division, print_function -import Tkinter + +import tkinter from twisted.trial import unittest from twisted.internet.defer import Deferred import twisted.internet.tksupport from RO.Comm.TkSocket import TCPSocket, TCPServer -root = Tkinter.Tk() +root = tkinter.Tk() Port = 2210 diff --git a/tests/Comm/testTwistedSocket.py b/tests/Comm/testTwistedSocket.py index 7226698..0913c67 100644 --- a/tests/Comm/testTwistedSocket.py +++ b/tests/Comm/testTwistedSocket.py @@ -1,5 +1,5 @@ # -*- test-case-name: tests.Comm.testTwistedSocket -*- -from __future__ import absolute_import, division, print_function + from twisted.trial import unittest from twisted.internet.defer import Deferred from RO.Comm.TwistedSocket import TCPSocket, TCPServer diff --git a/tools/cheol.py b/tools/cheol.py index 42fad7b..a4a9813 100644 --- a/tools/cheol.py +++ b/tools/cheol.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """ cheol: change end of line character Copyright (C) 2000-2001 Gordon Worley diff --git a/tools/eventlogger.py b/tools/eventlogger.py index 37386e5..01935bd 100755 --- a/tools/eventlogger.py +++ b/tools/eventlogger.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Event logger to allow testing events. The events are all generated by the entry widget and its title widget. @@ -8,12 +8,12 @@ """ import sys import os -import Tkinter +import tkinter RORoot = os.path.join(os.path.dirname(os.path.abspath(os.path.dirname(__file__))), "python") sys.path.append(RORoot) import RO.Wdg -class EventLogger(Tkinter.Frame): +class EventLogger(tkinter.Frame): EventDict = { '2': 'KeyPress', '3': 'KeyRelease', @@ -40,16 +40,16 @@ class EventLogger(Tkinter.Frame): } def __init__(self, master): - Tkinter.Frame.__init__(self, master) + tkinter.Frame.__init__(self, master) # dict of event type: event name self.eventInd = 0 - self.userLabel = Tkinter.Label(self, text="Type here:") - self.userEntry = Tkinter.Entry(self, highlightthickness=2) + self.userLabel = tkinter.Label(self, text="Type here:") + self.userEntry = tkinter.Entry(self, highlightthickness=2) self.logWdg = RO.Wdg.LogWdg(self) - for eventName in self.EventDict.values(): + for eventName in list(self.EventDict.values()): self.userLabel.bind('<%s>' % eventName, self.reportEvent) self.userEntry.bind('<%s>' % eventName, self.reportEvent) @@ -102,7 +102,7 @@ def reportEvent(self, evt): if __name__ == "__main__": - root = Tkinter.Tk() + root = tkinter.Tk() root.geometry("800x500") root.wm_title("Event Logger") evtLogger = EventLogger(root) diff --git a/tools/fitsinfo.py b/tools/fitsinfo.py index 062596a..6ac7332 100755 --- a/tools/fitsinfo.py +++ b/tools/fitsinfo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + import argparse import numpy import pyfits @@ -15,14 +15,14 @@ def fitsInfo(filePath, hduList=None, showHeader=True, showStats=True): fitsFile = pyfits.open(filePath) print("*** FITS file %r:" % (filePath,)) if hduList is None: - hduList = range(len(fitsFile)) + hduList = list(range(len(fitsFile))) for hduInd in hduList: print("*** HDU %s header:" % (hduInd,)) fitsExt = fitsFile[hduInd] hdr = fitsExt.header if showHeader: - for key, value in hdr.iteritems(): + for key, value in hdr.items(): if key.upper() == "COMMENT": print("%s %s" % (key, value)) elif isinstance(value, bool): diff --git a/tools/keysym.py b/tools/keysym.py index b8e7ec8..d6788a8 100644 --- a/tools/keysym.py +++ b/tools/keysym.py @@ -1,15 +1,15 @@ #!/usr/local/bin/Python -from __future__ import absolute_import, division, print_function + """Displays the keysym for each KeyPress event as you type.""" -import Tkinter +import tkinter -root = Tkinter.Tk() +root = tkinter.Tk() root.title("Keysym Logger") def reportEvent(event): print('keysym=%r, keysym_num=%s' % (event.keysym, event.keysym_num)) -text = Tkinter.Text(root, width=20, height=5, highlightthickness=2) +text = tkinter.Text(root, width=20, height=5, highlightthickness=2) text.bind('', reportEvent) diff --git a/tools/serialterm.py b/tools/serialterm.py index eceb0ce..7abb0e8 100755 --- a/tools/serialterm.py +++ b/tools/serialterm.py @@ -1,20 +1,20 @@ #!/usr/bin/env python -from __future__ import division, print_function + """Simple serial terminal. Type and press in the entry field along the bottom to send data """ import sys import os -import Tkinter +import tkinter RORoot = os.path.join(os.path.dirname(os.path.abspath(os.path.dirname(__file__))), "python") sys.path.append(RORoot) import RO.CnvUtil import RO.Comm.TkSerial import RO.Wdg -class SerialTerminal(Tkinter.Frame): +class SerialTerminal(tkinter.Frame): def __init__(self, master, portName, localEcho=False, **serialOptions): - Tkinter.Frame.__init__(self, master) + tkinter.Frame.__init__(self, master) self.localEcho = RO.CnvUtil.asBool(localEcho) self.conn = RO.Comm.TkSerial.TkSerial(portName, readCallback=self.doRead, **serialOptions) @@ -56,6 +56,6 @@ def doWrite(self, strToSend): for argInd in range(2, nArgs, 2): serialOptions[sys.argv[argInd]] = sys.argv[argInd+1] - root = Tkinter.Tk() + root = tkinter.Tk() serTerm = SerialTerminal(root, portName, **serialOptions) root.mainloop() diff --git a/tools/tcpclient.py b/tools/tcpclient.py index c93bb5f..b0da0c6 100755 --- a/tools/tcpclient.py +++ b/tools/tcpclient.py @@ -1,20 +1,20 @@ #!/usr/bin/env python -from __future__ import absolute_import, division, print_function + """Example trivial telnet client using RO.Comm.TCPConnection History: 2009-07-10 ROwen Removed an inline conditional statement to be Python 2.4 compatible. """ import sys -import Tkinter +import tkinter import RO.Comm.Generic RO.Comm.Generic.setFramework("tk") import RO.Comm.TCPConnection import RO.Wdg -class TCPClient(Tkinter.Frame): +class TCPClient(tkinter.Frame): def __init__(self, master, addr, port=None): - Tkinter.Frame.__init__(self, master) + tkinter.Frame.__init__(self, master) self.logWdg = RO.Wdg.LogWdg( master = self, maxLines = 1000, @@ -73,7 +73,7 @@ def logMsg(self, msg): else: port = 23 - root = Tkinter.Tk() + root = tkinter.Tk() root.geometry("400x200") client = TCPClient(root, addr, port) client.pack(side="top", expand=True, fill="both") From c30d9f38c4f39400ba8ca53ec70e26740db7aa2c Mon Sep 17 00:00:00 2001 From: Dylan Gatlin Date: Thu, 13 Feb 2020 02:40:06 -0700 Subject: [PATCH 2/6] Removed pyfits, changed comments of Tkinter to tkinter --- python/RO/Wdg/OptionButtons.py | 13 +++++++------ python/RO/Wdg/RadiobuttonSet.py | 5 +++-- tools/fitsinfo.py | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/python/RO/Wdg/OptionButtons.py b/python/RO/Wdg/OptionButtons.py index 1fda27f..5d14ba9 100755 --- a/python/RO/Wdg/OptionButtons.py +++ b/python/RO/Wdg/OptionButtons.py @@ -37,11 +37,12 @@ __all__ = ['OptionButtons'] import RO.InputCont -from . import Button -from . import Checkbutton +from .Button import Button +from .Checkbutton import Checkbutton from .InputContFrame import InputContFrame from .Label import Label + class OptionButtons(InputContFrame): def __init__ (self, master, @@ -127,7 +128,7 @@ def listGet(aList, ind, defVal=None): helpURL = listGet(optionData, 4) if helpURLPrefix and not helpURL: helpURL = helpURLPrefix + nameStr - wdg = Checkbutton.Checkbutton(self, + wdg = Checkbutton(self, text=labelStr, defValue = defVal, helpText = helpText, @@ -156,7 +157,7 @@ def listGet(aList, ind, defVal=None): if defButton is True: defButton = "Defaults" if defButton not in (False, None): - defButtonWdg = Button.Button(self, + defButtonWdg = Button(self, text=defButton, command=self.restoreDefault, helpText = "Restore defaults", @@ -167,7 +168,7 @@ def listGet(aList, ind, defVal=None): if clearButton is True: clearButton = "Clear" if clearButton not in (False, None): - clearButtonWdg = Button.Button(self, + clearButtonWdg = Button(self, text=clearButton, command=self.clear, helpText = "Uncheck all checkboxes", @@ -196,7 +197,7 @@ def setEnable(wdg=None): ) enableButton.pack() - printButton = Button.Button ( + printButton = Button ( master = root, command = doPrint, text = "Print Values", diff --git a/python/RO/Wdg/RadiobuttonSet.py b/python/RO/Wdg/RadiobuttonSet.py index 8e721df..1a8c8b5 100755 --- a/python/RO/Wdg/RadiobuttonSet.py +++ b/python/RO/Wdg/RadiobuttonSet.py @@ -42,6 +42,7 @@ Moved fix for Aqua Tk 8.5 width bug to RO.Wdg.Radiobutton. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. +2020-02-10 DGatlin Updated imports for Python 3 """ __all__ = ['RadiobuttonSet'] @@ -51,7 +52,7 @@ import RO.SeqUtil import RO.StringUtil import RO.TkUtil -from . import Button +from .Button import Radiobutton from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentActiveMixin class RadiobuttonSet (RO.AddCallback.TkVarMixin, @@ -160,7 +161,7 @@ def __init__(self, helpURLList = RO.SeqUtil.oneOrNAsList(helpURL, nButtons, "helpURL list") self.wdgSet = [] for ii in range(nButtons): - wdg = Button.Radiobutton( + wdg = Radiobutton( master = master, variable = self._var, text = textList[ii], diff --git a/tools/fitsinfo.py b/tools/fitsinfo.py index 6ac7332..eb2a35b 100755 --- a/tools/fitsinfo.py +++ b/tools/fitsinfo.py @@ -2,7 +2,7 @@ import argparse import numpy -import pyfits +from astropy.io import fits def fitsInfo(filePath, hduList=None, showHeader=True, showStats=True): """Print information about a FITS file @@ -12,7 +12,7 @@ def fitsInfo(filePath, hduList=None, showHeader=True, showStats=True): @param[in] showHeader: if True then show the header contents @param[in] showStats: if True then show basic image statistics """ - fitsFile = pyfits.open(filePath) + fitsFile = fits.open(filePath) print("*** FITS file %r:" % (filePath,)) if hduList is None: hduList = list(range(len(fitsFile))) From e34bb41e3808db638c97fc8a59df2a29c6b8eeab Mon Sep 17 00:00:00 2001 From: Dylan Gatlin Date: Fri, 14 Feb 2020 00:02:40 -0700 Subject: [PATCH 3/6] Resolved many Python 3 issues, including non-essential ones for STUI --- python/RO/Alg/IDGen.py | 5 +- python/RO/Alg/MultiDict.py | 9 +- python/RO/Astro/Cnv/AppGeoData.py | 3 +- python/RO/Astro/Cnv/AzAltFromHADec.py | 2 + python/RO/Astro/Cnv/CoordConv.py | 1 + python/RO/Astro/Cnv/FK4FromICRS.py | 3 +- python/RO/Astro/Cnv/FK5Prec.py | 2 + python/RO/Astro/Cnv/GeoFromICRS.py | 2 + python/RO/Astro/Cnv/GeoFromTopo.py | 2 + python/RO/Astro/Cnv/HADecFromAzAlt.py | 2 + python/RO/Astro/Cnv/ICRSFromFixedFK4.py | 3 +- python/RO/Astro/Cnv/ICRSFromGeo.py | 1 + python/RO/Astro/Cnv/ObsFromTopo.py | 6 +- python/RO/Astro/Cnv/ObserverData.py | 3 + python/RO/Astro/Cnv/TopoFromGeo.py | 2 + python/RO/Astro/Cnv/TopoFromObs.py | 6 +- python/RO/Astro/Cnv/__init__.py | 4 +- python/RO/Astro/Sph/AngSep.py | 3 + python/RO/Astro/Sph/AzAltFromHADec.py | 3 +- python/RO/Astro/Sph/CCFromSC.py | 2 + python/RO/Astro/Sph/CCFromSCPV.py | 2 +- python/RO/Astro/Sph/CoordConv.py | 5 +- python/RO/Astro/Sph/HADecFromAzAlt.py | 3 +- python/RO/Astro/Sph/SCFromCC.py | 2 + python/RO/Astro/Sph/SCFromCCPV.py | 1 + python/RO/Astro/Sph/SCFromCCPVOff.py | 3 +- python/RO/Astro/Tm/GMSTFromUT1.py | 4 +- python/RO/Astro/Tm/LASTFromUT1.py | 3 +- python/RO/Astro/Tm/MJDFromPyTuple.py | 2 + python/RO/Astro/Tm/UTCFromPySec.py | 1 + python/RO/Astro/Tm/__init__.py | 2 +- python/RO/Astro/llv/eqeqx.py | 1 + python/RO/Astro/llv/etrms.py | 3 + python/RO/Astro/llv/euler.py | 2 + python/RO/Astro/llv/evp.py | 4 +- python/RO/Astro/llv/mappa.py | 5 +- python/RO/Astro/llv/nut.py | 3 +- python/RO/Astro/llv/nutc.py | 1 + python/RO/Astro/llv/prebn.py | 2 + python/RO/Astro/llv/prenut.py | 6 +- python/RO/Astro/llv/vn.py | 2 + python/RO/CanvasUtil.py | 2 + python/RO/Comm/FTPGet.py | 6 +- python/RO/Comm/Generic.py | 17 +- python/RO/Comm/HTTPGet.py | 1 + python/RO/Comm/HubConnection.py | 3 +- python/RO/Comm/TCPConnection.py | 6 +- python/RO/Comm/TkSerial.py | 8 +- python/RO/Comm/TkSocket.py | 4 +- python/RO/Comm/TwistedSocket.py | 9 +- python/RO/Comm/VMSTelnet.py | 2 + python/RO/DS9.py | 10 +- python/RO/InputCont.py | 1 - python/RO/KeyDispatcher.py | 5 +- python/RO/KeyVariable.py | 6 +- python/RO/MathUtil.py | 11 +- python/RO/OS/OSUtil.py | 4 +- python/RO/OS/getMacDirs.py | 4 +- python/RO/PVT.py | 1 + python/RO/ParseMsg/GetValues.py | 5 +- python/RO/ParseMsg/ParseData.py | 3 +- python/RO/Prefs/PrefEditor.py | 6 +- python/RO/Prefs/PrefVar.py | 110 +++--- python/RO/Prefs/PrefWdg.py | 6 +- python/RO/ScriptRunner.py | 3 +- python/RO/SeqUtil.py | 2 + python/RO/StringUtil.py | 20 +- python/RO/TkUtil.py | 3 +- python/RO/Wdg/BalloonHelp.py | 7 +- python/RO/Wdg/Bindings.py | 2 + python/RO/Wdg/Button.py | 4 +- python/RO/Wdg/ChangedIndicator.py | 2 + python/RO/Wdg/Checkbutton.py | 6 +- python/RO/Wdg/CmdWdg.py | 2 + python/RO/Wdg/CtxMenu.py | 6 +- python/RO/Wdg/DropletApp.py | 10 +- python/RO/Wdg/DropletRunner.py | 10 +- python/RO/Wdg/Entry.py | 16 +- python/RO/Wdg/FTPLogWdg.py | 9 +- python/RO/Wdg/GrayImageDispWdg.py | 501 +++++++++++++----------- python/RO/Wdg/Gridder.py | 8 +- python/RO/Wdg/HTTPGetWdg.py | 7 +- python/RO/Wdg/HistoryMenu.py | 8 +- python/RO/Wdg/InputContPresetsWdg.py | 19 +- python/RO/Wdg/InputDialog.py | 7 +- python/RO/Wdg/IsCurrentMixin.py | 4 +- python/RO/Wdg/Label.py | 10 +- python/RO/Wdg/LogWdg.py | 9 +- python/RO/Wdg/Menubutton.py | 4 +- python/RO/Wdg/OptionButtons.py | 4 +- python/RO/Wdg/OptionMenu.py | 12 +- python/RO/Wdg/OptionPanelControl.py | 2 + python/RO/Wdg/PatchedCanvas.py | 3 +- python/RO/Wdg/PathWdg.py | 4 +- python/RO/Wdg/ProgressBar.py | 20 +- python/RO/Wdg/PythonTk.py | 6 +- python/RO/Wdg/PythonWdg.py | 6 +- python/RO/Wdg/RadiobuttonSet.py | 6 +- python/RO/Wdg/ResizableRect.py | 7 +- python/RO/Wdg/ScriptWdg.py | 23 +- python/RO/Wdg/ScrolledWdg.py | 4 +- python/RO/Wdg/SeverityMixin.py | 4 +- python/RO/Wdg/Sound.py | 2 + python/RO/Wdg/StateTracker.py | 2 + python/RO/Wdg/StatusBar.py | 4 +- python/RO/Wdg/StripChartWdg.py | 6 +- python/RO/Wdg/Text.py | 4 +- python/RO/Wdg/Toplevel.py | 3 +- python/RO/Wdg/WdgPrefs.py | 3 +- python/RO/procFiles.py | 2 + setup.py | 6 +- 111 files changed, 696 insertions(+), 467 deletions(-) diff --git a/python/RO/Alg/IDGen.py b/python/RO/Alg/IDGen.py index 297c81e..9837bc6 100644 --- a/python/RO/Alg/IDGen.py +++ b/python/RO/Alg/IDGen.py @@ -38,7 +38,10 @@ def __init__(self, startVal=1, wrapVal=None, incr=1): def __iter__(self): return self - + + def next(self): + return self.__next__() + def __next__(self): """Return the next ID number.""" newID = self.startVal + (self.ind * self.incr) diff --git a/python/RO/Alg/MultiDict.py b/python/RO/Alg/MultiDict.py index f685519..f6ccd7c 100755 --- a/python/RO/Alg/MultiDict.py +++ b/python/RO/Alg/MultiDict.py @@ -13,10 +13,13 @@ and added SetDict. 2010-05-18 ROwen Modified SetDict to use sets 2015-09-24 ROwen Replace "== None" with "is None" to future-proof array tests and modernize the code. +2020-01-13 DGatlin Changed set([val]) to set(val) for Python 3 """ __all__ = ["ListDict", "SetDict"] - -from collections import UserDict +try: + from collections import UserDict +except ImportError: + from UserDict import UserDict class ListDict(UserDict): """A dictionary whose values are a list of items. @@ -65,7 +68,7 @@ def __setitem__(self, key, val): """ valSet = self.data.get(key) if valSet is None: - self.data[key] = set([val]) + self.data[key] = set(val) else: valSet.add(val) diff --git a/python/RO/Astro/Cnv/AppGeoData.py b/python/RO/Astro/Cnv/AppGeoData.py index 42f7121..37cc27c 100755 --- a/python/RO/Astro/Cnv/AppGeoData.py +++ b/python/RO/Astro/Cnv/AppGeoData.py @@ -8,8 +8,9 @@ """ __all__ = ["AppGeoData"] -from RO.Astro import llv from RO.Astro import Tm +from RO.Astro import llv + class AppGeoData(object): """Position-independent data for conversion diff --git a/python/RO/Astro/Cnv/AzAltFromHADec.py b/python/RO/Astro/Cnv/AzAltFromHADec.py index b1d3378..83d7c6d 100755 --- a/python/RO/Astro/Cnv/AzAltFromHADec.py +++ b/python/RO/Astro/Cnv/AzAltFromHADec.py @@ -8,8 +8,10 @@ __all__ = ["azAltFromHADec"] import numpy + import RO.MathUtil + def azAltFromHADec (haDec, lat): """Converts cartesian HA/Dec position to alt/az. diff --git a/python/RO/Astro/Cnv/CoordConv.py b/python/RO/Astro/Cnv/CoordConv.py index a637eb6..51aa9dc 100755 --- a/python/RO/Astro/Cnv/CoordConv.py +++ b/python/RO/Astro/Cnv/CoordConv.py @@ -30,6 +30,7 @@ __all__ = ["coordConv"] import numpy + import RO.CoordSys from RO.Astro import Tm from .AppGeoData import AppGeoData diff --git a/python/RO/Astro/Cnv/FK4FromICRS.py b/python/RO/Astro/Cnv/FK4FromICRS.py index 2ee3bb4..a74d4ba 100755 --- a/python/RO/Astro/Cnv/FK4FromICRS.py +++ b/python/RO/Astro/Cnv/FK4FromICRS.py @@ -8,8 +8,9 @@ __all__ = ["fk4FromICRS"] import numpy -import RO.PhysConst + import RO.MathUtil +import RO.PhysConst from RO.Astro import llv # Constants diff --git a/python/RO/Astro/Cnv/FK5Prec.py b/python/RO/Astro/Cnv/FK5Prec.py index 5b94cbe..ae2eeea 100755 --- a/python/RO/Astro/Cnv/FK5Prec.py +++ b/python/RO/Astro/Cnv/FK5Prec.py @@ -8,8 +8,10 @@ __all__ = ["fk5Prec"] import numpy + from RO.Astro import llv + def fk5Prec(fromP, fromV, fromDate, toDate): """ Inputs: diff --git a/python/RO/Astro/Cnv/GeoFromICRS.py b/python/RO/Astro/Cnv/GeoFromICRS.py index 5dfa449..7028061 100755 --- a/python/RO/Astro/Cnv/GeoFromICRS.py +++ b/python/RO/Astro/Cnv/GeoFromICRS.py @@ -8,8 +8,10 @@ __all__ = ["geoFromICRS"] import numpy + from RO.Astro import llv + def geoFromICRS(icrsP, icrsV, agData): """ Converts ICRS coordinates to apparent geocentric coordinates. diff --git a/python/RO/Astro/Cnv/GeoFromTopo.py b/python/RO/Astro/Cnv/GeoFromTopo.py index ab055b6..5704c34 100755 --- a/python/RO/Astro/Cnv/GeoFromTopo.py +++ b/python/RO/Astro/Cnv/GeoFromTopo.py @@ -10,10 +10,12 @@ __all__ = ["geoFromTopo"] import numpy + import RO.MathUtil from RO.Astro import llv from .HADecFromAzAlt import haDecFromAzAlt + def geoFromTopo(appTopoP, last, obsData): """ Converts apparent topocentric coordinates to apparent geocentric coordinates. diff --git a/python/RO/Astro/Cnv/HADecFromAzAlt.py b/python/RO/Astro/Cnv/HADecFromAzAlt.py index a8960ec..7a56297 100755 --- a/python/RO/Astro/Cnv/HADecFromAzAlt.py +++ b/python/RO/Astro/Cnv/HADecFromAzAlt.py @@ -9,8 +9,10 @@ __all__ = ["haDecFromAzAlt"] import numpy + import RO.MathUtil + def haDecFromAzAlt(azAlt, lat): """Converts alt/az position to HA/Dec position. diff --git a/python/RO/Astro/Cnv/ICRSFromFixedFK4.py b/python/RO/Astro/Cnv/ICRSFromFixedFK4.py index dfd0eae..41dfc31 100755 --- a/python/RO/Astro/Cnv/ICRSFromFixedFK4.py +++ b/python/RO/Astro/Cnv/ICRSFromFixedFK4.py @@ -9,8 +9,9 @@ __all__ = ["icrsFromFixedFK4"] import numpy -import RO.PhysConst + import RO.MathUtil +import RO.PhysConst from RO.Astro import llv, Tm # Constants diff --git a/python/RO/Astro/Cnv/ICRSFromGeo.py b/python/RO/Astro/Cnv/ICRSFromGeo.py index 40f4db0..5707ea3 100755 --- a/python/RO/Astro/Cnv/ICRSFromGeo.py +++ b/python/RO/Astro/Cnv/ICRSFromGeo.py @@ -9,6 +9,7 @@ __all__ = ["icrsFromGeo"] import numpy + import RO.MathUtil from RO.Astro import llv diff --git a/python/RO/Astro/Cnv/ObsFromTopo.py b/python/RO/Astro/Cnv/ObsFromTopo.py index 2ffbfaa..52708e3 100755 --- a/python/RO/Astro/Cnv/ObsFromTopo.py +++ b/python/RO/Astro/Cnv/ObsFromTopo.py @@ -9,10 +9,12 @@ __all__ = ["obsFromTopo"] from math import sqrt + import numpy -import RO.SysConst -import RO.PhysConst + import RO.MathUtil +import RO.PhysConst +import RO.SysConst # Constants _MaxZDU = 85.0 diff --git a/python/RO/Astro/Cnv/ObserverData.py b/python/RO/Astro/Cnv/ObserverData.py index ac1ebff..6050714 100755 --- a/python/RO/Astro/Cnv/ObserverData.py +++ b/python/RO/Astro/Cnv/ObserverData.py @@ -7,10 +7,13 @@ __all__ = ["ObserverData"] import math + import numpy + import RO.PhysConst from RO.Astro import llv + class ObserverData(object): """Observatory-specific (or observer-specific) data. diff --git a/python/RO/Astro/Cnv/TopoFromGeo.py b/python/RO/Astro/Cnv/TopoFromGeo.py index e412ba5..bc98e43 100755 --- a/python/RO/Astro/Cnv/TopoFromGeo.py +++ b/python/RO/Astro/Cnv/TopoFromGeo.py @@ -9,10 +9,12 @@ __all__ = ["topoFromGeo"] import numpy + import RO.MathUtil from RO.Astro import llv from .AzAltFromHADec import azAltFromHADec + def topoFromGeo(appGeoP, last, obsData): """ Converts apparent geocentric coordinates to apparent topocentric coordinates diff --git a/python/RO/Astro/Cnv/TopoFromObs.py b/python/RO/Astro/Cnv/TopoFromObs.py index c7d3138..618b931 100755 --- a/python/RO/Astro/Cnv/TopoFromObs.py +++ b/python/RO/Astro/Cnv/TopoFromObs.py @@ -11,10 +11,12 @@ __all__ = ["topoFromObs"] from math import sqrt + import numpy -import RO.SysConst -import RO.PhysConst + import RO.MathUtil +import RO.PhysConst +import RO.SysConst # Constants # For zdu > _MaxZDU the correction is computed at _MaxZDU. diff --git a/python/RO/Astro/Cnv/__init__.py b/python/RO/Astro/Cnv/__init__.py index 935d5b3..ca0b816 100644 --- a/python/RO/Astro/Cnv/__init__.py +++ b/python/RO/Astro/Cnv/__init__.py @@ -34,12 +34,12 @@ from .GeoFromICRS import * from .GeoFromTopo import * from .HADecFromAzAlt import * -from .ICRSFromFixedFK4 import * from .ICRSFromFK4 import * +from .ICRSFromFixedFK4 import * from .ICRSFromGal import * from .ICRSFromGeo import * -from .ObserverData import * from .ObsFromTopo import * +from .ObserverData import * from .TopoFromGeo import * from .TopoFromGeoSimple import * from .TopoFromObs import * diff --git a/python/RO/Astro/Sph/AngSep.py b/python/RO/Astro/Sph/AngSep.py index b7e92bd..c09e718 100755 --- a/python/RO/Astro/Sph/AngSep.py +++ b/python/RO/Astro/Sph/AngSep.py @@ -9,10 +9,13 @@ __all__ = ["angSep"] import math + import numpy + import RO.MathUtil from .DCFromSC import dcFromSC + def angSep(posA, posB): """Computes the angular separation between two points on a sphere. diff --git a/python/RO/Astro/Sph/AzAltFromHADec.py b/python/RO/Astro/Sph/AzAltFromHADec.py index eafd768..5bffe9b 100755 --- a/python/RO/Astro/Sph/AzAltFromHADec.py +++ b/python/RO/Astro/Sph/AzAltFromHADec.py @@ -3,9 +3,10 @@ __all__ = ["azAltFromHADec"] +from RO.Astro import Cnv from .DCFromSC import dcFromSC from .SCFromDC import scFromDC -from RO.Astro import Cnv + def azAltFromHADec(haDec, lat): """Converts HA/Dec position to az/alt. diff --git a/python/RO/Astro/Sph/CCFromSC.py b/python/RO/Astro/Sph/CCFromSC.py index b609516..c438bb5 100755 --- a/python/RO/Astro/Sph/CCFromSC.py +++ b/python/RO/Astro/Sph/CCFromSC.py @@ -8,8 +8,10 @@ __all__ = ["ccFromSC"] import numpy + import RO.MathUtil + def ccFromSC(pos, magP): """ Converts a spherical position to cartesian coordinates. diff --git a/python/RO/Astro/Sph/CCFromSCPV.py b/python/RO/Astro/Sph/CCFromSCPV.py index 02e596e..4767409 100755 --- a/python/RO/Astro/Sph/CCFromSCPV.py +++ b/python/RO/Astro/Sph/CCFromSCPV.py @@ -3,8 +3,8 @@ __all__ = ["ccFromSCPV"] -import RO.PhysConst import RO.MathUtil +import RO.PhysConst from .CCFromSC import ccFromSC # Magic Numbers diff --git a/python/RO/Astro/Sph/CoordConv.py b/python/RO/Astro/Sph/CoordConv.py index 620b419..e56d260 100755 --- a/python/RO/Astro/Sph/CoordConv.py +++ b/python/RO/Astro/Sph/CoordConv.py @@ -3,12 +3,13 @@ __all__ = ["coordConv"] -from . import Const -from RO.Astro import Cnv import RO.MathUtil +from RO.Astro import Cnv +from . import Const from .CCFromSCPVOff import ccFromSCPVOff from .SCFromCCPVOff import scFromCCPVOff + def coordConv( fromPos, fromSys, fromDate, toSys, toDate, fromPM = (0.0, 0.0), fromParlax=0.0, fromRadVel=0.0, diff --git a/python/RO/Astro/Sph/HADecFromAzAlt.py b/python/RO/Astro/Sph/HADecFromAzAlt.py index 2921282..f799ce1 100755 --- a/python/RO/Astro/Sph/HADecFromAzAlt.py +++ b/python/RO/Astro/Sph/HADecFromAzAlt.py @@ -5,9 +5,10 @@ import RO.MathUtil import RO.SysConst +from RO.Astro import Cnv from .DCFromSC import dcFromSC from .SCFromDC import scFromDC -from RO.Astro import Cnv + def haDecFromAzAlt (azAlt, lat): """Converts alt/az position to ha/dec position. diff --git a/python/RO/Astro/Sph/SCFromCC.py b/python/RO/Astro/Sph/SCFromCC.py index 67794da..6c6d1f6 100755 --- a/python/RO/Astro/Sph/SCFromCC.py +++ b/python/RO/Astro/Sph/SCFromCC.py @@ -4,9 +4,11 @@ __all__ = ["scFromCC"] import math + import RO.MathUtil import RO.SysConst + def scFromCC(p): """ Converts cartesian position to spherical coordinates. diff --git a/python/RO/Astro/Sph/SCFromCCPV.py b/python/RO/Astro/Sph/SCFromCCPV.py index f90426f..e0c1337 100755 --- a/python/RO/Astro/Sph/SCFromCCPV.py +++ b/python/RO/Astro/Sph/SCFromCCPV.py @@ -4,6 +4,7 @@ __all__ = ["scFromCCPV"] import math + import RO.PhysConst from .SCFromCC import scFromCC diff --git a/python/RO/Astro/Sph/SCFromCCPVOff.py b/python/RO/Astro/Sph/SCFromCCPVOff.py index 3ca28cd..5277116 100755 --- a/python/RO/Astro/Sph/SCFromCCPVOff.py +++ b/python/RO/Astro/Sph/SCFromCCPVOff.py @@ -4,8 +4,9 @@ __all__ = ["scFromCCPVOff"] from .AngSideAng import angSideAng -from .SCFromCCPV import scFromCCPV from .SCFromCC import scFromCC +from .SCFromCCPV import scFromCCPV + def scFromCCPVOff(p, v, offP): """ diff --git a/python/RO/Astro/Tm/GMSTFromUT1.py b/python/RO/Astro/Tm/GMSTFromUT1.py index b028692..bdfd255 100755 --- a/python/RO/Astro/Tm/GMSTFromUT1.py +++ b/python/RO/Astro/Tm/GMSTFromUT1.py @@ -4,8 +4,10 @@ __all__ = ["gmstFromUT1"] import math -import RO.PhysConst + import RO.MathUtil +import RO.PhysConst + def gmstFromUT1(ut1): """Convert from universal time (MJD) diff --git a/python/RO/Astro/Tm/LASTFromUT1.py b/python/RO/Astro/Tm/LASTFromUT1.py index 12fc9f8..6900cca 100644 --- a/python/RO/Astro/Tm/LASTFromUT1.py +++ b/python/RO/Astro/Tm/LASTFromUT1.py @@ -2,11 +2,12 @@ __all__ = ["lastFromUT1"] -import RO.PhysConst import RO.MathUtil +import RO.PhysConst from RO.Astro import llv from .LMSTFromUT1 import lmstFromUT1 + def lastFromUT1(ut1, longitude): """Convert from universal time (MJD) to local apparent sidereal time (deg). diff --git a/python/RO/Astro/Tm/MJDFromPyTuple.py b/python/RO/Astro/Tm/MJDFromPyTuple.py index a90088d..aad012d 100755 --- a/python/RO/Astro/Tm/MJDFromPyTuple.py +++ b/python/RO/Astro/Tm/MJDFromPyTuple.py @@ -4,8 +4,10 @@ __all__ = ["mjdFromPyTuple"] import math + import RO.PhysConst + def mjdFromPyTuple(timeTuple): """Converts a python time tuple to Modified Julian Date. Only the first six elements of the time tuple are used: diff --git a/python/RO/Astro/Tm/UTCFromPySec.py b/python/RO/Astro/Tm/UTCFromPySec.py index 8140f73..a1dfcd3 100644 --- a/python/RO/Astro/Tm/UTCFromPySec.py +++ b/python/RO/Astro/Tm/UTCFromPySec.py @@ -8,6 +8,7 @@ __all__ = ["setClockError", "getClockError", "getCurrPySec", "utcFromPySec", "pySecFromUTC"] import time + import RO.PhysConst # Python time tuple for J2000: 2000-01-01 12:00:00 (a Saturday) diff --git a/python/RO/Astro/Tm/__init__.py b/python/RO/Astro/Tm/__init__.py index 704130d..a4b0971 100644 --- a/python/RO/Astro/Tm/__init__.py +++ b/python/RO/Astro/Tm/__init__.py @@ -23,10 +23,10 @@ """ from .EpJFromMJD import * from .GMSTFromUT1 import * +from .ISODate import * from .LASTFromUT1 import * from .LMSTFromUT1 import * from .MJDFromEpJ import * from .MJDFromPyTuple import * from .TAI import * from .UTCFromPySec import * -from .ISODate import * diff --git a/python/RO/Astro/llv/eqeqx.py b/python/RO/Astro/llv/eqeqx.py index eb97e31..89dcba9 100755 --- a/python/RO/Astro/llv/eqeqx.py +++ b/python/RO/Astro/llv/eqeqx.py @@ -4,6 +4,7 @@ __all__ = ["eqeqx"] import math + import RO.PhysConst from .nutc import nutc diff --git a/python/RO/Astro/llv/etrms.py b/python/RO/Astro/llv/etrms.py index ae7865b..575282f 100755 --- a/python/RO/Astro/llv/etrms.py +++ b/python/RO/Astro/llv/etrms.py @@ -9,9 +9,12 @@ __all__ = ["etrms"] import math + import numpy + import RO.PhysConst + def etrms(bep): """ Compute the e-terms (elliptic component of annual aberration) diff --git a/python/RO/Astro/llv/euler.py b/python/RO/Astro/llv/euler.py index 8002cee..cd1ca79 100755 --- a/python/RO/Astro/llv/euler.py +++ b/python/RO/Astro/llv/euler.py @@ -9,8 +9,10 @@ __all__ = ["euler"] import math + import numpy + def euler(axisAngSet): """ Form a rotation matrix from successive rotations diff --git a/python/RO/Astro/llv/evp.py b/python/RO/Astro/llv/evp.py index 363d0b5..5c34c2a 100755 --- a/python/RO/Astro/llv/evp.py +++ b/python/RO/Astro/llv/evp.py @@ -9,9 +9,11 @@ __all__ = ["evp"] from math import sin, cos, pi, sqrt, fmod + import numpy -from .prec import prec + from .epj import epj +from .prec import prec # Constants TWOPI = pi * 2.0 diff --git a/python/RO/Astro/llv/mappa.py b/python/RO/Astro/llv/mappa.py index 0ea3f18..fa0161f 100755 --- a/python/RO/Astro/llv/mappa.py +++ b/python/RO/Astro/llv/mappa.py @@ -9,10 +9,11 @@ __all__ = ["mappa"] from math import sqrt -from .vn import vn + +from .epj import epj from .evp import evp from .prenut import prenut -from .epj import epj +from .vn import vn # Constants # Light time for 1 au (sec) diff --git a/python/RO/Astro/llv/nut.py b/python/RO/Astro/llv/nut.py index 7af6f23..5d32755 100755 --- a/python/RO/Astro/llv/nut.py +++ b/python/RO/Astro/llv/nut.py @@ -8,8 +8,9 @@ """ __all__ = ["nut"] -from .nutc import nutc from .euler import euler +from .nutc import nutc + def nut(tdb): """ diff --git a/python/RO/Astro/llv/nutc.py b/python/RO/Astro/llv/nutc.py index 50a375f..e132619 100755 --- a/python/RO/Astro/llv/nutc.py +++ b/python/RO/Astro/llv/nutc.py @@ -4,6 +4,7 @@ __all__ = ["nutc"] import math + import RO.PhysConst _ArcSecPerRev = RO.PhysConst.ArcSecPerDeg * 360.0 diff --git a/python/RO/Astro/llv/prebn.py b/python/RO/Astro/llv/prebn.py index 60d2ec4..adb7829 100755 --- a/python/RO/Astro/llv/prebn.py +++ b/python/RO/Astro/llv/prebn.py @@ -10,9 +10,11 @@ __all__ = ["prebn"] import numpy + import RO.PhysConst from .euler import euler + def prebn(bep0, bep1): """ Generate the matrix of precession between two epochs, diff --git a/python/RO/Astro/llv/prenut.py b/python/RO/Astro/llv/prenut.py index 151b891..242367f 100755 --- a/python/RO/Astro/llv/prenut.py +++ b/python/RO/Astro/llv/prenut.py @@ -9,9 +9,11 @@ __all__ = ["prenut"] import numpy -from .prec import prec -from .nut import nut + from .epj import epj +from .nut import nut +from .prec import prec + def prenut(epoch, mjd): """ diff --git a/python/RO/Astro/llv/vn.py b/python/RO/Astro/llv/vn.py index c79b45e..6a69cfb 100755 --- a/python/RO/Astro/llv/vn.py +++ b/python/RO/Astro/llv/vn.py @@ -9,9 +9,11 @@ __all__ = ["vn"] import numpy + import RO.MathUtil import RO.SysConst + def vn(vec): """ Normalises a vector. diff --git a/python/RO/CanvasUtil.py b/python/RO/CanvasUtil.py index ffb379a..bac4454 100755 --- a/python/RO/CanvasUtil.py +++ b/python/RO/CanvasUtil.py @@ -23,8 +23,10 @@ import math import tkinter + import RO.MathUtil + def ctrCircle(cnv, xpos, ypos, rad, width = 1, **kargs): """Draws a centered circle on the specified canvas. diff --git a/python/RO/Comm/FTPGet.py b/python/RO/Comm/FTPGet.py index 6c93f4f..604b07f 100644 --- a/python/RO/Comm/FTPGet.py +++ b/python/RO/Comm/FTPGet.py @@ -41,11 +41,11 @@ """ __all__ = ['FTPGet'] +import ftplib import os import sys -import urllib.parse import threading -import ftplib +import urllib.parse _Debug = False @@ -274,7 +274,7 @@ def _getTask(self): mode = "wb" else: mode = "w" - self._toFile = file(self.toPath, mode) + self._toFile = open(self.toPath, mode) # open input socket if _Debug: diff --git a/python/RO/Comm/Generic.py b/python/RO/Comm/Generic.py index 3c2e7bf..639b879 100755 --- a/python/RO/Comm/Generic.py +++ b/python/RO/Comm/Generic.py @@ -14,10 +14,10 @@ Here are some examples: -1) Using Tkinter with the Tcl event loop (no Twisted) +1) Using tkinter with the Tcl event loop (no Twisted) -import Tkinter -root = Tkinter.Tk() +import tkinter +root = tkinter.Tk() import RO.Comm.Generic RO.Comm.Generic.setFramework("tk") @@ -39,11 +39,11 @@ #... reactor.run() -3) Using Twisted framework with Tkinter +3) Using Twisted framework with tkinter -import Tkinter +import tkinter import twisted.internet.tksupport -root = Tkinter.Tk() +root = tkinter.Tk() twisted.internet.tksupport.install(root) from twisted.internet import reactor @@ -60,10 +60,12 @@ __all__ = ["setFramework", "getFramework", "getFrameworkSet", "TCPSocket", "TCPSocket", "Timer", "WaitForTCPServer"] import time + from RO.AddCallback import safeCall2 _Framework = None + def setFramework(framework): """Set which framework you wish to use. @@ -77,7 +79,8 @@ def setFramework(framework): global _Framework, TCPSocket, TCPServer, Timer if framework not in getFrameworkSet(): frameworkList = sorted(list(getFrameworkSet())) - raise ValueError("framework=%r; must be one of %s" % (frameworkList,)) + raise ValueError("framework=%r; must be one of %s".fomrat( + *frameworkList)) if framework == "tk": from RO.Comm.TkSocket import TCPSocket, TCPServer diff --git a/python/RO/Comm/HTTPGet.py b/python/RO/Comm/HTTPGet.py index adc2eca..95b91ae 100755 --- a/python/RO/Comm/HTTPGet.py +++ b/python/RO/Comm/HTTPGet.py @@ -47,6 +47,7 @@ import sys import time import tkinter + import RO.AddCallback import RO.StringUtil import RO.TkUtil diff --git a/python/RO/Comm/HubConnection.py b/python/RO/Comm/HubConnection.py index 9bcffe6..8a3f99b 100755 --- a/python/RO/Comm/HubConnection.py +++ b/python/RO/Comm/HubConnection.py @@ -40,9 +40,10 @@ shaClass = sha.sha import sys -from .TCPConnection import TCPConnection import RO.ParseMsg import RO.StringUtil +from .TCPConnection import TCPConnection + class HubConnection(TCPConnection): """Connection to Apache Point Observatory hub diff --git a/python/RO/Comm/TCPConnection.py b/python/RO/Comm/TCPConnection.py index ab484ca..cccb440 100755 --- a/python/RO/Comm/TCPConnection.py +++ b/python/RO/Comm/TCPConnection.py @@ -58,9 +58,11 @@ __all__ = ["TCPConnection"] import sys -from RO.Comm.BaseSocket import NullTCPSocket -from RO.AddCallback import safeCall2 + import RO.Comm.Generic +from RO.AddCallback import safeCall2 +from RO.Comm.BaseSocket import NullTCPSocket + if RO.Comm.Generic.getFramework() is None: print("Warning: RO.Comm.Generic framework not set; setting to tk") RO.Comm.Generic.setFramework("tk") diff --git a/python/RO/Comm/TkSerial.py b/python/RO/Comm/TkSerial.py index 307e8c0..b431399 100644 --- a/python/RO/Comm/TkSerial.py +++ b/python/RO/Comm/TkSerial.py @@ -30,14 +30,12 @@ __all__ = ["TkSerial", "NullSerial"] import sys -import traceback import tkinter +import traceback + import RO.SeqUtil import RO.TkUtil -try: - set -except NameError: - from sets import Set as set + class TkBaseSerial(object): """Base class for communication via a serial port using the tcl event loop. diff --git a/python/RO/Comm/TkSocket.py b/python/RO/Comm/TkSocket.py index c2d4e00..6e8417a 100755 --- a/python/RO/Comm/TkSocket.py +++ b/python/RO/Comm/TkSocket.py @@ -94,11 +94,13 @@ import re import sys -import traceback import tkinter +import traceback + import RO.TkUtil from RO.Comm.BaseSocket import BaseSocket, BaseServer, nullCallback + class _TkSocketWrapper(object): """Convenience wrapper around a Tk socket """ diff --git a/python/RO/Comm/TwistedSocket.py b/python/RO/Comm/TwistedSocket.py index b7ed2ec..f3c7af8 100755 --- a/python/RO/Comm/TwistedSocket.py +++ b/python/RO/Comm/TwistedSocket.py @@ -23,15 +23,18 @@ import re import sys import traceback -from twisted.python.failure import Failure + +from twisted.internet import reactor +from twisted.internet.endpoints import TCP4ClientEndpoint, TCP4ServerEndpoint from twisted.internet.error import ConnectionDone from twisted.internet.protocol import Factory, Protocol -from twisted.internet.endpoints import TCP4ClientEndpoint, TCP4ServerEndpoint -from twisted.internet import reactor from twisted.python import log +from twisted.python.failure import Failure + from RO.Comm.BaseSocket import BaseSocket, BaseServer, nullCallback from RO.Comm.TwistedTimer import Timer + class _SocketProtocol(Protocol): """Twisted socket protocol for use with these socket classes diff --git a/python/RO/Comm/VMSTelnet.py b/python/RO/Comm/VMSTelnet.py index 2e7fb20..f4d4f49 100755 --- a/python/RO/Comm/VMSTelnet.py +++ b/python/RO/Comm/VMSTelnet.py @@ -30,9 +30,11 @@ __all__ = ["VMSTelnet"] import sys + import RO.Wdg from .TCPConnection import TCPConnection + class VMSTelnet(TCPConnection): """A telnet connection that negotiates the telnet protocol and handles password login. The only thing specific to VMS diff --git a/python/RO/DS9.py b/python/RO/DS9.py index e676aeb..528c294 100755 --- a/python/RO/DS9.py +++ b/python/RO/DS9.py @@ -153,12 +153,14 @@ """ __all__ = ["setup", "xpaget", "xpaset", "DS9Win"] -import numpy import os +import subprocess import time import warnings + +import numpy + import RO.OS -import subprocess _DebugSetup = False @@ -239,8 +241,8 @@ def _findUnixApp(appName): if errMsg: fullErrMsg = "'which %s' failed: %s" % (appName, errMsg) raise RuntimeError(fullErrMsg) - appPath = p.stdout.read().strip(b'\n') - if not appPath.startswith(b"/"): + appPath = p.stdout.read().strip(b'\n').decode('utf-8') + if not appPath.startswith("/"): raise RuntimeError("Could not find %s on your PATH" % (appName,)) finally: p.stdout.close() diff --git a/python/RO/InputCont.py b/python/RO/InputCont.py index 446780b..7f56768 100755 --- a/python/RO/InputCont.py +++ b/python/RO/InputCont.py @@ -95,7 +95,6 @@ 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. """ -import itertools import RO.AddCallback import RO.SeqUtil diff --git a/python/RO/KeyDispatcher.py b/python/RO/KeyDispatcher.py index 2b8a263..3766d5e 100755 --- a/python/RO/KeyDispatcher.py +++ b/python/RO/KeyDispatcher.py @@ -94,11 +94,12 @@ import sys import time import traceback + import RO.Alg import RO.CnvUtil +import RO.Comm.HubConnection import RO.Constants import RO.KeyVariable -import RO.Comm.HubConnection import RO.ParseMsg import RO.StringUtil from RO.Comm.Generic import Timer @@ -359,7 +360,7 @@ def executeCmd(self, cmdVar): try: fullCmd = "%d %s %s" % (cmdVar.cmdID, cmdVar.actor, cmdVar.cmdStr) - self.connection.writeLine (fullCmd) + self.connection.writeLine(fullCmd) # self.logMsg ( # msgStr = fullCmd, # actor = cmdVar.actor, diff --git a/python/RO/KeyVariable.py b/python/RO/KeyVariable.py index a217125..b2a4d47 100755 --- a/python/RO/KeyVariable.py +++ b/python/RO/KeyVariable.py @@ -134,15 +134,17 @@ import sys import time import traceback + import RO.AddCallback import RO.Alg import RO.CnvUtil +import RO.Comm.Generic import RO.Constants import RO.LangUtil import RO.PVT -import RO.StringUtil import RO.SeqUtil -import RO.Comm.Generic +import RO.StringUtil + if RO.Comm.Generic.getFramework() is None: print("Warning: RO.Comm.Generic framework not set; setting to tk") RO.Comm.Generic.setFramework("tk") diff --git a/python/RO/MathUtil.py b/python/RO/MathUtil.py index 4e5e7c1..7506b8b 100644 --- a/python/RO/MathUtil.py +++ b/python/RO/MathUtil.py @@ -29,9 +29,11 @@ "nint", "sign", "logEq", "logNE", "rot2D", "rThetaFromXY", "xyFromRTheta", "vecMag", "wrapCtr", "wrapPos"] import math + import numpy -from RO.PhysConst import RadPerDeg + import RO.SysConst +from RO.PhysConst import RadPerDeg DegPerRad = 1.0 / RadPerDeg _TinyFloat = numpy.finfo(float).tiny @@ -87,7 +89,12 @@ def compareFloats(a, b, rtol=1.0e-5, atol=RO.SysConst.FAccuracy): """ if abs(a - b) < (atol + (rtol * abs(float(a + b)))): return 0 - return cmp(a, b) + elif a > b: + return 1 + elif a < b: + return -1 + else: + return None def checkRange(value, minValue, maxValue, valDescr="value"): """Checks that value is in range [minValue, maxValue] and raises a ValueError if not. diff --git a/python/RO/OS/OSUtil.py b/python/RO/OS/OSUtil.py index 1cac32d..a197fa2 100644 --- a/python/RO/OS/OSUtil.py +++ b/python/RO/OS/OSUtil.py @@ -25,11 +25,13 @@ """ __all__ = ["delDir", "expandPath", "findFiles", "getResourceDir", "removeDupPaths", "splitPath", "openUniv"] +import fnmatch import os.path import sys -import fnmatch + import RO.SeqUtil + def delDir(dirPath): """Delete dirPath and all contents (including symbolic links, but does not follow those links). diff --git a/python/RO/OS/getMacDirs.py b/python/RO/OS/getMacDirs.py index d7b53e9..19446b8 100644 --- a/python/RO/OS/getMacDirs.py +++ b/python/RO/OS/getMacDirs.py @@ -17,9 +17,11 @@ 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. """ -import Carbon.Folder, Carbon.Folders +import Carbon.Folder +import Carbon.Folders import MacOS + def getStandardDir(domain, dirType, doCreate=False): """Return a path to the specified standard directory or None if not found. diff --git a/python/RO/PVT.py b/python/RO/PVT.py index 3c434a3..e451c57 100644 --- a/python/RO/PVT.py +++ b/python/RO/PVT.py @@ -23,6 +23,7 @@ import RO.MathUtil import RO.PhysConst + class PVT(object): """Defines a position, velocity, time triplet, where time is in TAI. diff --git a/python/RO/ParseMsg/GetValues.py b/python/RO/ParseMsg/GetValues.py index 79f2fe2..f6324b9 100755 --- a/python/RO/ParseMsg/GetValues.py +++ b/python/RO/ParseMsg/GetValues.py @@ -21,7 +21,8 @@ __all__ = ["getValues"] import re -from . import GetString + +from .GetString import getString _StartRE = re.compile(r"\s*(?P[=;])\s*(?:(?P\S)|$)") @@ -69,7 +70,7 @@ def getValues(astr, begInd=0): if astr[nextInd] in "\'\"": # value is a delimited string # print "looking for a delimited string" - (value, nextInd) = GetString.getString(astr, nextInd) + (value, nextInd) = getString(astr, nextInd) valueList.append(value) elif astr[nextInd] != ';': diff --git a/python/RO/ParseMsg/ParseData.py b/python/RO/ParseMsg/ParseData.py index dc12573..c882f73 100755 --- a/python/RO/ParseMsg/ParseData.py +++ b/python/RO/ParseMsg/ParseData.py @@ -13,9 +13,10 @@ """ __all__ = ["parseKeyValueData"] +import RO.Alg from .GetKeyword import getKeyword from .GetValues import getValues -import RO.Alg + def parseKeyValueData(astr): """Parses a string of the form: diff --git a/python/RO/Prefs/PrefEditor.py b/python/RO/Prefs/PrefEditor.py index ab8b953..56df3a7 100755 --- a/python/RO/Prefs/PrefEditor.py +++ b/python/RO/Prefs/PrefEditor.py @@ -61,16 +61,18 @@ 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. """ import sys -from . import PrefVar import tkinter import tkinter.colorchooser import tkinter.font + import RO.Alg import RO.Wdg from RO.TkUtil import Timer +from . import PrefVar __all__ = ["getPrefEditor"] + def getPrefEditor( prefVar, master, @@ -90,7 +92,7 @@ def getPrefEditor( return FilePrefEditor(prefVar, master, row, column) elif isinstance(prefVar, PrefVar.FontPrefVar): return FontPrefEditor(prefVar, master, row, column) - elif isinstance(prefVar, PrefVar.PrefVar): + elif isinstance(prefVar, PrefVar.BasePrefVar): return PrefEditor(prefVar, master, row, column) else: raise ValueError("prefVar is of unknown type") diff --git a/python/RO/Prefs/PrefVar.py b/python/RO/Prefs/PrefVar.py index 52259ea..aced002 100755 --- a/python/RO/Prefs/PrefVar.py +++ b/python/RO/Prefs/PrefVar.py @@ -91,7 +91,7 @@ 2015-11-03 ROwen Replace "!= None" with "is not None" to modernize the code. Stop using dangerous bare "except:". """ -__all__ = ["PrefVar", "StrPrefVar", "DirectoryPrefVar", "FilePrefVar", "SoundPrefVar", "BoolPrefVar", \ +__all__ = ["BasePrefVar", "StrPrefVar", "DirectoryPrefVar", "FilePrefVar", "SoundPrefVar", "BoolPrefVar", \ "IntPrefVar", "FloatPrefVar", "ColorPrefVar", "FontPrefVar", "FontSizePrefVar", "PrefSet"] import os.path @@ -99,6 +99,7 @@ import sys import tkinter import tkinter.font + import RO.Alg import RO.CnvUtil import RO.MathUtil @@ -106,7 +107,8 @@ import RO.StringUtil import RO.Wdg -class PrefVar(object): + +class BasePrefVar(object): """Base class for preference variables. Intended to be subclassed, not used directly. Inputs: @@ -316,7 +318,7 @@ def __str__(self): return ("%s " + self.formatStr) % (self.name, self.value) -class StrPrefVar(PrefVar): +class StrPrefVar(BasePrefVar): """String preference variable with optional pattern matching. Inputs: same as PrefVar, plus: @@ -347,12 +349,12 @@ def __init__(self, kargs.setdefault("formatStr", "%s") kargs.setdefault("cnvFunc", str) - PrefVar.__init__(self, - name = name, - category = category, - defValue = defValue, - **kargs - ) + BasePrefVar.__init__(self, + name = name, + category = category, + defValue = defValue, + **kargs + ) def locCheckValue(self, value): """Test that the string matches the desired pattern, if any. @@ -526,7 +528,7 @@ def setValue (self, rawValue): ) -class BoolPrefVar(PrefVar): +class BoolPrefVar(BasePrefVar): """A boolean-valued PrefVar. Inputs: same as PrefVar, but validValues and suggValues are ignored. @@ -544,12 +546,12 @@ def __init__(self, kargs["validValues"] = None kargs["suggValues"] = None - PrefVar.__init__(self, - name = name, - category = category, - defValue = bool(defValue), - **kargs - ) + BasePrefVar.__init__(self, + name = name, + category = category, + defValue = bool(defValue), + **kargs + ) def getEditWdg(self, master, var=None, ctxConfigFunc=None): """Return a Tkinter widget that allows the user to edit the value of the preference variable. @@ -584,7 +586,7 @@ def asStr(self, rawValue): return 'False' -class IntPrefVar(PrefVar): +class IntPrefVar(BasePrefVar): """An integer-valued PrefVar. Inputs: same as PrefVar plus: @@ -607,13 +609,13 @@ def __init__(self, kargs.setdefault("cnvFunc", RO.CnvUtil.asInt) - PrefVar.__init__(self, - name = name, - category = category, - defValue = defValue, - formatStr = formatStr, - **kargs - ) + BasePrefVar.__init__(self, + name = name, + category = category, + defValue = defValue, + formatStr = formatStr, + **kargs + ) def locCheckValue(self, value): """Raise a ValueError exception if the value is out of range. @@ -656,7 +658,7 @@ def getRangeStr(self): return ("[" + self.formatStr + ", " + self.formatStr + "]") % (self.minValue, self.maxValue) -class FloatPrefVar(PrefVar): +class FloatPrefVar(BasePrefVar): """A float-valued PrefVar. Inputs: same as PrefVar plus: @@ -682,13 +684,13 @@ def __init__(self, kargs.setdefault("cnvFunc", RO.CnvUtil.asFloat) - PrefVar.__init__(self, - name = name, - category = category, - defValue = defValue, - formatStr = formatStr, - **kargs - ) + BasePrefVar.__init__(self, + name = name, + category = category, + defValue = defValue, + formatStr = formatStr, + **kargs + ) def locCheckValue(self, value): """Raise a ValueError exception if the value is out of range. @@ -760,7 +762,7 @@ def setColor(self, *args): theColorUpdater = ColorUpdate() -class ColorPrefVar(PrefVar): +class ColorPrefVar(BasePrefVar): """Tk color preference variable. Inputs: same as PrefVar, plus: @@ -781,12 +783,12 @@ def __init__(self, kargs["formatStr"] = "%s" kargs["cnvFunc"] = str - PrefVar.__init__(self, - name = name, - category = category, - defValue = defValue, - **kargs - ) + BasePrefVar.__init__(self, + name = name, + category = category, + defValue = defValue, + **kargs + ) if wdgOption: global theColorUpdater theColorUpdater.addVar(wdgOption, self) @@ -800,7 +802,7 @@ def locCheckValue(self, value): except tkinter.TclError as e: raise ValueError(RO.StringUtil.strFromException(e)) -class FontPrefVar(PrefVar): +class FontPrefVar(BasePrefVar): """Tk Font preference variable. Inputs: same as PrefVar, plus: @@ -875,12 +877,12 @@ def __init__(self, netDefValue.update(defValue) self.value = {} - PrefVar.__init__(self, - name = name, - category = category, - defValue = netDefValue, - **kargs - ) + BasePrefVar.__init__(self, + name = name, + category = category, + defValue = netDefValue, + **kargs + ) # if optionPatterns supplied, add font to option database for ptn in optionPatterns: @@ -941,7 +943,7 @@ def asSummary(self, rawValue): charList.append(charName) return " ".join(charList) -class FontSizePrefVar(PrefVar): +class FontSizePrefVar(BasePrefVar): """Tk Font preference variable that controls only the size. This is useful for graphical elements that you want to display using the default font @@ -998,12 +1000,12 @@ def __init__(self, self.locCheckValue(defValue) netDefValue = defValue - PrefVar.__init__(self, - name = name, - category = category, - defValue = netDefValue, - **kargs - ) + BasePrefVar.__init__(self, + name = name, + category = category, + defValue = netDefValue, + **kargs + ) # if optionPatterns supplied, add font to option database for ptn in optionPatterns: @@ -1226,7 +1228,7 @@ def __getFileName(self, fileName=None): def callFunc(value, prefVar): print("callFunc called with value=%r, prefVar='%s'" % (value, prefVar)) - pv = PrefVar( + pv = BasePrefVar( name="basicPref", category="main", defValue=0, diff --git a/python/RO/Prefs/PrefWdg.py b/python/RO/Prefs/PrefWdg.py index 05a1580..b607246 100755 --- a/python/RO/Prefs/PrefWdg.py +++ b/python/RO/Prefs/PrefWdg.py @@ -38,10 +38,12 @@ __all__ = ["PrefWin", "PrefWdg"] import tkinter -from . import PrefVar -from . import PrefEditor + import RO.Constants import RO.Wdg +from . import PrefEditor +from . import PrefVar + class PrefWin(RO.Wdg.Toplevel): def __init__(self, diff --git a/python/RO/ScriptRunner.py b/python/RO/ScriptRunner.py index e02d88b..a345aa7 100755 --- a/python/RO/ScriptRunner.py +++ b/python/RO/ScriptRunner.py @@ -90,10 +90,11 @@ """ __all__ = ["ScriptError", "ScriptRunner"] +import queue import sys import threading -import queue import traceback + import RO.AddCallback import RO.Constants import RO.KeyVariable diff --git a/python/RO/SeqUtil.py b/python/RO/SeqUtil.py index a7d566c..eb72b1b 100755 --- a/python/RO/SeqUtil.py +++ b/python/RO/SeqUtil.py @@ -31,8 +31,10 @@ 2010-06-28 ROwen Modified to require Python 2.4 by assuming set is a builtin type. """ import collections + import RO.MathUtil + def asCollection(item): """Convert one or more items to a Collection. If item is Collection, returns it unchanged, diff --git a/python/RO/StringUtil.py b/python/RO/StringUtil.py index a7e5859..987fec0 100755 --- a/python/RO/StringUtil.py +++ b/python/RO/StringUtil.py @@ -52,13 +52,14 @@ 2015-11-05 ROwen Stop using dangerous bare "except:". """ import re + import numpy -AngstromStr = "\N{ANGSTROM SIGN}" -DegStr = "\N{DEGREE SIGN}" +AngstromStr = u"\N{ANGSTROM SIGN}" +DegStr = u"\N{DEGREE SIGN}" DMSStr = DegStr + "'\"" LambdaStr = "\u00c5" # for some reason this fails: u"\N{GREEK SMALL LETTER LAMBDA}" -MuStr = "\N{GREEK SMALL LETTER MU}" +MuStr = u"\N{GREEK SMALL LETTER MU}" def dmsStrFromDeg (decDeg, nFields=3, precision=1, omitExtraFields = False): """Convert a number to a sexagesimal string with 1-3 fields. @@ -335,7 +336,18 @@ def prettyDict(aDict, entrySepStr = "\n", keyValSepStr = ": "): Returns a string containing the pretty-printed dictionary """ sortedKeys = list(aDict.keys()) - sortedKeys.sort() + # Python 3 doesn't support sort for lists, so this needs to be done by hand + ints = [] + strs = [] + for key in sortedKeys: + if isinstance(key, (int, float)): + ints.append(key) + ints.sort() + for key in sortedKeys: + if isinstance(key, str): + strs.append(key) + strs.sort() + sortedKeys = ints + strs eltList = [] for aKey in sortedKeys: eltList.append(repr(aKey) + keyValSepStr + repr(aDict[aKey])) diff --git a/python/RO/TkUtil.py b/python/RO/TkUtil.py index 31ce185..04fe776 100755 --- a/python/RO/TkUtil.py +++ b/python/RO/TkUtil.py @@ -27,8 +27,9 @@ import re import sys -import traceback import tkinter +import traceback + import RO.OS # windowing system constants diff --git a/python/RO/Wdg/BalloonHelp.py b/python/RO/Wdg/BalloonHelp.py index eecbc82..5847cb4 100755 --- a/python/RO/Wdg/BalloonHelp.py +++ b/python/RO/Wdg/BalloonHelp.py @@ -16,6 +16,7 @@ __all__ = ['enableBalloonHelp'] import tkinter + from RO.TkUtil import Timer _HelpObj = None @@ -126,9 +127,9 @@ def enableBalloonHelp(delayMS = 1000): if __name__ == '__main__': from .OptionMenu import OptionMenu - root = Tkinter.Tk() + root = tkinter.Tk() - l0 = Tkinter.Label(text="Data") + l0 = tkinter.Label(text="Data") l0.grid(row=0, column=0, sticky="e") l0.helpText = "Help for the Data label" e0 = tkinter.Entry(width=10) @@ -148,6 +149,6 @@ def enableBalloonHelp(delayMS = 1000): ) m2.grid(row=2, column=1) - ph = enableBalloonHelp() + enableBalloonHelp() root.mainloop() diff --git a/python/RO/Wdg/Bindings.py b/python/RO/Wdg/Bindings.py index 15237a0..21acde8 100755 --- a/python/RO/Wdg/Bindings.py +++ b/python/RO/Wdg/Bindings.py @@ -44,8 +44,10 @@ __all__ = ['makeReadOnly', 'stdBindings', 'stopEvent'] import tkinter + import RO.TkUtil + def doQuit(evt): evt.widget.quit() diff --git a/python/RO/Wdg/Button.py b/python/RO/Wdg/Button.py index 8d4ff7c..3332b8f 100644 --- a/python/RO/Wdg/Button.py +++ b/python/RO/Wdg/Button.py @@ -22,12 +22,14 @@ __all__ = ['Button', 'Radiobutton'] import tkinter + import RO.AddCallback import RO.Constants import RO.TkUtil -from .CtxMenu import CtxMenu, CtxMenuMixin +from .CtxMenu import CtxMenuMixin from .SeverityMixin import SeverityActiveMixin + class Button(tkinter.Button, RO.AddCallback.TkButtonMixin, CtxMenuMixin, SeverityActiveMixin): def __init__(self, master, diff --git a/python/RO/Wdg/ChangedIndicator.py b/python/RO/Wdg/ChangedIndicator.py index 404e6d6..bb1ee82 100644 --- a/python/RO/Wdg/ChangedIndicator.py +++ b/python/RO/Wdg/ChangedIndicator.py @@ -17,9 +17,11 @@ __all__ = ['ChangedIndicator'] import tkinter + import RO.SeqUtil from .CtxMenu import CtxMenuMixin + class ChangedIndicator (tkinter.Label, CtxMenuMixin): def __init__(self, master, diff --git a/python/RO/Wdg/Checkbutton.py b/python/RO/Wdg/Checkbutton.py index 1eb76e6..1d91af4 100755 --- a/python/RO/Wdg/Checkbutton.py +++ b/python/RO/Wdg/Checkbutton.py @@ -73,6 +73,7 @@ __all__ = ['Checkbutton'] import tkinter + import RO.AddCallback import RO.CnvUtil import RO.MathUtil @@ -81,6 +82,7 @@ from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentCheckbuttonMixin from .SeverityMixin import SeverityActiveMixin + class Checkbutton (tkinter.Checkbutton, RO.AddCallback.TkVarMixin, AutoIsCurrentMixin, IsCurrentCheckbuttonMixin, SeverityActiveMixin, CtxMenuMixin): """A Checkbutton with callback, help, isCurrent and severity support. @@ -389,9 +391,9 @@ def _computeCorrectedWidth(self, width, hasBitmap, showIndicator): if __name__ == "__main__": - from . import PythonTk + from .PythonTk import PythonTk from .StatusBar import StatusBar - root = PythonTk.PythonTk() + root = PythonTk() def btnCallback(btn): print("%s state=%s" % (btn["text"], btn.getBool())) diff --git a/python/RO/Wdg/CmdWdg.py b/python/RO/Wdg/CmdWdg.py index 9183f46..390f22b 100755 --- a/python/RO/Wdg/CmdWdg.py +++ b/python/RO/Wdg/CmdWdg.py @@ -29,8 +29,10 @@ __all__ = ['CmdWdg'] import tkinter + from . import Entry + class CmdWdg (Entry.StrEntry): """Entry field for one-line text commands, with history. diff --git a/python/RO/Wdg/CtxMenu.py b/python/RO/Wdg/CtxMenu.py index a2baff9..60a1e7a 100755 --- a/python/RO/Wdg/CtxMenu.py +++ b/python/RO/Wdg/CtxMenu.py @@ -48,10 +48,12 @@ __all__ = ['CtxMenu', 'CtxMenuMixin', 'addCtxMenu'] import tkinter + import RO.Comm.BrowseURL import RO.Constants import RO.OS + class CtxMenu(object): def __init__(self, wdg=None, @@ -208,8 +210,8 @@ def addCtxMenu( if __name__ == "__main__": from . import Bindings - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() # set up standard binding for <> Bindings.stdBindings(root) diff --git a/python/RO/Wdg/DropletApp.py b/python/RO/Wdg/DropletApp.py index 762c272..b945bea 100755 --- a/python/RO/Wdg/DropletApp.py +++ b/python/RO/Wdg/DropletApp.py @@ -44,12 +44,14 @@ __all__ = ["DropletApp"] import sys -import traceback import tkinter -import RO.OS +import traceback + import RO.Constants +import RO.OS from RO.TkUtil import Timer -from . import LogWdg +from .LogWdg import LogWdg + class DropletApp(tkinter.Frame): """Run an application as a droplet (an application onto which you drop files) @@ -110,7 +112,7 @@ def __init__(self, self.processDirs = bool(processDirs) self.doneMsg = doneMsg + "\n" - self.logWdg = LogWdg.LogWdg( + self.logWdg = LogWdg( master = self, width = width, height = height, diff --git a/python/RO/Wdg/DropletRunner.py b/python/RO/Wdg/DropletRunner.py index c8ab445..8e7675d 100755 --- a/python/RO/Wdg/DropletRunner.py +++ b/python/RO/Wdg/DropletRunner.py @@ -59,14 +59,16 @@ """ __all__ = ["DropletRunner"] -import sys import os.path import subprocess +import sys import tkinter -import RO.OS + import RO.Constants +import RO.OS from RO.TkUtil import Timer -from . import LogWdg +from .LogWdg import LogWdg + class DropletRunner(object): """Run a script as a droplet (an application onto which you drop file) with a log window. @@ -109,7 +111,7 @@ def __init__(self, scriptPath, title=None, initialText=None, **keyArgs): else: filePathList = sys.argv[1:] - self.logWdg = LogWdg.LogWdg(self.tkRoot, **keyArgs) + self.logWdg = LogWdg(self.tkRoot, **keyArgs) self.logWdg.grid(row=0, column=0, sticky="nsew") self.tkRoot.grid_rowconfigure(0, weight=1) self.tkRoot.grid_columnconfigure(0, weight=1) diff --git a/python/RO/Wdg/Entry.py b/python/RO/Wdg/Entry.py index 63f960f..429c52b 100755 --- a/python/RO/Wdg/Entry.py +++ b/python/RO/Wdg/Entry.py @@ -163,19 +163,27 @@ """ __all__ = ['StrEntry', 'ASCIIEntry', 'FloatEntry', 'IntEntry', 'DMSEntry'] -#import os +# import os import re import tkinter + +# import os +import RO.AddCallback import RO.AddCallback import RO.CnvUtil +import RO.CnvUtil +import RO.MathUtil +import RO.MathUtil +import RO.SeqUtil import RO.SeqUtil import RO.StringUtil -import RO.MathUtil +import RO.StringUtil from . import Bindings from .CtxMenu import CtxMenuMixin from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentMixin from .SeverityMixin import SeveritySelectMixin + class _BaseEntry (tkinter.Entry, RO.AddCallback.BaseMixin, AutoIsCurrentMixin, IsCurrentMixin, SeveritySelectMixin, CtxMenuMixin): """Base class for RO.Wdg entry widgets. @@ -1519,7 +1527,7 @@ def _optionKeyPress(self, evt): if __name__ == "__main__": from RO.Wdg.PythonTk import PythonTk - from . import StatusBar + from .StatusBar import StatusBar root = PythonTk() entryList = [] @@ -1583,7 +1591,7 @@ def setDeg(*args): degButton = tkinter.Button (root, command=setDeg, text="DMS in deg") degButton.pack() - statusBar = StatusBar.StatusBar(root) + statusBar = StatusBar(root) addEntry ( "StrEntry AutoIsCurr", diff --git a/python/RO/Wdg/FTPLogWdg.py b/python/RO/Wdg/FTPLogWdg.py index fd323ba..084957f 100755 --- a/python/RO/Wdg/FTPLogWdg.py +++ b/python/RO/Wdg/FTPLogWdg.py @@ -55,16 +55,17 @@ import atexit import sys +import tkinter import traceback import weakref -from . import Bindings -import tkinter + import RO.AddCallback import RO.Constants import RO.MathUtil -from RO.TkUtil import Timer -from RO.Comm.FTPGet import FTPGet import RO.Wdg +from RO.Comm.FTPGet import FTPGet +from RO.TkUtil import Timer +from . import Bindings from .CtxMenu import addCtxMenu _StatusInterval = 0.200 # time between status checks (sec) diff --git a/python/RO/Wdg/GrayImageDispWdg.py b/python/RO/Wdg/GrayImageDispWdg.py index c8aaa6f..d6effdd 100755 --- a/python/RO/Wdg/GrayImageDispWdg.py +++ b/python/RO/Wdg/GrayImageDispWdg.py @@ -172,12 +172,15 @@ by casting image shape to a tuple when calling fromBuffer. 2020-02-10 DGatlin Modified imports for Python 3 """ -__all__ = ["ann_Circle", "ann_Plus", "ann_X", "ann_Line", "ann_Text", "MaskInfo", "GrayImageWdg"] +__all__ = ["ann_Circle", "ann_Plus", "ann_X", "ann_Line", "ann_Text", + "MaskInfo", "GrayImageWdg"] -import weakref -import tkinter import math +import tkinter +import weakref + import numpy + try: import numpy.ma as ma except ImportError: @@ -192,8 +195,8 @@ import RO.TkUtil from . import Entry from .Label import StrLabel, FloatLabel -from . import OptionMenu -from . import RadiobuttonSet +from .OptionMenu import OptionMenu +from .RadiobuttonSet import RadiobuttonSet _AnnTag = "_gs_ann_" _DragRectTag = "_gs_dragRect" @@ -211,6 +214,7 @@ ann_X = RO.CanvasUtil.ctrX ann_Line = RO.CanvasUtil.radialLine + def ann_Text(cnv, xpos, ypos, rad, text, anchor="c", **kargs): """Draws a centered circle on the specified canvas. @@ -225,6 +229,7 @@ def ann_Text(cnv, xpos, ypos, rad, text, anchor="c", **kargs): """ cnv.create_text(xpos, ypos, text=text, anchor=anchor, **kargs) + def getBitmapDict(): bitmapDir = RO.OS.getResourceDir(RO, "Bitmaps") modeDict = { @@ -237,8 +242,10 @@ def getBitmapDict(): retDict[mode] = "@%s.xbm" % os.path.join(bitmapDir, bitmapName) return retDict + _BitmapDict = getBitmapDict() + class MaskInfo(object): """Information about a mask plane @@ -253,17 +260,18 @@ class MaskInfo(object): in the intensity stretch calculation """ tkWdg = None + def __init__(self, - bitInd, - name, - btext, - color, - intens = 75, - doShow = True, - doStretch = True, - ): + bitInd, + name, + btext, + color, + intens=75, + doShow=True, + doStretch=True, + ): self.bitInd = int(bitInd) - self.andVal = 2**bitInd + self.andVal = 2 ** bitInd self.name = name self.btext = btext self.intens = int(intens) @@ -310,7 +318,7 @@ def setWdg(self, wdg): def setColor(self, color): """Set the mask color""" - self.maskRGB = [val/256 for val in self.tkWdg.winfo_rgb(color)] + self.maskRGB = [val / 256 for val in self.tkWdg.winfo_rgb(color)] self.color = color @@ -345,15 +353,16 @@ class Annotation(object): and a unique id tag will also be used as tags. **kargs arguments for annType """ + def __init__(self, - gim, - annType, - imPos, - rad, - cnvOffset = (0, 0), - isImSize = True, - tags = None, - **kargs): + gim, + annType, + imPos, + rad, + cnvOffset=(0, 0), + isImSize=True, + tags=None, + **kargs): self.gim = gim self.annType = annType @@ -396,24 +405,26 @@ def draw(self): # radius is in image units; adjust for zoom factor rad = int(round(self.rad * self.gim.zoomFac)) if self.holeRad is not None: - self.kargs["holeRad"] = int(round(self.holeRad * self.gim.zoomFac)) + self.kargs["holeRad"] = int( + round(self.holeRad * self.gim.zoomFac)) else: # radius is already in canvas units; leave it alone rad = self.rad -# print "cnvPos=%s; draw at=%s" % (cnvPos, (cnvPos[0] + self.cnvOffset[0], cnvPos[1] + self.cnvOffset[1])) + # print "cnvPos=%s; draw at=%s" % (cnvPos, (cnvPos[0] + self.cnvOffset[0], cnvPos[1] + self.cnvOffset[1])) return self.annType( self.gim.cnv, cnvPos[0] + self.cnvOffset[0], cnvPos[1] + self.cnvOffset[1], rad, - **self.kargs) + **self.kargs) def delete(self): """Delete the annotation from the canvas. """ self.gim.cnv.delete(self.idTag) + class GrayImageWdg(tkinter.Frame, RO.AddCallback.BaseMixin): """Display a grayscale image. @@ -430,16 +441,20 @@ class GrayImageWdg(tkinter.Frame, RO.AddCallback.BaseMixin): "100%", "99.9%", "99.8%", "99.7%", "99.6%", "99.5%", "99%" kargs any other keyword arguments are passed to Tkinter.Frame """ - _RangeMenuItems = ("100%", "99.9%", "99.8%", "99.7%", "99.6%", "99.5%", "99%", "98%", "97%", "96%", "95%") + _RangeMenuItems = ( + "100%", "99.9%", "99.8%", "99.7%", "99.6%", "99.5%", "99%", "98%", + "97%", + "96%", "95%") + def __init__(self, - master, - height = 300, - width = 300, - helpURL = None, - maskInfo = None, - callFunc = None, - defRange = "99.9%", - **kargs): + master, + height=300, + width=300, + helpURL=None, + maskInfo=None, + callFunc=None, + defRange="99.9%", + **kargs): tkinter.Frame.__init__(self, master, **kargs) RO.AddCallback.BaseMixin.__init__(self) if defRange not in self._RangeMenuItems: @@ -453,18 +468,19 @@ def __init__(self, self.dataDispMax = None # scaled data array and attributes - self.scaledArr = None # must be float32; Image doesn't support float64! + self.scaledArr = None # must be float32; Image doesn't support float64! self.scaledIm = None self.scaleFuncOff = 0.0 self.scaleFunc = None # displayed image attributes self.zoomFac = None - self.begIJ = None # start of data subregion to display - self.endIJ = None # end of data subregion to display + self.begIJ = None # start of data subregion to display + self.endIJ = None # end of data subregion to display self.dispOffset = 0 self.dispScale = 1.0 - self.frameShape = (width, height) # shape of area in which image can be displayed + self.frameShape = ( + width, height) # shape of area in which image can be displayed if maskInfo: maskInfo = RO.SeqUtil.asSequence(maskInfo) @@ -499,24 +515,24 @@ def __init__(self, # tool bar toolFrame = tkinter.Frame(self) - self.scaleMenuWdg = OptionMenu.OptionMenu( - master = toolFrame, - items = ("Linear", "ASinh 0.01", "ASinh 0.1", "ASinh 1"), - defValue = "Linear", - width = 8, - callFunc = self.doScaleMenu, - helpText = "scaling function", - helpURL = helpURL, + self.scaleMenuWdg = OptionMenu( + master=toolFrame, + items=("Linear", "ASinh 0.01", "ASinh 0.1", "ASinh 1"), + defValue="Linear", + width=8, + callFunc=self.doScaleMenu, + helpText="scaling function", + helpURL=helpURL, ) - self.scaleMenuWdg.pack(side = "left") - self.rangeMenuWdg = OptionMenu.OptionMenu( - master = toolFrame, - items = self._RangeMenuItems, - defValue = defRange, - width = 5, - callFunc = self.doRangeMenu, - helpText = "data range", - helpURL = helpURL, + self.scaleMenuWdg.pack(side="left") + self.rangeMenuWdg = OptionMenu( + master=toolFrame, + items=self._RangeMenuItems, + defValue=defRange, + width=5, + callFunc=self.doRangeMenu, + helpText="data range", + helpURL=helpURL, ) self.rangeMenuWdg.pack(side="left") @@ -526,32 +542,32 @@ def __init__(self, _ModeZoom, ) bitmapList = [_BitmapDict[md] for md in modeList] - self.modeWdg = RadiobuttonSet.RadiobuttonSet( - master = toolFrame, - bitmapList = bitmapList, - valueList = modeList, - helpText = ( + self.modeWdg = RadiobuttonSet( + master=toolFrame, + bitmapList=bitmapList, + valueList=modeList, + helpText=( "Default mode", "Drag to adjust black and white levels (or middle-click & drag)", "Drag to zoom (or right-click and drag)", ), - helpURL = helpURL, - height = 18, - width = 18, - indicatoron = False, - callFunc = self.setMode, - side = "left", + helpURL=helpURL, + height=18, + width=18, + indicatoron=False, + callFunc=self.setMode, + side="left", ) wdgSet = self.modeWdg.getWdgSet() self.currZoomWdg = Entry.FloatEntry( - master = toolFrame, - width = 4, - defFormat = "%.2f", - defValue = 1.0, - defMenu = "default", - helpText = "Zoom factor", - helpURL = helpURL, + master=toolFrame, + width=4, + defFormat="%.2f", + defValue=1.0, + defMenu="default", + helpText="Zoom factor", + helpURL=helpURL, ) self.currZoomWdg.set(self.zoomFac) self.currZoomWdg.pack(side="left") @@ -562,11 +578,11 @@ def __init__(self, if self.maskInfo: for mInfo in self.maskInfo: maskWdg = RO.Wdg.Checkbutton( - master = toolFrame, - text = mInfo.btext, - defValue = mInfo.doShow, - callFunc = self.doShowHideMask, - helpText = "Show/hide %s" % (mInfo.name,), + master=toolFrame, + text=mInfo.btext, + defValue=mInfo.doShow, + callFunc=self.doShowHideMask, + helpText="Show/hide %s" % (mInfo.name,), ) mInfo.setWdg(maskWdg) maskWdg.pack(side="left") @@ -578,59 +594,60 @@ def __init__(self, posFrame = tkinter.Frame(self) StrLabel( posFrame, - text = " Cursor Pos: ", - bd = 0, - padx = 0, - helpText = "Cursor position (pix)", - helpURL = helpURL, + text=" Cursor Pos: ", + bd=0, + padx=0, + helpText="Cursor position (pix)", + helpURL=helpURL, ).pack(side="left") self.currXPosWdg = FloatLabel( posFrame, - width = 6, - precision = 1, - bd = 0, - padx = 0, - helpText = "Cursor X position (pix)", - helpURL = helpURL, + width=6, + precision=1, + bd=0, + padx=0, + helpText="Cursor X position (pix)", + helpURL=helpURL, ) self.currXPosWdg.pack(side="left") StrLabel( posFrame, text=",", - bd = 0, - padx = 0, + bd=0, + padx=0, ).pack(side="left") self.currYPosWdg = FloatLabel( posFrame, - width = 6, - precision = 1, - bd = 0, - padx = 0, - helpText = "Cursor Y position (pix)", - helpURL = helpURL, + width=6, + precision=1, + bd=0, + padx=0, + helpText="Cursor Y position (pix)", + helpURL=helpURL, ) self.currYPosWdg.pack(side="left") StrLabel( posFrame, - text = " Value: ", - bd = 0, - padx = 0, - helpText = "Value at cursor (ADUs)", - helpURL = helpURL, + text=" Value: ", + bd=0, + padx=0, + helpText="Value at cursor (ADUs)", + helpURL=helpURL, ).pack(side="left") self.currValWdg = FloatLabel( posFrame, - bd = 0, - padx = 0, - precision = 1, - helpText = "Value at cursor (ADUs)", - helpURL = helpURL, + bd=0, + padx=0, + precision=1, + helpText="Value at cursor (ADUs)", + helpURL=helpURL, ) self.currValWdg.pack(side="left") posFrame.pack(side="bottom", anchor="nw") # set up scrolling panel to display canvas and error messages - self.scrollFrame = tkinter.Frame(self, height=height, width=width) #, borderwidth=2, relief="sunken") + self.scrollFrame = tkinter.Frame(self, height=height, + width=width) # , borderwidth=2, relief="sunken") self.scrollFrame.grid_propagate(False) self.strMsgWdg = StrLabel(self.scrollFrame) self.strMsgWdg.grid(row=0, column=0) @@ -639,8 +656,8 @@ def __init__(self, self.hsb = tkinter.Scrollbar( self.scrollFrame, orient="horizontal", - width = 10, - command = RO.Alg.GenericCallback(self.doScrollBar, 1), + width=10, + command=RO.Alg.GenericCallback(self.doScrollBar, 1), ) self.hsb.grid(row=1, column=0, sticky="ew") self._hscrollbar = self.hsb @@ -649,20 +666,20 @@ def __init__(self, self.vsb = tkinter.Scrollbar( self.scrollFrame, orient="vertical", - width = 10, - command = RO.Alg.GenericCallback(self.doScrollBar, 0), + width=10, + command=RO.Alg.GenericCallback(self.doScrollBar, 0), ) self.vsb.grid(row=0, column=1, sticky="ns") self.vsb.set(0.0, 1.0) self.cnv = tkinter.Canvas( - master = self.scrollFrame, -# cursor="tcross", - bd = 0, - selectborderwidth = 0, - highlightthickness = 0, + master=self.scrollFrame, + # cursor="tcross", + bd=0, + selectborderwidth=0, + highlightthickness=0, ) - self.cnv.grid(row=0, column=0) #, sticky="nsew") + self.cnv.grid(row=0, column=0) # , sticky="nsew") self.scrollFrame.grid_rowconfigure(0, weight=1) self.scrollFrame.grid_columnconfigure(0, weight=1) @@ -670,10 +687,11 @@ def __init__(self, self.scrollFrame.pack(side="top", expand=True, fill="both") bdWidth = 0 - for bdName in ("borderwidth", "selectborderwidth", "highlightthickness"): + for bdName in ( + "borderwidth", "selectborderwidth", "highlightthickness"): bdWidth += int(self.cnv[bdName]) self.bdWidth = bdWidth - self.cnvShape = (0,0) + self.cnvShape = (0, 0) # set up bindings self.cnv.bind("", self._updCurrVal) @@ -719,12 +737,13 @@ def setMode(self, wdg=None, isTemp=False): self.permMode = self.mode self.mode = self.modeWdg.getString() -# if self.mode == _ModeZoom: -# self.cnv["cursor"] = "icon" -# elif self.mode == _ModeLevels: -# self.cnv["cursor"] = "circle" -# elif self.mode == _ModeNormal: -# self.cnv["cursor"] = "tcross" + + # if self.mode == _ModeZoom: + # self.cnv["cursor"] = "icon" + # elif self.mode == _ModeLevels: + # self.cnv["cursor"] = "circle" + # elif self.mode == _ModeNormal: + # self.cnv["cursor"] = "tcross" def modeStart(self, evt): """Mouse down for current mode (whatever that might be). @@ -732,9 +751,9 @@ def modeStart(self, evt): if self.mode == _ModeNormal: return elif self.mode == _ModeZoom: - self.dragZoomStart(evt, isTemp = False) + self.dragZoomStart(evt, isTemp=False) elif self.mode == _ModeLevels: - self.dragLevelStart(evt, isTemp = False) + self.dragLevelStart(evt, isTemp=False) def modeContinue(self, evt): if self.mode == _ModeNormal: @@ -748,19 +767,20 @@ def modeEnd(self, evt): if self.mode == _ModeNormal: return elif self.mode == _ModeZoom: - self.dragZoomEnd(evt, isTemp = False) + self.dragZoomEnd(evt, isTemp=False) elif self.mode == _ModeLevels: - self.dragLevelEnd(evt, isTemp = False) + self.dragLevelEnd(evt, isTemp=False) def modeReset(self, evt): if self.mode == _ModeNormal: return elif self.mode == _ModeZoom: - self.dragZoomReset(isTemp = False) + self.dragZoomReset(isTemp=False) elif self.mode == _ModeLevels: - self.dragLevelReset(isTemp = False) + self.dragLevelReset(isTemp=False) - def addAnnotation(self, annType, imPos, rad, cnvOffset=(0, 0), tags=None, isImSize=True, **kargs): + def addAnnotation(self, annType, imPos, rad, cnvOffset=(0, 0), tags=None, + isImSize=True, **kargs): """Add an annotation. Inputs: @@ -792,14 +812,14 @@ def addAnnotation(self, annType, imPos, rad, cnvOffset=(0, 0), tags=None, isImSi return annObj = Annotation( - gim = self, - annType = annType, - imPos = imPos, - rad = rad, - cnvOffset = cnvOffset, - tags = tags, - isImSize = isImSize, - **kargs) + gim=self, + annType=annType, + imPos=imPos, + rad=rad, + cnvOffset=cnvOffset, + tags=tags, + isImSize=isImSize, + **kargs) self.annDict[annObj.tags] = annObj return annObj.idTag @@ -819,7 +839,7 @@ def applyRange(self, redisplay=True): self.dispScale = (self.dispMaxLevel - self.dispMinLevel) / dispRange self.dispOffset = self.dispMinLevel * float(self.dispScale) + minDisp - #print "applyRange(%r); dispMinLevel=%s, dispMaxLevel=%s, dispOffset=%r; dispScale=%r" % (redisplay, self.dispMinLevel, self.dispMaxLevel, self.dispOffset, self.dispScale) + # print "applyRange(%r); dispMinLevel=%s, dispMaxLevel=%s, dispOffset=%r; dispScale=%r" % (redisplay, self.dispMinLevel, self.dispMaxLevel, self.dispOffset, self.dispScale) currIm = self.scaledIm.point(self._dispFromScaled) if self.scaledMask: @@ -860,7 +880,7 @@ def doRangeMenu(self, wdg=None, redisplay=True): return strVal = self.rangeMenuWdg.getString() - numVal = float(strVal[:-1]) / 100.0 # ignore % from end + numVal = float(strVal[:-1]) / 100.0 # ignore % from end lowFrac = (1.0 - numVal) / 2.0 highFrac = 1.0 - lowFrac dataLen = len(self.sortedData) @@ -869,7 +889,7 @@ def doRangeMenu(self, wdg=None, redisplay=True): self.dataDispMin = self.sortedData[lowInd] self.dataDispMax = self.sortedData[highInd] - #print "doRangeMenu; strVal=%r; numVal=%s; lowFrac=%s; highFrac=%s, dataLen=%s, lowInd=%s, highInd=%s, dataDispMin=%s, dataDispMax=%s" % (strVal, numVal, lowFrac, highFrac, dataLen, lowInd, highInd, self.dataDispMin, self.dataDispMax) + # print "doRangeMenu; strVal=%r; numVal=%s; lowFrac=%s; highFrac=%s, dataLen=%s, lowInd=%s, highInd=%s, dataDispMin=%s, dataDispMax=%s" % (strVal, numVal, lowFrac, highFrac, dataLen, lowInd, highInd, self.dataDispMin, self.dataDispMax) if redisplay: self.redisplay() @@ -892,7 +912,7 @@ def doScaleMenu(self, *dumArgs): def doScrollBar(self, ijInd, scrollCmd, scrollAmt=None, c=None): """Handle scroll bar events""" - #print "doScrollBarijInd=%r, scrollCmd=%r, scrollAmt=%r, c=%r)" % (ijInd, scrollCmd, scrollAmt, c) + # print "doScrollBarijInd=%r, scrollCmd=%r, scrollAmt=%r, c=%r)" % (ijInd, scrollCmd, scrollAmt, c) if scrollAmt is None or self.dataArr is None: return sbWdg = (self.vsb, self.hsb)[ijInd] @@ -902,7 +922,6 @@ def doScrollBar(self, ijInd, scrollCmd, scrollAmt=None, c=None): if visFrac > 1.0: print("doScrollBar warning: visFrac = %r >1" % (visFrac,)) - if scrollCmd == "scroll": multFac = int(scrollAmt) newScroll = currScroll + (multFac * (visFrac / 2.0)) @@ -913,7 +932,7 @@ def doScrollBar(self, ijInd, scrollCmd, scrollAmt=None, c=None): print("doScrollBar error: unknown scroll command=%r" % (scrollCmd,)) return - #print "currScroll=%r, newScroll=%r" % (currScroll, newScroll) + # print "currScroll=%r, newScroll=%r" % (currScroll, newScroll) # apply ranges if newScroll[1] > 1.0: @@ -924,7 +943,7 @@ def doScrollBar(self, ijInd, scrollCmd, scrollAmt=None, c=None): if ijInd == 0: temp = newScroll[:] newScroll = [1.0 - elt for elt in temp[::-1]] - #print "fixing newScroll %r - >%r" % (temp, newScroll) + # print "fixing newScroll %r - >%r" % (temp, newScroll) self.begIJ[ijInd] = self.dataArr.shape[ijInd] * newScroll[0] self.endIJ[ijInd] = self.dataArr.shape[ijInd] * newScroll[1] @@ -947,11 +966,11 @@ def dragLevelContinue(self, evt): if self.dataArr is None: return - #print "cnvShape=%s, evt.x=%s, evt.y=%s" % (self.cnvShape, evt.x, evt.y) - ctr = [sh/2.0 for sh in self.cnvShape] + # print "cnvShape=%s, evt.x=%s, evt.y=%s" % (self.cnvShape, evt.x, evt.y) + ctr = [sh / 2.0 for sh in self.cnvShape] dx = evt.x - ctr[0] dy = ctr[1] - evt.y - #print "ctr=%s, dx=%s, dy=%s" % (ctr, dx, dy) + # print "ctr=%s, dx=%s, dy=%s" % (ctr, dx, dy) self.dispMinLevel = 0 + dx self.dispMaxLevel = 256 + dy self.applyRange(redisplay=True) @@ -981,7 +1000,8 @@ def dragZoomContinue(self, evt): return newPos = self.cnvPosFromEvt(evt) - self.cnv.coords(self.dragRectID, self.dragStart[0], self.dragStart[1], newPos[0], newPos[1]) + self.cnv.coords(self.dragRectID, self.dragStart[0], self.dragStart[1], + newPos[0], newPos[1]) def dragZoomEnd(self, evt, isTemp=True): self.cnv.delete(self.dragRectID) @@ -1000,26 +1020,28 @@ def dragZoomEnd(self, evt, isTemp=True): return deltaPos = numpy.subtract(endPos, startPos) - ctrCnvPos = numpy.add(startPos, deltaPos/2.0) + ctrCnvPos = numpy.add(startPos, deltaPos / 2.0) if deltaPos[0] > 0 and deltaPos[1] > 0: # zoom in newZoomFac = _MaxZoomFac for ii in range(2): - desZoomFac = self.frameShape[ii] * self.zoomFac / float(max(1, abs(deltaPos[ii]))) + desZoomFac = self.frameShape[ii] * self.zoomFac / float( + max(1, abs(deltaPos[ii]))) newZoomFac = min(desZoomFac, newZoomFac) - #print "ii=%s, desZoomFac=%s; newZoomFac=%s" % (ii, desZoomFac, newZoomFac) - #print "newZoomFac=%s" % (newZoomFac,) + # print "ii=%s, desZoomFac=%s; newZoomFac=%s" % (ii, desZoomFac, newZoomFac) + # print "newZoomFac=%s" % (newZoomFac,) self.setZoomFac(newZoomFac, ctrCnvPos) elif deltaPos[0] < 0 and deltaPos[1] < 0: # zoom out newZoomFac = _MaxZoomFac for ii in range(2): - desZoomFac = abs(deltaPos[ii]) * self.zoomFac / float(self.frameShape[ii]) + desZoomFac = abs(deltaPos[ii]) * self.zoomFac / float( + self.frameShape[ii]) newZoomFac = min(desZoomFac, newZoomFac) - #print "ii=%s, desZoomFac=%s; newZoomFac=%s" % (ii, desZoomFac, newZoomFac) - #print "newZoomFac=%s; minZoomFac=%s" % (newZoomFac, self.getFitZoomFac()) + # print "ii=%s, desZoomFac=%s; newZoomFac=%s" % (ii, desZoomFac, newZoomFac) + # print "newZoomFac=%s; minZoomFac=%s" % (newZoomFac, self.getFitZoomFac()) newZoomFac = max(newZoomFac, self.getFitZoomFac()) self.setZoomFac(newZoomFac, ctrCnvPos) @@ -1039,9 +1061,10 @@ def dragZoomReset(self, wdg=None, isTemp=True): def dragZoomStart(self, evt, isTemp=True): self.dragStart = self.cnvPosFromEvt(evt) self.dragRectID = self.cnv.create_rectangle( - self.dragStart[0], self.dragStart[1], self.dragStart[0], self.dragStart[1], - outline = "green", - tags = _DragRectTag, + self.dragStart[0], self.dragStart[1], self.dragStart[0], + self.dragStart[1], + outline="green", + tags=_DragRectTag, ) if isTemp: @@ -1056,10 +1079,11 @@ def getFitZoomFac(self): return 1.0 frameShapeIJ = self.frameShape[::-1] - desZoomFac = [frameShapeIJ[ii] / float(self.dataArr.shape[ii]) for ii in (0,1)] + desZoomFac = [frameShapeIJ[ii] / float(self.dataArr.shape[ii]) for ii in + (0, 1)] fitZoomFac = min(desZoomFac) limZoomFac = limitZoomFac(fitZoomFac) - #print "getFitZoomFac: arrShape=%s, frameShapeIJ=%s, desZoomFac=%s, fitZoomFac=%s, limZoomFac=%s" % (self.dataArr.shape, frameShapeIJ, desZoomFac, fitZoomFac, limZoomFac) + # print "getFitZoomFac: arrShape=%s, frameShapeIJ=%s, desZoomFac=%s, fitZoomFac=%s, limZoomFac=%s" % (self.dataArr.shape, frameShapeIJ, desZoomFac, fitZoomFac, limZoomFac) return limZoomFac def isNormalMode(self): @@ -1081,16 +1105,20 @@ def redisplay(self): # offset so minimum display value = scaling function minimum input # reuse existing scaledArr memory if possible if self.scaledArr is None or self.scaledArr.shape != self.dataArr.shape: - self.scaledArr = numpy.subtract(self.dataArr, float(self.dataDispMin), dtype=numpy.float32) + self.scaledArr = numpy.subtract(self.dataArr, + float(self.dataDispMin), + dtype=numpy.float32) else: - numpy.subtract(self.dataArr, float(self.dataDispMin), self.scaledArr) + numpy.subtract(self.dataArr, float(self.dataDispMin), + self.scaledArr) offsetDispRange = [0.0, float(self.dataDispMax - self.dataDispMin)] # apply scaling function, if any if self.scaleFunc: self.scaleFunc(self.scaledArr, self.scaledArr) - scaledMin, scaledMax = self.scaleFunc(offsetDispRange).astype(float) + scaledMin, scaledMax = self.scaleFunc(offsetDispRange).astype( + float) else: scaledMin, scaledMax = offsetDispRange # linearly offset and stretch data so that @@ -1099,14 +1127,15 @@ def redisplay(self): # so the offset is superfluous) adjOffset = scaledMin adjScale = 256.0 / max((scaledMax - scaledMin), 1.0) - #print "apply adjOffset=%s; adjScale=%s" % (adjOffset, adjScale) + # print "apply adjOffset=%s; adjScale=%s" % (adjOffset, adjScale) self.scaledArr -= adjOffset self.scaledArr *= adjScale # reshape canvas, if necessary subFrameShapeIJ = numpy.subtract(self.endIJ, self.begIJ) subFrameShapeXY = subFrameShapeIJ[::-1] - cnvShapeXY = numpy.around(numpy.multiply(subFrameShapeXY, self.zoomFac)).astype(int) + cnvShapeXY = numpy.around( + numpy.multiply(subFrameShapeXY, self.zoomFac)).astype(int) if not numpy.allclose(self.cnvShape, cnvShapeXY): self._setCnvSize(cnvShapeXY) @@ -1115,7 +1144,8 @@ def redisplay(self): self.scaledIm = Image.frombuffer( "F", tuple(subFrameShapeIJ[::-1]), - self.scaledArr[self.begIJ[0]:self.endIJ[0], self.begIJ[1]:self.endIJ[1]].tostring(), + self.scaledArr[self.begIJ[0]:self.endIJ[0], + self.begIJ[1]:self.endIJ[1]].tostring(), "raw", "F", 0, @@ -1125,7 +1155,8 @@ def redisplay(self): self.scaledMask = Image.frombuffer( "L", tuple(subFrameShapeIJ[::-1]), - self.mask[self.begIJ[0]:self.endIJ[0], self.begIJ[1]:self.endIJ[1]].tostring(), + self.mask[self.begIJ[0]:self.endIJ[0], + self.begIJ[1]:self.endIJ[1]].tostring(), "raw", "L", 0, @@ -1136,7 +1167,7 @@ def redisplay(self): # resize image, if necessary if not numpy.allclose(subFrameShapeXY, self.cnvShape): - #print "applying zoom factor =", self.zoomFac + # print "applying zoom factor =", self.zoomFac self.scaledIm = self.scaledIm.resize(self.cnvShape) if self.scaledMask: self.scaledMask = self.scaledMask.resize(self.cnvShape) @@ -1144,8 +1175,10 @@ def redisplay(self): # update scroll bars # note that the vertical scrollbar is upside-down with respect to ij, so set it to 1-end, 1-beg floatShape = [float(elt) for elt in self.dataArr.shape] - self.hsb.set(self.begIJ[1] / floatShape[1], self.endIJ[1] / floatShape[1]) - self.vsb.set(1.0 - (self.endIJ[0] / floatShape[0]), 1.0 - (self.begIJ[0] / floatShape[0])) + self.hsb.set(self.begIJ[1] / floatShape[1], + self.endIJ[1] / floatShape[1]) + self.vsb.set(1.0 - (self.endIJ[0] / floatShape[0]), + 1.0 - (self.begIJ[0] / floatShape[0])) # compute and apply current range self.applyRange(redisplay=False) @@ -1178,8 +1211,10 @@ def scaleASinh(self, scaleFac=0.1): I don't yet set m. I might be able to add it, I'm just not sure it's useful given how I already stretch data """ + def arcsinh(x, out=None): return numpy.arcsinh(numpy.multiply(x, scaleFac), out) + self.setScaleFunc(arcsinh) def scaleLinear(self): @@ -1198,10 +1233,10 @@ def setScaleFunc(self, func): scaled value = func(data - dataMin) """ self.scaleFunc = func - #print "scaleFunc = %r" % (self.scaleFunc) + # print "scaleFunc = %r" % (self.scaleFunc) self.redisplay() - def setZoomFac(self, zoomFac, desCtrCnv = None, forceRedisplay=False): + def setZoomFac(self, zoomFac, desCtrCnv=None, forceRedisplay=False): """Set the zoom factor. Inputs: @@ -1217,14 +1252,15 @@ def setZoomFac(self, zoomFac, desCtrCnv = None, forceRedisplay=False): etc. """ if desCtrCnv is not None: - desCtrIJ = self.arrIJFromImPos(self.imPosFromCnvPos(desCtrCnv), doCheck=False) + desCtrIJ = self.arrIJFromImPos(self.imPosFromCnvPos(desCtrCnv), + doCheck=False) else: desCtrIJ = None oldZoomFac = self.zoomFac self.zoomFac = limitZoomFac(zoomFac) self.currZoomWdg.set(self.zoomFac) - #print "setZoomFac(zoomFac=%s; desCtrCnv=%s); oldZoomFac=%s, newZoomFac=%s" % (zoomFac, desCtrCnv, oldZoomFac, self.zoomFac) + # print "setZoomFac(zoomFac=%s; desCtrCnv=%s); oldZoomFac=%s, newZoomFac=%s" % (zoomFac, desCtrCnv, oldZoomFac, self.zoomFac) if self.zoomFac != oldZoomFac or forceRedisplay: self._updImBounds(desCtrIJ=desCtrIJ, updZoom=False) @@ -1259,15 +1295,15 @@ def showArr(self, arr, mask=None): mask = numpy.asarray(mask) if mask.shape != self.dataArr.shape: raise RuntimeError("mask shape=%s != arr shape=%s" % \ - (mask.shape, self.dataArr.shape)) + (mask.shape, self.dataArr.shape)) # an extra array cast is used because "compressed" returns what *looks* like an array # but is actually something else (I'm not sure exactly what) unmaskedArr = numpy.array( ma.array( dataArr, - mask = mask & self.stretchExcludeBits, - dtype = float, + mask=mask & self.stretchExcludeBits, + dtype=float, ).compressed()) if len(unmaskedArr) < 100: # too few points remaining; use everything @@ -1287,7 +1323,7 @@ def showArr(self, arr, mask=None): if self.dataArr.shape != oldShape or not self.zoomFac: # unknown zoom or new image is a different size than the old one; zoom to fit - self.begIJ = (0,0) + self.begIJ = (0, 0) self.endIJ = self.dataArr.shape newZoomFac = self.getFitZoomFac() self.setZoomFac(newZoomFac, forceRedisplay=True) @@ -1312,7 +1348,7 @@ def _dispFromScaled(self, val): Note: the form of the equation must strictly be val * scale + offset with no variation allowed, else this equation will not work with images. """ - #print "_dispFromScaled(%r); scale=%r; offset=%r" % (val, self.dispScale, self.dispOffset) + # print "_dispFromScaled(%r); scale=%r; offset=%r" % (val, self.dispScale, self.dispOffset) return val * self.dispScale + self.dispOffset def _setCnvSize(self, cnvShape): @@ -1323,9 +1359,9 @@ def _setCnvSize(self, cnvShape): # set canvas size and scroll region self.cnv.configure( - width = cnvShape[0], - height = cnvShape[1], - scrollregion = (0, 0, cnvShape[0], cnvShape[1]), + width=cnvShape[0], + height=cnvShape[1], + scrollregion=(0, 0, cnvShape[0], cnvShape[1]), ) # save the shape for use elsewhere @@ -1337,9 +1373,10 @@ def _trackMem(self, obj, objName): if not _DebugMem: return objID = id(obj) + def refGone(ref=None, objID=objID, objName=objName): print("GrayImage deleting %s" % (objName,)) - del(self._memDebugDict[objID]) + del (self._memDebugDict[objID]) self._memDebugDict[objID] = weakref.ref(obj, refGone) @@ -1347,7 +1384,7 @@ def _updCurrVal(self, evt=None): """Show the value that the mouse pointer is over. If evt is None then clear the current value. """ - if (evt==None) or (self.dataArr is None): + if (evt is None) or (self.dataArr is None): self.currXPosWdg.set(None) self.currYPosWdg.set(None) self.currValWdg.set(None) @@ -1360,7 +1397,7 @@ def _updCurrVal(self, evt=None): except IndexError: return - #print "evtxy=%s; cnvPos=%s; ds9pos=%s; arrIJ=%s" % ((evt.x, evt.y), cnvPos, imPos, arrIJ) + # print "evtxy=%s; cnvPos=%s; ds9pos=%s; arrIJ=%s" % ((evt.x, evt.y), cnvPos, imPos, arrIJ) val = self.dataArr[arrIJ[0], arrIJ[1]] self.currXPosWdg.set(imPos[0]) @@ -1374,7 +1411,7 @@ def _updFrameShape(self, evt=None): self.hsb.winfo_width(), self.vsb.winfo_height(), ) - #print "self._updFrameShape: self.frameShape=%s" % (self.frameShape,) + # print "self._updFrameShape: self.frameShape=%s" % (self.frameShape,) self._updImBounds(updZoom=True) def _updImBounds(self, desCtrIJ=None, updZoom=True): @@ -1384,26 +1421,32 @@ def _updImBounds(self, desCtrIJ=None, updZoom=True): Inputs: - updZoom: if True, zoom is increased if necessary so that the image fills x or y """ - #print "self._updImBounds(desCtrIJ=%s, updZoom=%s)" % (desCtrIJ, updZoom) + # print "self._updImBounds(desCtrIJ=%s, updZoom=%s)" % (desCtrIJ, updZoom) if self.dataArr is None: return if not updZoom: if desCtrIJ is None: desCtrIJ = numpy.divide(numpy.add(self.endIJ, self.begIJ), 2.0) - desSizeIJ = numpy.around(numpy.divide(self.frameShape[::-1], float(self.zoomFac))).astype(int) + desSizeIJ = numpy.around(numpy.divide(self.frameShape[::-1], + float(self.zoomFac))).astype( + int) sizeIJ = numpy.minimum(self.dataArr.shape, desSizeIJ) - desBegIJ = numpy.around(numpy.subtract(desCtrIJ, numpy.divide(sizeIJ, 2.0))).astype(int) - self.begIJ = numpy.minimum(numpy.maximum(desBegIJ, (0,0)), numpy.subtract(self.dataArr.shape, sizeIJ)) + desBegIJ = numpy.around( + numpy.subtract(desCtrIJ, numpy.divide(sizeIJ, 2.0))).astype(int) + self.begIJ = numpy.minimum(numpy.maximum(desBegIJ, (0, 0)), + numpy.subtract(self.dataArr.shape, + sizeIJ)) self.endIJ = self.begIJ + sizeIJ -# print "self._updImBounds desCtrIJ=%s, zoomFac=%s, desSizeIJ=%s, sizeIJ=%s, begIJ=%s, endIJ=%s" % (desCtrIJ, self.zoomFac, desSizeIJ, sizeIJ, self.begIJ, self.endIJ) + # print "self._updImBounds desCtrIJ=%s, zoomFac=%s, desSizeIJ=%s, sizeIJ=%s, begIJ=%s, endIJ=%s" % (desCtrIJ, self.zoomFac, desSizeIJ, sizeIJ, self.begIJ, self.endIJ) else: sizeIJ = numpy.subtract(self.endIJ, self.begIJ) - actZoomIJ = numpy.divide(self.frameShape[::-1], sizeIJ.astype(float)) + actZoomIJ = numpy.divide(self.frameShape[::-1], + sizeIJ.astype(float)) desZoomFac = min(actZoomIJ) self.zoomFac = limitZoomFac(desZoomFac) self.currZoomWdg.set(self.zoomFac) -# print "self._updImBounds; sizeIJ=%s, frameShape=%s, actZoomIJ=%s, desZoomFac=%s, zoomFac=%s" % (sizeIJ, self.frameShape, actZoomIJ, desZoomFac, self.zoomFac) + # print "self._updImBounds; sizeIJ=%s, frameShape=%s, actZoomIJ=%s, desZoomFac=%s, zoomFac=%s" % (sizeIJ, self.frameShape, actZoomIJ, desZoomFac, self.zoomFac) self.redisplay() @@ -1419,7 +1462,7 @@ def cnvPosFromImPos(self, imPos): """ # offImPos = imPos with respect to LL corner of displayed subframe begImPos = self.begIJ[::-1] - offImPos = [imPos[ii] - begImPos[ii] for ii in (0,1)] + offImPos = [imPos[ii] - begImPos[ii] for ii in (0, 1)] # cnvLLPos is the canvas position relative to the # lower left corner of the displayed subframe (with borders removed) @@ -1430,7 +1473,7 @@ def cnvPosFromImPos(self, imPos): cnvLLPos[0] + self.bdWidth, self.cnvShape[1] - 1 - self.bdWidth - cnvLLPos[1], ] - #print "cnvPosFromImPos(imPos=%s) begImPos=%s, offImPos=%s, cnvLLPos=%s, cnvPos=%s" % (imPos, begImPos, offImPos, cnvLLPos, cnvPos) + # print "cnvPosFromImPos(imPos=%s) begImPos=%s, offImPos=%s, cnvLLPos=%s, cnvPos=%s" % (imPos, begImPos, offImPos, cnvLLPos, cnvPos) return cnvPos def arrIJFromImPos(self, imPos, doCheck=True): @@ -1440,7 +1483,7 @@ def arrIJFromImPos(self, imPos, doCheck=True): arrIJ = [int(math.floor(imPos[ii])) for ii in (1, 0)] if doCheck: if not (0 <= arrIJ[0] < self.dataArr.shape[0] \ - and 0 <= arrIJ[1] < self.dataArr.shape[1]): + and 0 <= arrIJ[1] < self.dataArr.shape[1]): raise IndexError("%s out of range" % arrIJ) return arrIJ @@ -1462,8 +1505,8 @@ def imPosFromCnvPos(self, cnvPos): offImPos = [(cnvLL + 0.5) / float(self.zoomFac) for cnvLL in cnvLLPos] begImPos = self.begIJ[::-1] - imPos = [offImPos[ii] + begImPos[ii] for ii in (0,1)] - #print "imPosFroMCnvPos(cnvPos=%s) cnvLLPos=%s, offImPos=%s, begImPos=%s, imPos=%s" % (cnvPos, cnvLLPos, offImPos, begImPos, imPos) + imPos = [offImPos[ii] + begImPos[ii] for ii in (0, 1)] + # print "imPosFroMCnvPos(cnvPos=%s) cnvLLPos=%s, offImPos=%s, begImPos=%s, imPos=%s" % (cnvPos, cnvLLPos, offImPos, begImPos, imPos) return imPos @@ -1494,10 +1537,9 @@ def evtOnCanvas(self, evt): """Return True if event is on the visible part of the image/canvas. """ cnvPos = self.cnvPosFromEvt(evt) - return cnvPos[0] >= 0 \ - and cnvPos[1] >= 0 \ - and cnvPos[0] < self.cnv.winfo_width() \ - and cnvPos[1] < self.cnv.winfo_height() + return 0 <= cnvPos[0] < self.cnv.winfo_width() \ + and 0 <= cnvPos[1] < self.cnv.winfo_height() + def limitZoomFac(desZoomFac): """Return zoom factor restricted to be in bounds""" @@ -1510,35 +1552,35 @@ def limitZoomFac(desZoomFac): except ImportError: import pyfits import RO.DS9 - from . import PythonTk - from . import StatusBar + from .PythonTk import PythonTk + from .StatusBar import StatusBar - root = PythonTk.PythonTk() + root = PythonTk() root.geometry("450x450") fileName = 'gimg0128.fits' fileName = "testImage.fits" maskInfo = ( MaskInfo( - bitInd = 1, - name = "saturated pixels", - btext = "Sat", - color = "red", - intens = 255, + bitInd=1, + name="saturated pixels", + btext="Sat", + color="red", + intens=255, ), MaskInfo( - bitInd = 0, - name = "masked pixels", - btext = "Mask", - color = "green", - intens = 100, + bitInd=0, + name="masked pixels", + btext="Mask", + color="green", + intens=100, ), ) - testFrame = GrayImageWdg(root, maskInfo = maskInfo) + testFrame = GrayImageWdg(root, maskInfo=maskInfo) testFrame.grid(row=0, column=0, sticky="news") - statusBar = StatusBar.StatusBar(root) + statusBar = StatusBar(root) statusBar.grid(row=1, column=0, sticky="ew") root.grid_rowconfigure(0, weight=1) @@ -1549,11 +1591,12 @@ def limitZoomFac(desZoomFac): if not fileName: arrSize = 255 - imArr = numpy.arange(arrSize**2, dtype=numpy.float64).reshape([arrSize, arrSize]) + imArr = numpy.arange(arrSize ** 2, dtype=numpy.float64).reshape( + [arrSize, arrSize]) # put marks at center ctr = (arrSize - 1) / 2 imArr[ctr] = 0 - imArr[:,ctr] = 0 + imArr[:, ctr] = 0 mask = None else: dirName = os.path.dirname(__file__) @@ -1562,15 +1605,13 @@ def limitZoomFac(desZoomFac): imArr = fitsIm[0].data mask = None if len(fitsIm) > 1 and \ - fitsIm[1].data.shape == imArr.shape and \ - fitsIm[1].data.dtype == numpy.uint8: + fitsIm[1].data.shape == imArr.shape and \ + fitsIm[1].data.dtype == numpy.uint8: mask = fitsIm[1].data testFrame.showArr(imArr, mask=mask) - #ds9 = RO.DS9.DS9Win() - #ds9.showArray(imArr) + # ds9 = RO.DS9.DS9Win() + # ds9.showArray(imArr) root.mainloop() - - diff --git a/python/RO/Wdg/Gridder.py b/python/RO/Wdg/Gridder.py index 2cd3036..1ab1c60 100755 --- a/python/RO/Wdg/Gridder.py +++ b/python/RO/Wdg/Gridder.py @@ -40,9 +40,11 @@ __all__ = ['Gridder'] import tkinter + import RO.Alg import RO.SeqUtil -from .Label import Label, StrLabel +from .Label import StrLabel + class Gridder(object): def __init__(self, @@ -495,8 +497,8 @@ def __init__ (self, self._gridWdg(self.unitsWdg, sticky="w", colSpan=1) if __name__ == "__main__": - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() wdgFrame = tkinter.Frame(root) gr = Gridder(wdgFrame) diff --git a/python/RO/Wdg/HTTPGetWdg.py b/python/RO/Wdg/HTTPGetWdg.py index 4637eb7..9a32bc6 100755 --- a/python/RO/Wdg/HTTPGetWdg.py +++ b/python/RO/Wdg/HTTPGetWdg.py @@ -31,15 +31,16 @@ __all__ = ['HTTPGetWdg'] import sys +import tkinter import traceback import weakref -from . import Bindings -import tkinter + import RO.AddCallback +import RO.Comm.HTTPGet as HTTPGet import RO.Constants import RO.MathUtil -import RO.Comm.HTTPGet as HTTPGet import RO.Wdg +from . import Bindings from .CtxMenu import addCtxMenu _StatusInterval = 200 # ms between status checks diff --git a/python/RO/Wdg/HistoryMenu.py b/python/RO/Wdg/HistoryMenu.py index 9ae36e0..21f85d7 100755 --- a/python/RO/Wdg/HistoryMenu.py +++ b/python/RO/Wdg/HistoryMenu.py @@ -21,8 +21,10 @@ __all__ = ['HistoryMenu'] import tkinter + import RO.Alg -from .CtxMenu import CtxMenu, CtxMenuMixin +from .CtxMenu import CtxMenuMixin + class HistoryMenu (tkinter.Menubutton, CtxMenuMixin): """A menu showing a history of recent events. @@ -116,8 +118,8 @@ def nItems(self): if __name__ == "__main__": - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() def doAdd(*args): name = nameVar.get() diff --git a/python/RO/Wdg/InputContPresetsWdg.py b/python/RO/Wdg/InputContPresetsWdg.py index 8d4aea7..a0e7ed2 100755 --- a/python/RO/Wdg/InputContPresetsWdg.py +++ b/python/RO/Wdg/InputContPresetsWdg.py @@ -17,12 +17,13 @@ import RO.TkUtil from . import Entry -from .Label import Label, StrLabel from . import InputDialog -from . import OptionMenu -from . import Menubutton +from .Menubutton import Menubutton +from .OptionMenu import OptionMenu +from .Label import StrLabel -class InputContPresetsWdg(Menubutton.Menubutton): + +class InputContPresetsWdg(Menubutton): """Widget to manage named presets for an input container list Manages a list of named presets, with two categories: @@ -55,7 +56,7 @@ def __init__(self, - helpURL: URL for on-line help - autoUpdate: automatically set text to name of preset that matches inputCont, if there is a match. if None then set False if "text" is in kwargs and True otherwise - - **kwargs: additional config arguments for Menubutton.Menubutton. + - **kwargs: additional config arguments for Menubutton. Warning: for auto update to work correctly, every value dict in stdPresets must have an entry for each input container, and the values must be strings. @@ -83,7 +84,7 @@ def __init__(self, "highlightthickness": 2, } wdgKArgs.update(kwargs) - Menubutton.Menubutton.__init__(self, master, helpText=helpText, helpURL=helpURL, **wdgKArgs) + Menubutton.__init__(self, master, helpText=helpText, helpURL=helpURL, **wdgKArgs) self._menu = tkinter.Menu(self, tearoff=False) editMenu = tkinter.Menu( @@ -295,7 +296,7 @@ def body(self, master): StrLabel(master=master, text="Save This Preset As:").grid(row=0, column=0, columnspan=5) # Tkinter.Label(master, text="Name:").grid(row=1, column=0) self.nameEntry = Entry.StrEntry(master) - self.currNameWdg = OptionMenu.OptionMenu( + self.currNameWdg = OptionMenu( master = master, items = self._currNameList, label = "", @@ -327,7 +328,7 @@ def __init__(self, master, currNameList): def body(self, master): StrLabel(master=master, text="Rename Preset:").grid(row=0, column=0, columnspan=5) # Tkinter.Label(master, text="Name:").grid(row=1, column=0) - self.oldNameWdg = OptionMenu.OptionMenu( + self.oldNameWdg = OptionMenu( master = master, items = self._currNameList, ) @@ -356,7 +357,7 @@ def __init__(self, master, currNameList): def body(self, master): StrLabel(master=master, text="Delete Preseturation:").grid(row=0, column=0, columnspan=5) - self.currNameWdg = OptionMenu.OptionMenu( + self.currNameWdg = OptionMenu( master = master, items = self._currNameList, ) diff --git a/python/RO/Wdg/InputDialog.py b/python/RO/Wdg/InputDialog.py index ef90fae..57cd00d 100755 --- a/python/RO/Wdg/InputDialog.py +++ b/python/RO/Wdg/InputDialog.py @@ -28,7 +28,8 @@ import tkinter -from . import Button +from .Button import Button + class ModalDialogBase(tkinter.Toplevel): """Base class for modal dialogs. @@ -111,9 +112,9 @@ def buttons(self, master): Override if you want something else. """ - self.okWdg = Button.Button(master, text="OK", width=6, command=self.ok, default="active") + self.okWdg = Button(master, text="OK", width=6, command=self.ok, default="active") self.okWdg.pack(side="left") - self.cancelWdg = Button.Button(master, text="Cancel", width=6, command=self.close) + self.cancelWdg = Button(master, text="Cancel", width=6, command=self.close) self.cancelWdg.pack(side="left") self.bind("", self.ok) diff --git a/python/RO/Wdg/IsCurrentMixin.py b/python/RO/Wdg/IsCurrentMixin.py index b05f04c..1d81594 100755 --- a/python/RO/Wdg/IsCurrentMixin.py +++ b/python/RO/Wdg/IsCurrentMixin.py @@ -227,8 +227,8 @@ def getIsCurrent(self): if __name__ == "__main__": import tkinter - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() class ColorButton(tkinter.Button, IsCurrentActiveMixin): def __init__(self, *args, **kargs): diff --git a/python/RO/Wdg/Label.py b/python/RO/Wdg/Label.py index a774382..9766096 100755 --- a/python/RO/Wdg/Label.py +++ b/python/RO/Wdg/Label.py @@ -57,12 +57,14 @@ import sys import tkinter + import RO.Constants import RO.MathUtil import RO.StringUtil -from .CtxMenu import CtxMenu, CtxMenuMixin -from .SeverityMixin import SeverityMixin +from .CtxMenu import CtxMenuMixin from .IsCurrentMixin import IsCurrentMixin +from .SeverityMixin import SeverityMixin + class Label(tkinter.Label, CtxMenuMixin, IsCurrentMixin, SeverityMixin): """Base class for labels (display ROWdgs); do not use directly. @@ -355,9 +357,9 @@ def setCvtDegToHrs(self, cvtDegToHrs): if __name__ == "__main__": - from . import PythonTk + from .PythonTk import PythonTk from RO.TkUtil import Timer - root = PythonTk.PythonTk() + root = PythonTk() wdgSet = ( BoolLabel(root, diff --git a/python/RO/Wdg/LogWdg.py b/python/RO/Wdg/LogWdg.py index 8c6e34f..5722aca 100755 --- a/python/RO/Wdg/LogWdg.py +++ b/python/RO/Wdg/LogWdg.py @@ -71,8 +71,9 @@ __all__ = ['LogWdg'] import tkinter + import RO.Alg -from . import Text +from .Text import Text _AllTextTag = "__alltext" @@ -115,7 +116,7 @@ def __init__(self, master = self, orient = "vertical", ) - self.text = Text.Text ( + self.text = Text( master = self, yscrollcommand = self.yscroll.set, wrap = "word", @@ -507,8 +508,8 @@ def _updSevTagColor(self, sevTag, color, colorPref): if __name__ == '__main__': import random import sys - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() testFrame = LogWdg ( master=root, diff --git a/python/RO/Wdg/Menubutton.py b/python/RO/Wdg/Menubutton.py index 844b334..244c165 100644 --- a/python/RO/Wdg/Menubutton.py +++ b/python/RO/Wdg/Menubutton.py @@ -9,8 +9,10 @@ __all__ = ['Menubutton'] import tkinter + import RO.Constants -from .CtxMenu import CtxMenu, CtxMenuMixin +from .CtxMenu import CtxMenuMixin + class Menubutton(tkinter.Menubutton, CtxMenuMixin): def __init__(self, diff --git a/python/RO/Wdg/OptionButtons.py b/python/RO/Wdg/OptionButtons.py index 5d14ba9..f3c0fe3 100755 --- a/python/RO/Wdg/OptionButtons.py +++ b/python/RO/Wdg/OptionButtons.py @@ -180,8 +180,8 @@ def listGet(aList, ind, defVal=None): wdg.pack(side="top", anchor="nw") if __name__ == "__main__": - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() def doPrint(): print("getString() = %r" % (optFrame.getString(),)) diff --git a/python/RO/Wdg/OptionMenu.py b/python/RO/Wdg/OptionMenu.py index a1fdd5c..6996743 100755 --- a/python/RO/Wdg/OptionMenu.py +++ b/python/RO/Wdg/OptionMenu.py @@ -109,12 +109,14 @@ __all__ = ['OptionMenu'] import tkinter + import RO.AddCallback import RO.Alg import RO.SeqUtil from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentActiveMixin -from .SeverityMixin import SeverityActiveMixin from .Menubutton import Menubutton +from .SeverityMixin import SeverityActiveMixin + class _DoItem: def __init__(self, var, value): @@ -546,9 +548,9 @@ def _doCallbacks(self): if __name__ == "__main__": from .Label import Label - from . import PythonTk - from . import StatusBar - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + from .StatusBar import StatusBar + root = PythonTk() def callFunc(wdg): label.set(wdg.getString()) @@ -609,7 +611,7 @@ def callFunc(wdg): label = Label(root, width=20, anchor="w", helpText="most recently selected value") label.grid(row=2, column=0, columnspan=4, sticky="w") - statusBar = StatusBar.StatusBar(root, width=20) + statusBar = StatusBar(root, width=20) statusBar.grid(row=3, column=0, columnspan=4, sticky="ew") root.mainloop() diff --git a/python/RO/Wdg/OptionPanelControl.py b/python/RO/Wdg/OptionPanelControl.py index ce95536..fb5c626 100755 --- a/python/RO/Wdg/OptionPanelControl.py +++ b/python/RO/Wdg/OptionPanelControl.py @@ -28,9 +28,11 @@ __all__ = ['OptionPanelControl'] import tkinter + from .Checkbutton import Checkbutton from .CtxMenu import CtxMenuMixin + class _WdgButton(Checkbutton): """A checkbutton that shows or hides a gridded widget. diff --git a/python/RO/Wdg/PatchedCanvas.py b/python/RO/Wdg/PatchedCanvas.py index c3166e7..438f3af 100755 --- a/python/RO/Wdg/PatchedCanvas.py +++ b/python/RO/Wdg/PatchedCanvas.py @@ -14,8 +14,9 @@ """ __all__ = ['PatchedCanvas'] -import warnings import tkinter +import warnings + class PatchedCanvas(tkinter.Canvas): def __init__(self, *args, **kargs): diff --git a/python/RO/Wdg/PathWdg.py b/python/RO/Wdg/PathWdg.py index bbd3906..7d1ec4a 100755 --- a/python/RO/Wdg/PathWdg.py +++ b/python/RO/Wdg/PathWdg.py @@ -29,11 +29,13 @@ import os import tkinter import tkinter.filedialog + import RO.AddCallback import RO.Constants -from .CtxMenu import CtxMenu, CtxMenuMixin +from .CtxMenu import CtxMenuMixin from .SeverityMixin import SeverityActiveMixin + class BasePathWdg (tkinter.Button, RO.AddCallback.BaseMixin, CtxMenuMixin, SeverityActiveMixin): def __init__(self, diff --git a/python/RO/Wdg/ProgressBar.py b/python/RO/Wdg/ProgressBar.py index 94482fb..863da67 100755 --- a/python/RO/Wdg/ProgressBar.py +++ b/python/RO/Wdg/ProgressBar.py @@ -31,13 +31,15 @@ __all__ = ['ProgressBar', 'TimeBar'] import time +import tkinter + import RO.SeqUtil from RO.TkUtil import Timer -import tkinter -from . import Button +from .Button import Button from . import Entry from .Gridder import Gridder -from .Label import Label, StrLabel +from .Label import StrLabel + class ProgressBar (tkinter.Frame): """A bar graph showing a value or fraction of a task performed. @@ -494,8 +496,8 @@ def _updateTime(self, reschedule = True): if __name__ == "__main__": - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() # horizontal and vertical progress bars @@ -574,10 +576,10 @@ def clearRemTime(): timeEntry = Entry.IntEntry(root, defValue = 9, width=5) gr.gridWdg ("Rem Time", timeEntry) gr.gridWdg (False, ( - Button.Button(root, text="Start", command=startRemTime), - Button.Button(root, text="Pause", command=pauseRemTime), - Button.Button(root, text="Resume", command=resumeRemTime), - Button.Button(root, text="Clear", command=clearRemTime), + Button(root, text="Start", command=startRemTime), + Button(root, text="Pause", command=pauseRemTime), + Button(root, text="Resume", command=resumeRemTime), + Button(root, text="Clear", command=clearRemTime), ), ) diff --git a/python/RO/Wdg/PythonTk.py b/python/RO/Wdg/PythonTk.py index a9a0688..71ba073 100755 --- a/python/RO/Wdg/PythonTk.py +++ b/python/RO/Wdg/PythonTk.py @@ -27,8 +27,10 @@ __all__ = ['PythonTk'] import tkinter + from . import Bindings -from . import PythonWdg +from .PythonWdg import PythonWdg + class PythonTk (tkinter.Tk): """Creates a Tkinter application with standard menus and such""" @@ -67,7 +69,7 @@ def __init__(self, **kargs): self.pyToplevel = tkinter.Toplevel() self.pyToplevel.geometry("+0+450") self.pyToplevel.title("Python") - pyFrame = PythonWdg.PythonWdg(self.pyToplevel) + pyFrame = PythonWdg(self.pyToplevel) pyFrame.pack(expand=tkinter.YES, fill=tkinter.BOTH) # set up standard bindings diff --git a/python/RO/Wdg/PythonWdg.py b/python/RO/Wdg/PythonWdg.py index 6206266..45fdee6 100755 --- a/python/RO/Wdg/PythonWdg.py +++ b/python/RO/Wdg/PythonWdg.py @@ -43,9 +43,11 @@ import re import tkinter import tkinter.filedialog + import RO.CnvUtil import RO.OS -from . import Text +from .Text import Text + class PythonWdg(tkinter.Frame): """A frame containing text window into which you may enter Python code. @@ -65,7 +67,7 @@ def __init__ (self, self.master=master self.filePath = filePath - self.inputWdg = Text.Text( + self.inputWdg = Text( master = self, width = 60, height = 10, diff --git a/python/RO/Wdg/RadiobuttonSet.py b/python/RO/Wdg/RadiobuttonSet.py index 1a8c8b5..f747947 100755 --- a/python/RO/Wdg/RadiobuttonSet.py +++ b/python/RO/Wdg/RadiobuttonSet.py @@ -47,6 +47,7 @@ __all__ = ['RadiobuttonSet'] import tkinter + import RO.AddCallback import RO.Alg import RO.SeqUtil @@ -55,6 +56,7 @@ from .Button import Radiobutton from .IsCurrentMixin import AutoIsCurrentMixin, IsCurrentActiveMixin + class RadiobuttonSet (RO.AddCallback.TkVarMixin, AutoIsCurrentMixin, IsCurrentActiveMixin): """A set of Tkinter Radiobuttons with extra features. @@ -312,9 +314,9 @@ def winfo_ismapped(self): return self.wdgSet[0].winfo_ismapped() if __name__ == "__main__": - from . import PythonTk + from .PythonTk import PythonTk from .StatusBar import StatusBar - root = PythonTk.PythonTk() + root = PythonTk() rbFrame1 = tkinter.Frame() rbs1 = RadiobuttonSet( diff --git a/python/RO/Wdg/ResizableRect.py b/python/RO/Wdg/ResizableRect.py index d8c9f23..b3f9939 100755 --- a/python/RO/Wdg/ResizableRect.py +++ b/python/RO/Wdg/ResizableRect.py @@ -30,8 +30,9 @@ __all__ = ["ResizableRect"] import tkinter -import RO.SeqUtil + import RO.AddCallback +import RO.SeqUtil from RO.Alg import GenericCallback Debug = False @@ -329,8 +330,8 @@ def _setRegionCoords(self, regionName, x0, y0, x1, y1): if __name__ == "__main__": - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() cnvFrame = tkinter.Frame(root, borderwidth=2, relief="solid") cnv = tkinter.Canvas( cnvFrame, diff --git a/python/RO/Wdg/ScriptWdg.py b/python/RO/Wdg/ScriptWdg.py index 2fdf078..8281ac7 100755 --- a/python/RO/Wdg/ScriptWdg.py +++ b/python/RO/Wdg/ScriptWdg.py @@ -33,14 +33,15 @@ """ __all__ = ['BasicScriptWdg', 'ScriptModuleWdg', 'ScriptFileWdg'] +import importlib import os.path import tkinter -import RO.Constants + import RO.AddCallback +import RO.Constants import RO.ScriptRunner -from . import Button -from . import StatusBar -import importlib +from .Button import Button +from .StatusBar import StatusBar # compute _StateSevDict which contains # state:severity for non-normal severities @@ -264,7 +265,7 @@ def __init__(self, self.columnconfigure(0, weight=1) row += 1 - scriptStatusBar = StatusBar.StatusBar( + scriptStatusBar = StatusBar( master = self, helpURL = helpURL, helpText = "script status and messages", @@ -272,7 +273,7 @@ def __init__(self, scriptStatusBar.grid(row=row, column=0, sticky="ew") row += 1 - cmdStatusBar = StatusBar.StatusBar( + cmdStatusBar = StatusBar( master = self, dispatcher = dispatcher, summaryLen = 30, @@ -283,19 +284,19 @@ def __init__(self, row += 1 buttonFrame = tkinter.Frame(self) - startButton = Button.Button( + startButton = Button( master = buttonFrame, text = "Start", helpText = "Start the script", helpURL = helpURL, ) startButton.pack(side="left") - pauseButton = Button.Button( + pauseButton = Button( master = buttonFrame, helpURL = helpURL, ) pauseButton.pack(side="left") - cancelButton = Button.Button( + cancelButton = Button( master = buttonFrame, text = "Cancel", helpText = "Halt the script", @@ -541,9 +542,9 @@ def _getScriptFuncs(self, isFirst=None): if __name__ == "__main__": import RO.KeyDispatcher - from . import PythonTk + from .PythonTk import PythonTk from . import TestScriptWdg - root = PythonTk.PythonTk() + root = PythonTk() root.title('Script 1 (root)') dispatcher = RO.KeyDispatcher.KeyDispatcher() diff --git a/python/RO/Wdg/ScrolledWdg.py b/python/RO/Wdg/ScrolledWdg.py index 6f80aea..b0dd808 100755 --- a/python/RO/Wdg/ScrolledWdg.py +++ b/python/RO/Wdg/ScrolledWdg.py @@ -162,8 +162,8 @@ def _configVIncr(self, evt=None): if __name__ == '__main__': - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() root.resizable(False, True) diff --git a/python/RO/Wdg/SeverityMixin.py b/python/RO/Wdg/SeverityMixin.py index 0554b40..1c347c8 100755 --- a/python/RO/Wdg/SeverityMixin.py +++ b/python/RO/Wdg/SeverityMixin.py @@ -112,8 +112,8 @@ def _updateSeverityColor(self, *args): if __name__ == "__main__": import tkinter - from . import PythonTk - root = PythonTk.PythonTk() + from .PythonTk import PythonTk + root = PythonTk() class ColorButton(tkinter.Button, SeverityActiveMixin): def __init__(self, *args, **kargs): diff --git a/python/RO/Wdg/Sound.py b/python/RO/Wdg/Sound.py index 8adeaca..4c27334 100644 --- a/python/RO/Wdg/Sound.py +++ b/python/RO/Wdg/Sound.py @@ -19,7 +19,9 @@ import os import sys import tkinter + import RO.StringUtil + try: import pygame.mixer _PyGameAvail = True diff --git a/python/RO/Wdg/StateTracker.py b/python/RO/Wdg/StateTracker.py index dd51b39..8d1986d 100644 --- a/python/RO/Wdg/StateTracker.py +++ b/python/RO/Wdg/StateTracker.py @@ -10,9 +10,11 @@ __all__ = ["StateTracker"] import sys + import RO.Alg.GenericCallback import RO.Constants + class _ItemState(object): """Functions for getting and setting item state """ diff --git a/python/RO/Wdg/StatusBar.py b/python/RO/Wdg/StatusBar.py index 36851b4..28cef67 100644 --- a/python/RO/Wdg/StatusBar.py +++ b/python/RO/Wdg/StatusBar.py @@ -66,13 +66,15 @@ import sys import tkinter + import RO.Alg import RO.Constants import RO.KeyVariable import RO.Prefs.PrefVar from RO.TkUtil import Timer -from . import Sound from . import Entry +from . import Sound + def _getSound(playCmdSounds, prefs, prefName): noPlay = Sound.NoPlay() diff --git a/python/RO/Wdg/StripChartWdg.py b/python/RO/Wdg/StripChartWdg.py index db1f701..61443b1 100755 --- a/python/RO/Wdg/StripChartWdg.py +++ b/python/RO/Wdg/StripChartWdg.py @@ -79,14 +79,16 @@ import bisect import datetime import time - -import numpy import tkinter + import matplotlib import matplotlib.dates +import numpy from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg + from RO.TkUtil import Timer + class StripChartWdg(tkinter.Frame): """A widget to changing values in real time as a strip chart diff --git a/python/RO/Wdg/Text.py b/python/RO/Wdg/Text.py index b86c22e..eaff961 100755 --- a/python/RO/Wdg/Text.py +++ b/python/RO/Wdg/Text.py @@ -230,12 +230,12 @@ def _updateStateTagColors(self, *args): if __name__ == "__main__": from RO.Wdg.PythonTk import PythonTk - from . import StatusBar + from .StatusBar import StatusBar root = PythonTk() text1 = Text(root, "text widget", height=5, width=20) text2 = Text(root, readOnly=True, helpText = "read only text widget", height=5, width=20) - statusBar = StatusBar.StatusBar(root) + statusBar = StatusBar(root) text1.grid(row=0, column=0, sticky="nsew") text2.grid(row=1, column=0, sticky="nsew") statusBar.grid(row=2, column=0, sticky="ew") diff --git a/python/RO/Wdg/Toplevel.py b/python/RO/Wdg/Toplevel.py index b25ebf2..499cfff 100755 --- a/python/RO/Wdg/Toplevel.py +++ b/python/RO/Wdg/Toplevel.py @@ -68,8 +68,9 @@ import json import os.path import sys -import traceback import tkinter +import traceback + import RO.CnvUtil import RO.OS import RO.SeqUtil diff --git a/python/RO/Wdg/WdgPrefs.py b/python/RO/Wdg/WdgPrefs.py index 53ac999..79cf794 100755 --- a/python/RO/Wdg/WdgPrefs.py +++ b/python/RO/Wdg/WdgPrefs.py @@ -23,9 +23,10 @@ __all__ = [] import tkinter + import RO.Constants -import RO.TkUtil import RO.Prefs.PrefVar +import RO.TkUtil # use lazy evaluation to avoid accessing tk root until there is one _wdgPrefs = None diff --git a/python/RO/procFiles.py b/python/RO/procFiles.py index e6c0788..df81ae3 100755 --- a/python/RO/procFiles.py +++ b/python/RO/procFiles.py @@ -148,9 +148,11 @@ def func(inPath, isFirst, isLast, outPath): import os.path import sys import traceback + import RO.OS import RO.SeqUtil + def procFiles ( func, inPathList = sys.argv[1:], diff --git a/setup.py b/setup.py index 1ac1f2f..65762b3 100755 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ Alternatively you can copy python/RO to site-packages """ -long_description = """\ +long_description = """ Includes: * Alg: various useful algorithms including OrderedDict (a dictionary that remembers the order in which items are added) and MultiDict (a dictionary whose values are lists). @@ -56,8 +56,10 @@ classifiers = [c for c in classifiers.split("\n") if c], platforms = ["MacOS X", "unix", "Windows"], package_dir = {PkgName: PkgDir}, + package_data = {'':'python/RO/Bitmaps/*.xbm'}, packages = find_packages(PkgRoot), include_package_data = True, scripts = [], - zip_safe = False, # icons (e.g. as used by RO.Wdg.GrayImageDispWdg) are not retrieved in a zip-safe way + zip_safe = False, install_requires=['twisted'] + # icons (e.g. as used by RO.Wdg.GrayImageDispWdg) are not retrieved in a zip-safe way ) From cee9516206f61517d10be2e0845d58ec485ad6fd Mon Sep 17 00:00:00 2001 From: Dylan Gatlin Date: Fri, 14 Feb 2020 03:12:59 -0700 Subject: [PATCH 4/6] Fixed a mixup between open and file --- python/RO/Prefs/PrefVar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/RO/Prefs/PrefVar.py b/python/RO/Prefs/PrefVar.py index aced002..73867fb 100755 --- a/python/RO/Prefs/PrefVar.py +++ b/python/RO/Prefs/PrefVar.py @@ -1141,7 +1141,7 @@ def readFromFile(self, fileName=None): return try: - inFile = file(fileName, 'rU') + inFile = open(fileName, 'rU') except Exception as e: sys.stderr.write("Could not open preference file %r; error: %s\n" % (fileName, e)) return From ce07c32644af2fe280a758a7d85a159066425c5f Mon Sep 17 00:00:00 2001 From: Dylan Gatlin Date: Tue, 3 Mar 2020 14:53:05 -0700 Subject: [PATCH 5/6] Included python3 version warning in readme + some import changes --- README.txt | 2 ++ python/RO/StringUtil.py | 3 +-- setup.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.txt b/README.txt index 879411f..ceaf989 100755 --- a/README.txt +++ b/README.txt @@ -4,3 +4,5 @@ Tkinter-compatible networking. The docs directory contains installation instructions, an overview, version history and the license. + +> **WARNING:** this version is Python 3 only in preparation for SDSS-V. For SDSS-IV, use the ``python2`` branch. diff --git a/python/RO/StringUtil.py b/python/RO/StringUtil.py index 987fec0..61c02ee 100755 --- a/python/RO/StringUtil.py +++ b/python/RO/StringUtil.py @@ -52,14 +52,13 @@ 2015-11-05 ROwen Stop using dangerous bare "except:". """ import re - import numpy AngstromStr = u"\N{ANGSTROM SIGN}" DegStr = u"\N{DEGREE SIGN}" DMSStr = DegStr + "'\"" LambdaStr = "\u00c5" # for some reason this fails: u"\N{GREEK SMALL LETTER LAMBDA}" -MuStr = u"\N{GREEK SMALL LETTER MU}" +MuStr = u"\N{MICRO SIGN}" def dmsStrFromDeg (decDeg, nFields=3, precision=1, omitExtraFields = False): """Convert a number to a sexagesimal string with 1-3 fields. diff --git a/setup.py b/setup.py index 65762b3..13566a3 100755 --- a/setup.py +++ b/setup.py @@ -60,6 +60,6 @@ packages = find_packages(PkgRoot), include_package_data = True, scripts = [], - zip_safe = False, install_requires=['twisted'] + zip_safe = False, install_requires=['twisted', 'numpy'] # icons (e.g. as used by RO.Wdg.GrayImageDispWdg) are not retrieved in a zip-safe way ) From 680b0a9ee99c937495bc448fd9e9ea040e8bc915 Mon Sep 17 00:00:00 2001 From: Dylan Gatlin Date: Wed, 13 May 2020 13:22:16 -0600 Subject: [PATCH 6/6] OrderedDict is for all intents and purposes, dict. It still needs to have its own methods like _CheckIntegrity for tests --- python/RO/Alg/OrderedDict.py | 150 ++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 73 deletions(-) diff --git a/python/RO/Alg/OrderedDict.py b/python/RO/Alg/OrderedDict.py index 835f05b..0a8e425 100644 --- a/python/RO/Alg/OrderedDict.py +++ b/python/RO/Alg/OrderedDict.py @@ -34,9 +34,13 @@ Modified __repr__ to return a string that can recreate the dict. Added __str__ to output the traditional dict representation. 2015-09-24 ROwen Replace "== None" with "is None" to modernize the code. +2020-05-13 DGatlin Removed a number of functions in OrderedDict that can simply + be inhereted by dict in Python 3 """ __all__ = ["OrderedDict", "ReverseOrderedDict"] + + class OrderedDict(dict): """A dictionary in which the order of adding items is preserved. Replacing an existing item replaces it at its current location. @@ -55,25 +59,23 @@ def __init__(self, seqOrDict=None): else: for key, val in seqOrDict: self[key] = val - - def clear(self): - self.__keyList = [] - dict.clear(self) - + + # def clear(self): + # self.__keyList = [] + # dict.clear(self) + def copy(self): return self.__class__(self) - + def iterkeys(self): - return iter(self.__keyList) - + return self.keys() + def itervalues(self): - for key in self.keys(): - yield self[key] - + return iter(self) + def iteritems(self): - for key in self: - yield (key, self[key]) - + return self.items() + def index(self, key): """Return the index of key. Raise KeyError if not found. @@ -82,7 +84,7 @@ def index(self, key): return self.__keyList.index(key) except ValueError: raise KeyError("key=%r not in %s" % (key, self.__class__.__name__)) - + def insert(self, ind, key, value): """Insert a key, value pair before the specified index. If the key already exists, it is NOT moved but its value is updated. @@ -91,72 +93,72 @@ def insert(self, ind, key, value): if key not in self: self.__keyList.insert(ind, key) dict.__setitem__(self, key, value) - - def keys(self): - return self.__keyList[:] - - def pop(self, key): - val = self[key] - self.__delitem__(key) - return val - - def popitem(self, i=-1): - """Remove the ith item from the dictionary (the last item if i is omitted) - and returns (key, value). This emulates list.pop() instead of dict.popitem(), - since ordered dictionaries have a defined order. - """ - key = self.__keyList[i] - item = (key, self[key]) - self.__delitem__(key) - return item - - def setdefault(self, key, value): - if key not in self: - self[key] = value - return self[key] - + + # def keys(self): + # return self.__keyList[:] + + # def pop(self, key): + # val = self[key] + # self.__delitem__(key) + # return val + + # def popitem(self, i=-1): + # """Remove the ith item from the dictionary (the last item if i is omitted) + # and returns (key, value). This emulates list.pop() instead of dict.popitem(), + # since ordered dictionaries have a defined order. + # """ + # key = self.__keyList[i] + # item = (key, self[key]) + # self.__delitem__(key) + # return item + + # def setdefault(self, key, value): + # if key not in self: + # self[key] = value + # return self[key] + def sort(self, cmpFunc=None): """Sort the keys. """ - self.__keyList.sort(cmpFunc) - - def update(self, aDict): - """Add all items from dictionary aDict to self (in order if aDict is an ordered dictionary). - """ - for key, value in aDict.items(): - self[key] = value - - def values(self): - return [self[key] for key in self.keys()] - + pass + + # def update(self, aDict): + # """Add all items from dictionary aDict to self (in order if aDict is an ordered dictionary). + # """ + # for key, value in aDict.items(): + # self[key] = value + + # def values(self): + # return [self[key] for key in self.keys() + def _checkIntegrity(self): """Perform an internal consistency check and raise an AssertionError if anything is wrong. - + In principal a bug could lead to the system getting out of synch, hence this method. """ - assert len(self) == len(self.__keyList), \ - "length of dict %r != length of key list %r" % (len(self), len(self.__keyList)) + assert len(self) == len(self.keys()), \ + "length of dict %r != length of key list %r" % (len(self), len(self.keys())) for key in self.keys(): assert key in self, \ "key %r in key list missing from dictionary" % (key,) - - def __delitem__(self, key): - dict.__delitem__(self, key) - self.__keyList.remove(key) - - def __iter__(self): - return iter(self.keys()) - - def __repr__(self): - return "%s([%s])" % (self.__class__.__name__, ', '.join(["(%r, %r)" % item for item in self.items()])) - def __str__(self): - return "{%s}" % (', '.join(["(%r, %r)" % item for item in self.items()]),) - - def __setitem__(self, key, value): - if key not in self: - self.__keyList.append(key) - dict.__setitem__(self, key, value) + # def __delitem__(self, key): + # dict.__delitem__(self, key) + # self.__keyList.remove(key) + + # def __iter__(self): + # return iter(self.keys()) + + # def __repr__(self): + # return "%s([%s])" % (self.__class__.__name__, ', '.join(["(%r, %r)" % item for item in self.items()])) + + # def __str__(self): + # return "{%s}" % (', '.join(["(%r, %r)" % item for item in self.items()]),) + + # def __setitem__(self, key, value): + # if key not in self: + # self.__keyList.append(key) + # dict.__setitem__(self, key, value) class ReverseOrderedDict(OrderedDict): @@ -170,7 +172,7 @@ class ReverseOrderedDict(OrderedDict): because seqOrDict is read in normal left-to-right order and each new entry goes at the beginning of the dict. Thus ReverseOrderedDict([(1, "a"), (2, "b")]) stores keys in order 2, 1. - + This has one nasty side effect: repr() shows the items in the reverse order in which they are stored internally. This is because it shows the call needed to recreate the dict. @@ -181,17 +183,18 @@ def __setitem__(self, key, value): if key not in self: self._OrderedDict__keyList.insert(0, key) dict.__setitem__(self, key, value) - + def copy(self): revCopy = self.__class__(self) revCopy._OrderedDict__keyList.reverse() return revCopy - + def __repr__(self): descrList = ["(%r, %r)" % item for item in self.items()] descrList.reverse() return "%s([%s])" % (self.__class__.__name__, ', '.join(descrList)) + if __name__ == "__main__": print("testing OrderedDict") import copy @@ -284,3 +287,4 @@ def altKeyToValue(key): dictCopy[()] = "value for ()" dictCopy._checkIntegrity() oDict._checkIntegrity() + print('Tests complete')