1 year ago
#43552
Codejoy
python2 to python3 conversion cannot find imports now. Namespacing issue?
While I am able to fix this and it is not a huge issue. I am curious if I am doing something wrong or went about something wrong. I inherited a codebase that is python2 to upgrade it to python3. So I just bit the bullet and dug in, started with a 2to3 conversion. Now bit by bit I am running and seeing where it croaks, fixing it and rinse repeat. I noticed most the issues are in the module imports from local modules created.
An example:
a file in a folder called Label.py has the line:
__all__ = ['Label', 'BoolLabel', 'StrLabel', 'IntLabel', 'FloatLabel']
class Label(tkinter.Label, CtxMenuMixin, IsCurrentMixin, SeverityMixin):
...code...
...code...
class FloatLabel(Label):
...code...
...code...
This file is used by another one called GrayImageDispWdg.py and in that it is trying to do a call as such:
self.currXPosWdg = Label.FloatLabel()
This USED to work in python2.7 now though after the conversion I get a:
type object 'Label' has no attribute 'FloatLabel'
Now I can fix this at the top of say GrayImageDispWdg.py
file by instead of saying just this:
from . import Label
if I also say:
from . import FloatLabel
and then change the line:
self.currXPosWdg = Label.FloatLabel()
to
self.currXPosWdg = FloatLabel()
Then it seems to work, but I am doing this a ton on all files since the conversion. Maybe I had something wrong setup? Maybe was some sort of path issue I missed? (I am not a Python guru by any means whilst editing / converting this stuff either)
__all__ = ['Label', 'BoolLabel', 'StrLabel', 'IntLabel', 'FloatLabel', 'DMSLabel']
import sys
import tkinter
import RO.Constants
import RO.MathUtil
import RO.StringUtil
from . import CtxMenu
from . import CtxMenuMixin
from .SeverityMixin import SeverityMixin
from .IsCurrentMixin import IsCurrentMixin
class Label(tkinter.Label, CtxMenuMixin, IsCurrentMixin, SeverityMixin):
"""Base class for labels (display ROWdgs); do not use directly.
Inputs:
- formatStr: formatting string; if omitted, formatFunc is used.
Displayed value is formatStr % value.
- formatFunc: formatting function; ignored if formatStr specified.
Displayed value is formatFunc(value).
- helpText short text for hot help
- helpURL URL for on-line help
- isCurrent is value current?
- severity one of RO.Constants.sevNormal, sevWarning or sevError
- **kargs: all other keyword arguments go to Tkinter.Label;
the defaults are anchor="e", justify="right"
Inherited methods include:
getIsCurrent, setIsCurrent
getSeverity, setSeverity
Note: if display formatting fails (raises an exception)
then "?%r?" % value is displayed.
"""
def __init__ (self,
master,
formatStr = None,
formatFunc = str,
helpText = None,
helpURL = None,
isCurrent = True,
severity = RO.Constants.sevNormal,
**kargs):
kargs.setdefault("anchor", "e")
kargs.setdefault("justify", "right")
tkinter.Label.__init__(self, master, **kargs)
CtxMenuMixin.__init__(self, helpURL=helpURL)
IsCurrentMixin.__init__(self, isCurrent)
SeverityMixin.__init__(self, severity)
self._formatStr = formatStr
if formatStr != None:
formatFunc = self._formatFromStr
self._formatFunc = formatFunc
self.helpText = helpText
self._value = None
def get(self):
"""Return a tuple consisting of (set value, isCurrent).
If the value is None then it is invalid or unknown.
If isCurrent is false then the value is suspect
Otherwise the value is valid and current.
"""
return (self._value, self._isCurrent)
def getFormatted(self):
"""Return a tuple consisting of the (displayed value, isCurrent).
If the value is None then it is invalid.
If isCurrent is false then the value is suspect
Otherwise the value is valid and current.
"""
if self._value == None:
return (None, self._isCurrent)
else:
return (self["text"], self._isCurrent)
def clear(self, isCurrent=1):
"""Clear the display; leave severity unchanged.
"""
self.set(value="", isCurrent=isCurrent)
def set(self,
value,
isCurrent = True,
severity = None,
**kargs):
"""Set the value
Inputs:
- value: the new value
- isCurrent: is value current (if not, display with bad background color)
- severity: the new severity, one of: RO.Constants.sevNormal, sevWarning or sevError;
if omitted, the severity is left unchanged
kargs is ignored; it is only present for compatibility with KeyVariable callbacks.
Raises an exception if the value cannot be coerced.
"""
# print "RO.Wdg.Label.set called: value=%r, isCurrent=%r, **kargs=%r" % (value, isCurrent, kargs)
self._value = value
self.setIsCurrent(isCurrent)
if severity != None:
self.setSeverity(severity)
self._updateText()
def setNotCurrent(self):
"""Mark the data as not current.
To mark the value as current again, set a new value.
"""
self.setIsCurrent(False)
def _formatFromStr(self, value):
"""Format function based on formatStr.
"""
return self._formatStr % value
def _updateText(self):
"""Updates the displayed value. Ignores isCurrent and severity.
"""
if self._value == None:
self["text"] = ""
else:
try:
self["text"] = self._formatFunc(self._value)
except Exception as e:
sys.stderr.write("format of value %r failed with error: %s\n" % (self._value, e))
self["text"] = "?%r?" % (self._value,)
class BoolLabel(Label):
"""Label to display string data.
Inputs are those for Label, but formatStr and formatFunc are forbidden.
"""
def __init__ (self,
master,
helpText = None,
helpURL = None,
trueValue = "True",
falseValue = "False",
isCurrent = True,
**kargs
):
assert "formatStr" not in kargs, "formatStr not allowed for %s" % self.__class__.__name__
assert "formatFunc" not in kargs, "formatFunc not allowed for %s" % self.__class__.__name__
def formatFnct(val):
if val:
return trueValue
else:
return falseValue
Label.__init__(self,
master,
formatFunc = formatFnct,
helpText = helpText,
helpURL = helpURL,
isCurrent = isCurrent,
**kargs)
class StrLabel(Label):
"""Label to display string data.
Inputs are those for Label but the default formatFunc is str.
"""
def __init__ (self,
master,
helpText = None,
helpURL = None,
isCurrent = True,
**kargs
):
kargs.setdefault("formatFunc", str)
Label.__init__(self,
master,
helpText = helpText,
helpURL = helpURL,
isCurrent = isCurrent,
**kargs)
class IntLabel(Label):
"""Label to display integer data; truncates floating point data
Inputs are those for Label, but the default formatStr is "%s" and formatFunc is forbidden.
"""
def __init__ (self,
master,
helpText = None,
helpURL = None,
isCurrent = True,
**kargs
):
kargs.setdefault("formatStr", "%d")
assert "formatFunc" not in kargs, "formatFunc not allowed for %s" % self.__class__.__name__
Label.__init__(self,
master,
helpText = helpText,
helpURL = helpURL,
isCurrent = isCurrent,
**kargs)
class FloatLabel(Label):
"""Label to display floating point data.
If you specify a format string, that is used and the specified is ignored
else you must specify a precision, in which case the data is displayed
as without an exponent and with "precision" digits past the decimal.
The default precision is 2 digits.
Inputs:
- precision: number of digits past the decimal point; ignored if formatStr specified
The other inputs are those for Label but formatFunc is forbidden.
"""
def __init__ (self,
master,
formatStr=None,
precision=2,
helpText = None,
helpURL = None,
isCurrent = True,
**kargs):
assert "formatFunc" not in kargs, "formatFunc not allowed for %s" % self.__class__.__name__
# handle default format string
if formatStr == None:
formatStr = "%." + str(precision) + "f"
# test and set format string
try:
formatStr % (1.1,)
except:
raise ValueError("Invalid floating point format string %s" % (formatStr,))
Label.__init__(self,
master,
formatStr = formatStr,
helpText = helpText,
helpURL = helpURL,
isCurrent = isCurrent,
**kargs)
class DMSLabel(Label):
"""Label to display floating point data as dd:mm:ss.ss.
Has the option to store data in degrees but display in hh:mm:ss.ss;
this option can be changed at any time and the display updates correctly.
Inputs:
- precision: number of digits past the decimal point
- nFields: number of sexagesimal fields to display
- cnvDegToHrs: if True, data is in degrees but display is in hours
The other inputs are those for Label, but formatStr and formatFunc are forbidden.
"""
def __init__ (self,
master,
precision,
nFields = 3,
cvtDegToHrs = False,
helpText = None,
helpURL = None,
isCurrent = True,
**kargs):
assert "formatStr" not in kargs, "formatStr not allowed for %s" % self.__class__.__name__
assert "formatFunc" not in kargs, "formatFunc not allowed for %s" % self.__class__.__name__
self.precision = precision
self.nFields = nFields
self.cvtDegToHrs = cvtDegToHrs
Label.__init__(self,
master,
formatFunc = self.formatFunc,
helpText = helpText,
helpURL = helpURL,
isCurrent = isCurrent,
**kargs)
def formatFunc(self, value):
if self.cvtDegToHrs and value != None:
value = value / 15.0
return RO.StringUtil.dmsStrFromDeg (
value,
precision = self.precision,
nFields = self.nFields,
)
def setCvtDegToHrs(self, cvtDegToHrs):
if RO.MathUtil.logNE(self.cvtDegToHrs, cvtDegToHrs):
self.cvtDegToHrs = cvtDegToHrs
self._updateText()
if __name__ == "__main__":
from . import PythonTk
from RO.TkUtil import Timer
root = PythonTk.PythonTk()
wdgSet = (
BoolLabel(root,
helpText = "Bool label",
),
StrLabel(root,
helpText = "String label",
),
IntLabel(root,
width=5,
helpText = "Int label; width=5",
),
FloatLabel(root,
precision=2,
width=5,
helpText = "Float label; precision = 2, width=5",
),
FloatLabel(root,
formatStr="%.5g",
width=8,
helpText = "Float label; format = '\%.5g', width = 8",
),
DMSLabel(root,
precision=2,
width=10,
helpText = "DMS label; precision = 2, width = 10",
),
DMSLabel(root,
precision=2,
cvtDegToHrs=1,
width=10,
helpText = "DMS label; precision = 2, width = 10, convert degrees to hours",
),
)
for wdg in wdgSet:
wdg.pack(fill=tkinter.X)
# a list of (value, isCurrent) pairs
testData = [
("some text", True),
("invalid text", False),
(0, True),
("", True),
(False, True),
(1, True),
(1234567890, True),
(1234567890, False),
(1.1, True),
(1.9, True),
(-1.1, True),
(-1.9, True),
(-0.001, True),
(-1.9, False),
]
ind = 0
def displayNext():
global ind, testData
val = testData[ind]
print("\nvalue = %r, isCurrent = %s" % tuple(val))
for wdg in wdgSet:
wdg.set(*val)
ind += 1
if ind < len(testData):
Timer(1.2, displayNext)
Timer(1.2, displayNext)
root.mainloop()
python
python-3.x
import
python-2to3
0 Answers
Your Answer