---
I did a bit of testing to figure out what's up here. I may have an
answer. As far as I can see, this problem exists where there are
SpinButtons that take non-whole-number values; is that accurate?
First, I made the de_DE.UTF-8 locale available by executing
sudo apt-get install language-pack-de
Then, I wrote up the following test program with a spin box:
import gtk
import locale
import sys
def ch(*args):
print "ch", s.get_text(), s.get_value()
w = gtk.Window()
a = gtk.Adjustment(50.1, 0, 100, .1, 1, 0)
s = gtk.SpinButton(a, 0, 1)
s.connect('value-changed', ch)
w.connect('destroy', lambda *args: sys.exit(0))
w.add(s)
w.show_all()
gtk.main()
When I run it with
$ LC_NUMERIC=de_DE.UTF-8 python spin.py
I see that the result of the s.get_text() call is the same string that
is shown to the user, so it's in the user's notation such as 50,1
instead of 50.1.
But the result of the s.get_value() call is the number, without the
requirement that it be converted to a string at all.
However, it appears not all widgets that you want to use as floats have
a get_value() method. (others are plain entry fields?) So that leads
to creating a function which can adapt to the circumstances.
def get_value(w):
try:
return w.get_value()
except AttributeError:
pass
oldlocale = locale.getlocale(locale.LC_NUMERIC)
try:
locale.setlocale(locale.LC_NUMERIC, "")
return locale.atof(w.get_text())
finally:
locale.setlocale(locale.LC_NUMERIC, oldlocale)
It is LC_NUMERIC that causes numbers to be formatted and parsed
according to different conventions. A second argument to setlocale of
"" selects the user's preferred convention. Here's a sample session in
the interactive interpreter showing the effect of LC_NUMERIC:
>>> import locale
>>> locale.atof("1.0")
1.0
>>> locale.format_string("%.1f", 1.0)
'1.0'
>>> locale.setlocale(locale.LC_NUMERIC, "de_DE.UTF-8")
'de_DE.UTF-8'
>>> locale.format("%.1f", 1.0)
'1,0'
>>> locale.atof("1,0")
1.0
Switching in and out of the user's LC_NUMERIC locale may be
superstition; we want to be sure that regular numbers read by Python
from other sources (like the input .pcncconf file) are going to be in
"C" format with a "." for the decimal point. Python used to
have a bug in this department which was fixed in the 2004 time frame:
http://bugs.python.org/issue774665
now Python is supposed to always accept and create the "C"-style
(decimal point=".") numbers for float() and str(), so this dance is
probably not necessary.
>>> locale.setlocale(locale.LC_NUMERIC, "de_DE.UTF-8")
'de_DE.UTF-8'
>>> locale.atof("1.0")
10.0 # Well, that's a surprise!
There may be another problem lurking where .set_text() is used.
Something similar, preferring .set_value() and falling back to
locale.format() + set_text when that's not available on a particular
widget.
I wrote the following patch but I don't feel I know how to adequately
test it. Let me know if you'd like to commit it, or feel free to commit
it yourself.
src/emc/usr_intf/pncconf/pncconf.py | 115 +++++++++++++++++++---------------
1 files changed, 64 insertions(+), 51 deletions(-)
diff --git a/src/emc/usr_intf/pncconf/pncconf.py
b/src/emc/usr_intf/pncconf/pncconf.py
index ceb0d2e..fb3144d 100755
--- a/src/emc/usr_intf/pncconf/pncconf.py
+++ b/src/emc/usr_intf/pncconf/pncconf.py
@@ -29,6 +29,7 @@ import shutil
import math
import getopt
import textwrap
+import locale
import gobject
import gtk
@@ -39,6 +40,18 @@ import xml.dom.minidom
import traceback
+def get_value(w):
+ try:
+ return w.get_value()
+ except AttributeError:
+ pass
+ oldlocale = locale.getlocale(locale.LC_NUMERIC)
+ try:
+ locale.setlocale(locale.LC_NUMERIC, "")
+ return locale.atof(w.get_text())
+ finally:
+ locale.setlocale(locale.LC_NUMERIC, oldlocale)
+
# otherwise, on hardy the user is shown spurious "[application] closed
# unexpectedly" messages but denied the ability to actually "report [the]
# problem"
@@ -3731,7 +3744,7 @@ class App:
print axis
w = self.widgets
stepdriven = rotaryaxis = encoder = 1
- def get(n): return float(w[n].get_text())
+ def get(n): return get_value(w[n])
test = self.data.findsignal(axis+"-stepgen-step")
if test == "false":stepdriven = 0
test = self.data.findsignal(axis+"-encoder-a")
@@ -3749,7 +3762,7 @@ class App:
#self.widgets['window1'].set_sensitive(0)
self.widgets.scaledialog.hide()
try:
- w[axis + "encodercounts"].set_text( "%d" % ( 4 *
float(w["encoderline"].get_text())))
+ w[axis + "encodercounts"].set_text( "%d" % ( 4 *
get_value(w["encoderline"])))
pitch = get("leadscrew")
#if self.data.units == 1 or axis =='a' : pitch = 1./pitch
if axis == 'a': factor = ((get("wormnum") / get("wormden")))
@@ -3758,7 +3771,7 @@ class App:
if stepdriven :
scale = (factor * get("steprev") * get("microstep") *
((get("pulleynum") / get("pulleyden"))))
else:
- scale = ( factor * float(w[("encoderline")].get_text()) * 4 *
(get("pulleynum") / get("pulleyden")))
+ scale = ( factor * get_value(w[("encoderline")]) * 4 *
(get("pulleynum") / get("pulleyden")))
if axis == 'a': scale = scale / 360
w[axis + "calscale"].set_text("%.1f" % scale)
w[axis + "scale"].set_text( "%.1f" % scale)
@@ -3984,10 +3997,10 @@ class App:
def axis_done(self, axis):
d = self.data
w = self.widgets
- def get_text(n): d[axis + n] = float(w[axis + n].get_text())
+ def get_text(n): d[axis + n] = get_value(w[axis + n])
def get_active(n): d[axis + n] = w[axis + n].get_active()
- d[axis + "steprev"] = int(float(w["steprev"].get_text()))
- d[axis + "microstep"] = int(float(w["microstep"].get_text()))
+ d[axis + "steprev"] = int(get_value(w["steprev"]))
+ d[axis + "microstep"] = int(get_value(w["microstep"]))
get_text("P")
get_text("I")
get_text("D")
@@ -4005,27 +4018,27 @@ class App:
get_text("outputscale")
get_text("outputoffset")
get_text("maxoutput")
- d[axis + "encodercounts"] = int(float(w["encoderline"].get_text())*4)
+ d[axis + "encodercounts"] = int(get_value(w["encoderline"])*4)
get_text("scale")
get_active("invertmotor")
get_active("invertencoder")
- d[axis + "pulleynum"] = int(float(w["pulleynum"].get_text()))
- d[axis + "pulleyden"] = int(float(w["pulleyden"].get_text()))
- d[axis + "leadscrew"] = int(float(w["leadscrew"].get_text()))
+ d[axis + "pulleynum"] = int(get_value(w["pulleynum"]))
+ d[axis + "pulleyden"] = int(get_value(w["pulleyden"]))
+ d[axis + "leadscrew"] = int(get_value(w["leadscrew"]))
d[axis + "compfilename"] = w[axis + "compfilename"].get_text()
get_active("comptype")
d[axis + "backlash"]= w[axis + "backlash"].get_value()
get_active("usecomp")
get_active("usebacklash")
- d[axis + "maxvel"] = (float(w[axis + "maxvel"].get_text())/60)
+ d[axis + "maxvel"] = (get_value(w[axis + "maxvel"])/60)
get_text("maxacc")
get_text("homepos")
get_text("minlim")
get_text("maxlim")
get_text("homesw")
- d[axis + "homesearchvel"] = (float(w[axis +
"homesearchvel"].get_text())/60)
- d[axis + "homelatchvel"] = (float(w[axis +
"homelatchvel"].get_text())/60)
- d[axis + "homefinalvel"] = (float(w[axis +
"homefinalvel"].get_text())/60)
+ d[axis + "homesearchvel"] = (get_value(w[axis + "homesearchvel"])/60)
+ d[axis + "homelatchvel"] = (get_value(w[axis + "homelatchvel"])/60)
+ d[axis + "homefinalvel"] = (get_value(w[axis + "homefinalvel"])/60)
get_active("searchdir")
get_active("latchdir")
get_active("usehomeindex")
@@ -4034,23 +4047,23 @@ class App:
def update_pps(self, axis):
w = self.widgets
d = self.data
- def get(n): return float(w[axis + n].get_text())
+ def get(n): return get_value(w[axis + n])
try:
- #pitch = float(w["leadscrew"].get_text())
+ #pitch = get_value(w["leadscrew"])
#if d.units == 1 or axis =='a' : pitch = 1./pitch
maxvps = get("maxvel")/60
- pps = (float(w[axis+"scale"].get_text()) * (maxvps))/1000
+ pps = (get_value(w[axis+"scale"]) * (maxvps))/1000
if pps == 0: raise ValueError
pps = abs(pps)
w[axis + "khz"].set_text("%.1f" % pps)
acctime = (maxvps) / get("maxacc")
accdist = acctime * .5 * (maxvps)
- maxrpm = int( (maxvps * 60) * ( float(w[axis+"scale"].get_text())/
( float(w[(axis +"encodercounts")].get_text()) ) ) )
+ maxrpm = int( (maxvps * 60) * ( get_value(w[axis+"scale"])/ (
get_value(w[(axis +"encodercounts")]) ) ) )
w[axis + "acctime"].set_text("%.4f" % acctime)
if not axis == 's':
w[axis + "accdist"].set_text("%.4f" % accdist)
- w[axis + "chartresolution"].set_text("%.7f" % (1.0 /
float(w[axis+"scale"].get_text())))
+ w[axis + "chartresolution"].set_text("%.7f" % (1.0 /
get_value(w[axis+"scale"])))
w[axis + "calscale"].set_text(w[axis+"scale"].get_text())
w[axis + "maxrpm"].set_text("%d" % maxrpm)
self.widgets.druid1.set_buttons_sensitive(1,1,1,1)
@@ -4255,7 +4268,7 @@ class App:
def on_spindle_next(self, *args):
d = self.data
w = self.widgets
- def get_text(n): d["s" + n] = float(w["s" + n].get_text())
+ def get_text(n): d["s" + n] = get_value(w["s" + n])
def get_active(n): d["s" + n] = w["s" + n].get_active()
d["ssteprev"] = int(w["steprev"].get_text())
d["smicrostep"] = int(w["microstep"].get_text())
@@ -4282,16 +4295,16 @@ class App:
d["spulleynum"] = int(w["pulleynum"].get_text())
d["spulleyden"] = int(w["pulleyden"].get_text())
d["sleadscrew"] = int(w["leadscrew"].get_text())
- d["smaxvel"] = (float(w["smaxvel"].get_text())/60)
+ d["smaxvel"] = (get_value(w["smaxvel"])/60)
get_text("maxacc")
d["sdrivertype"] = self.drivertype_toid('s',
w["sdrivertype"].get_active())
- #self.data.spindlecarrier =
float(self.widgets.spindlecarrier.get_text())
- self.data.spindlespeed1 = float(self.widgets.spindlespeed1.get_text())
- self.data.spindlespeed2 = float(self.widgets.spindlespeed2.get_text())
- self.data.spindlepwm1 = float(self.widgets.spindlepwm1.get_text())
- self.data.spindlepwm2 = float(self.widgets.spindlepwm2.get_text())
- #self.data.spindlecpr = float(self.widgets.spindlecpr.get_text())
+ #self.data.spindlecarrier = get_value(self.widgets.spindlecarrier)
+ self.data.spindlespeed1 = get_value(self.widgets.spindlespeed1)
+ self.data.spindlespeed2 = get_value(self.widgets.spindlespeed2)
+ self.data.spindlepwm1 = get_value(self.widgets.spindlepwm1)
+ self.data.spindlepwm2 = get_value(self.widgets.spindlepwm2)
+ #self.data.spindlecpr = get_value(self.widgets.spindlecpr)
def on_spindle_back(self, *args):
self.on_spindle_next()
@@ -4900,8 +4913,8 @@ class App:
w[axis + "tunedistunits"].set_text(_("inches"))
w[axis + "tunevelunits"].set_text(_("inches / minute"))
w[axis + "tuneaccunits"].set_text(_("inches / second²"))
- w[axis+"tunevel"].set_value(float(w[axis+"maxvel"].get_text()))
- w[axis+"tuneacc"].set_value(float(w[axis+"maxacc"].get_text()))
+ w[axis+"tunevel"].set_value(get_value(w[axis+"maxvel"]))
+ w[axis+"tuneacc"].set_value(get_value(w[axis+"maxacc"]))
w[axis+"tunecurrentP"].set_value(w[axis+"P"].get_value())
w[axis+"tuneorigP"].set_text("%s" % w[axis+"P"].get_value())
w[axis+"tunecurrentI"].set_value(w[axis+"I"].get_value())
@@ -4920,11 +4933,11 @@ class App:
w[axis+"tuneorigdeadband"].set_text("%s" %
w[axis+"deadband"].get_value())
w[axis+"tunecurrentsteptime"].set_value(w[axis+"steptime"].get_value())
w[axis+"tuneorigsteptime"].set_text("%s" %
w[axis+"steptime"].get_value())
-
w[axis+"tunecurrentstepspace"].set_value(float(w[axis+"stepspace"].get_text()))
+
w[axis+"tunecurrentstepspace"].set_value(get_value(w[axis+"stepspace"]))
w[axis+"tuneorigstepspace"].set_text("%s" %
w[axis+"stepspace"].get_value())
-
w[axis+"tunecurrentdirhold"].set_value(float(w[axis+"dirhold"].get_text()))
+ w[axis+"tunecurrentdirhold"].set_value(get_value(w[axis+"dirhold"]))
w[axis+"tuneorigdirhold"].set_text("%s" %
w[axis+"dirhold"].get_value())
-
w[axis+"tunecurrentdirsetup"].set_value(float(w[axis+"dirsetup"].get_text()))
+ w[axis+"tunecurrentdirsetup"].set_value(get_value(w[axis+"dirsetup"]))
w[axis+"tuneorigdirsetup"].set_text("%s" %
w[axis+"dirsetup"].get_value())
self.tunejogplus = self.tunejogminus = 0
w[axis+"tunedir"].set_active(0)
@@ -4996,7 +5009,7 @@ class App:
self.stepinvert = concount*24+1
halrun.write("setp
hm2_%s.0.gpio.%03d.invert_output %d \n"%
(self.boardname,self.stepinvert,w[axis+"invertmotor"].get_active()))
halrun.write("setp hm2_%s.0.stepgen.%02d.step_type
0 \n"% (self.boardname,compnum))
- halrun.write("setp
hm2_%s.0.stepgen.%02d.position-scale %f \n"%
(self.boardname,compnum,float(w[axis + "scale"].get_text()) ))
+ halrun.write("setp
hm2_%s.0.stepgen.%02d.position-scale %f \n"%
(self.boardname,compnum,get_value(w[axis + "scale"]) ))
halrun.write("setp hm2_%s.0.stepgen.%02d.enable
true \n"% (self.boardname,compnum))
halrun.write("net cmd steptest.0.position-cmd =>
hm2_%s.0.stepgen.%02d.position-cmd \n"% (self.boardname,compnum))
halrun.write("net feedback steptest.0.position-fb
<= hm2_%s.0.stepgen.%02d.position-fb \n"% (self.boardname,compnum))
@@ -5004,7 +5017,7 @@ class App:
halrun.write("setp hm2_%s.0.stepgen.%02d.stepspace
%d \n"% (self.boardname,compnum,w[axis+"stepspace"].get_value()))
halrun.write("setp hm2_%s.0.stepgen.%02d.dirhold
%d \n"% (self.boardname,compnum,w[axis+"dirhold"].get_value()))
halrun.write("setp hm2_%s.0.stepgen.%02d.dirsetup
%d \n"% (self.boardname,compnum,w[axis+"dirsetup"].get_value()))
- halrun.write("setp steptest.0.epsilon %f\n"%
abs(1. / float(w[axis + "scale"].get_text())) )
+ halrun.write("setp steptest.0.epsilon %f\n"%
abs(1. / get_value(w[axis + "scale"])) )
halrun.write("setp hm2_%s.0.stepgen.%02d.maxaccel
0 \n"% (self.boardname,compnum))
halrun.write("setp hm2_%s.0.stepgen.%02d.maxvel 0
\n"% (self.boardname,compnum))
halrun.write("loadusr halmeter -s pin
hm2_%s.0.stepgen.%02d.velocity-fb -g 0 500 330\n"% (self.boardname,compnum))
@@ -5042,19 +5055,19 @@ class App:
if result == gtk.RESPONSE_OK:
w[axis+"maxvel"].set_text("%s" % w[axis+"tunevel"].get_value())
w[axis+"maxacc"].set_text("%s" % w[axis+"tuneacc"].get_value())
- w[axis+"P"].set_value( float(w[axis+"tunecurrentP"].get_text()))
- w[axis+"I"].set_value( float(w[axis+"tunecurrentI"].get_text()))
- w[axis+"D"].set_value( float(w[axis+"tunecurrentD"].get_text()))
- w[axis+"FF0"].set_value(
float(w[axis+"tunecurrentFF0"].get_text()))
- w[axis+"FF1"].set_value(
float(w[axis+"tunecurrentFF1"].get_text()))
- w[axis+"FF2"].set_value(
float(w[axis+"tunecurrentFF2"].get_text()))
- w[axis+"bias"].set_value(
float(w[axis+"tunecurrentbias"].get_text()))
- w[axis+"deadband"].set_value(
float(w[axis+"tunecurrentdeadband"].get_text()))
+ w[axis+"P"].set_value( get_value(w[axis+"tunecurrentP"]))
+ w[axis+"I"].set_value( get_value(w[axis+"tunecurrentI"]))
+ w[axis+"D"].set_value( get_value(w[axis+"tunecurrentD"]))
+ w[axis+"FF0"].set_value( get_value(w[axis+"tunecurrentFF0"]))
+ w[axis+"FF1"].set_value( get_value(w[axis+"tunecurrentFF1"]))
+ w[axis+"FF2"].set_value( get_value(w[axis+"tunecurrentFF2"]))
+ w[axis+"bias"].set_value( get_value(w[axis+"tunecurrentbias"]))
+ w[axis+"deadband"].set_value(
get_value(w[axis+"tunecurrentdeadband"]))
w[axis+"tunecurrentbias"].set_value(w[axis+"bias"].get_value())
-
w[axis+"steptime"].set_value(float(w[axis+"tunecurrentsteptime"].get_text()))
-
w[axis+"stepspace"].set_value(float(w[axis+"tunecurrentstepspace"].get_text()))
-
w[axis+"dirhold"].set_value(float(w[axis+"tunecurrentdirhold"].get_text()))
-
w[axis+"dirsetup"].set_value(float(w[axis+"tunecurrentdirsetup"].get_text()))
+
w[axis+"steptime"].set_value(get_value(w[axis+"tunecurrentsteptime"]))
+
w[axis+"stepspace"].set_value(get_value(w[axis+"tunecurrentstepspace"]))
+
w[axis+"dirhold"].set_value(get_value(w[axis+"tunecurrentdirhold"]))
+
w[axis+"dirsetup"].set_value(get_value(w[axis+"tunecurrentdirsetup"]))
w[axis+"invertmotor"].set_active(w[axis+"tuneinvertmotor"].get_active())
w[axis+"invertencoder"].set_active(w[axis+"tuneinvertencoder"].get_active())
if not amp == "false":
@@ -5160,8 +5173,8 @@ class App:
#dir = axis + "dir"
boardname = self.data.mesa0_currentfirmwaredata[0]
firmware = self.data.mesa0_currentfirmwaredata[1]
- fastdac = float(widgets["fastdac"].get_text())
- slowdac = float(widgets["slowdac"].get_text())
+ fastdac = get_value(widgets["fastdac"])
+ slowdac = get_value(widgets["slowdac"])
dacspeed = widgets.Dac_speed_fast.get_active()
if self.data.findsignal( (axis + "-pwm-pulse")) =="false" or
self.data.findsignal( (axis + "-encoder-a")) =="false":
@@ -5312,12 +5325,12 @@ class App:
axis = self.axis_under_test
if axis is None: return
halrun = self.halrun
- if self.widgets.Dac_speed_fast.get_active() == True:output =
float(self.widgets.fastdac.get_text())
- else: output = float(self.widgets.slowdac.get_text())
+ if self.widgets.Dac_speed_fast.get_active() == True:output =
get_value(self.widgets.fastdac)
+ else: output = get_value(self.widgets.slowdac)
if self.jogminus == 1:output = output * -1
elif not self.jogplus == 1:output = 0
if self.widgets.testinvertmotor.get_active() == True: output = output
* -1
- output += float(self.widgets.testoutputoffset.get_text())
+ output += get_value(self.widgets.testoutputoffset)
if not self.amp == "false":
halrun.write("setp %s %d\n"% (self.amp, self.enable_amp))
halrun.write("""setp %(scalepin)s.scale %(scale)d\n""" % {
'scalepin':self.enc, 'scale': self.enc_scale})
--
1.6.3.3
------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev
_______________________________________________
Emc-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/emc-developers