---
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
Emc-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-developers

Reply via email to