diff --git a/io_import_scene_mhx.py b/io_import_scene_mhx.py
index 1a7cf9f57e9d4b286b7946cf48c64c1c2c51205c..1d7a572ad35019bb583b3d1d90dae266f0b85410 100644
--- a/io_import_scene_mhx.py
+++ b/io_import_scene_mhx.py
@@ -38,7 +38,7 @@ Alternatively, run the script in the script editor (Alt-P), and access from the
 bl_info = {
     'name': 'Import: MakeHuman (.mhx)',
     'author': 'Thomas Larsson',
-    'version': (1, 16, 3),
+    'version': (1, 16, 4),
     "blender": (2, 68, 0),
     'location': "File > Import > MakeHuman (.mhx)",
     'description': 'Import files in the MakeHuman eXchange format (.mhx)',
@@ -92,8 +92,6 @@ theTempDatum = None
 theMessage = ""
 theMhxFile = ""
 
-todo = []
-
 #
 #    toggle flags
 #
@@ -203,7 +201,7 @@ Plural = {
 #
 
 def readMhxFile(filePath):
-    global todo, nErrors, theScale, theArmature, defaultScale, One
+    global nErrors, theScale, theArmature, defaultScale, One
     global toggle, warnedVersion, theMessage, alpha7, theDir
 
     defaultScale = theScale
@@ -295,16 +293,6 @@ def readMhxFile(filePath):
     print( "Parsing" )
     parse(tokens)
 
-    for (expr, glbals, lcals) in todo:
-        try:
-            print("Doing %s" % expr)
-            exec(expr, glbals, lcals)
-        except:
-            msg = "Failed: %s\n" % expr
-            print( msg )
-            nErrors += 1
-            #MyError(msg)
-
     scn.objects.active = theArmature
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.select_all(action='DESELECT')
@@ -320,10 +308,10 @@ def readMhxFile(filePath):
     return
 
 #
-#    getObject(name, var, glbals, lcals):
+#    getObject(name, var):
 #
 
-def getObject(name, var, glbals, lcals):
+def getObject(name, var):
     try:
         ob = loadedData['Object'][name]
     except:
@@ -479,8 +467,6 @@ def parse(tokens):
 #
 
 def parseDefaultType(typ, args, tokens):
-    global todo
-
     name = args[0]
     data = None
     expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
@@ -492,7 +478,7 @@ def parseDefaultType(typ, args, tokens):
         return None
 
     for (key, val, sub) in tokens:
-        defaultKey(key, val, sub, 'data', [], globals(), locals())
+        defaultKey(key, val, sub, data)
     return data
 
 #
@@ -537,7 +523,7 @@ def parseAction(args, tokens):
         if key == 'FCurve':
             fcu = parseActionFCurve(act, ob, val, sub)
         else:
-            defaultKey(key, val, sub, 'act', [], globals(), locals())
+            defaultKey(key, val, sub, act)
     ob.animation_data.action = None
     bpy.ops.object.mode_set(mode='OBJECT')
     return act
@@ -625,7 +611,7 @@ def parseActionFCurve(act, ob, args, tokens):
                 #print(tokens)
                 #MyError("kp", fcu, n, len(fcu.keyframe_points), val)
         else:
-            defaultKey(key, val, sub, 'fcu', [], globals(), locals())
+            defaultKey(key, val, sub, fcu)
     return fcu
 
 def parseKeyFramePoint(pt, args, tokens):
@@ -651,7 +637,7 @@ def parseAnimationData(rna, args, tokens):
         if key == 'FCurve':
             fcu = parseAnimDataFCurve(adata, rna, val, sub)
         else:
-            defaultKey(key, val, sub, 'adata', [], globals(), locals())
+            defaultKey(key, val, sub, adata)
     return adata
 
 def parseAnimDataFCurve(adata, rna, args, tokens):
@@ -673,7 +659,7 @@ def parseAnimDataFCurve(adata, rna, args, tokens):
             pt = parseKeyFramePoint(pt, val, sub)
             n += 1
         else:
-            defaultKey(key, val, sub, 'fcu', [], globals(), locals())
+            defaultKey(key, val, sub, fcu)
     return fcu
 
 """
@@ -704,7 +690,7 @@ def parseDriver(adata, dataPath, index, rna, args, tokens):
         if key == 'DriverVariable':
             var = parseDriverVariable(drv, rna, val, sub)
         else:
-            defaultKey(key, val, sub, 'drv', [], globals(), locals())
+            defaultKey(key, val, sub, drv)
     return fcu
 
 def parseDriverVariable(drv, rna, args, tokens):
@@ -717,14 +703,14 @@ def parseDriverVariable(drv, rna, args, tokens):
             parseDriverTarget(var, nTarget, rna, val, sub)
             nTarget += 1
         else:
-            defaultKey(key, val, sub, 'var', [], globals(), locals())
+            defaultKey(key, val, sub, var)
     return var
 
 def parseFModifier(fcu, args, tokens):
     fmod = fcu.modifiers.new(args[0])
     #fmod = fcu.modifiers[0]
     for (key, val, sub) in tokens:
-        defaultKey(key, val, sub, 'fmod', [], globals(), locals())
+        defaultKey(key, val, sub, fmod)
     return fmod
 
 """
@@ -749,7 +735,7 @@ def parseDriverTarget(var, nTarget, rna, args, tokens):
             else:
                 targ.data_path = propNames(val)[1]
         else:
-            defaultKey(key, val, sub, 'targ', [], globals(), locals())
+            defaultKey(key, val, sub, targ)
     return targ
 
 
@@ -760,7 +746,6 @@ def parseDriverTarget(var, nTarget, rna, args, tokens):
 #
 
 def parseMaterial(args, tokens):
-    global todo
     name = args[0]
     mat = bpy.data.materials.new(name)
     if mat is None:
@@ -786,12 +771,11 @@ def parseMaterial(args, tokens):
             parseAnimationData(mat, val, sub)
         else:
             exclude = ['specular_intensity', 'tangent_shading']
-            defaultKey(key, val, sub, 'mat', [], globals(), locals())
+            defaultKey(key, val, sub, mat)
 
     return mat
 
 def parseMTex(mat, args, tokens):
-    global todo
     index = int(args[0])
     texname = args[1]
     texco = args[2]
@@ -802,12 +786,11 @@ def parseMTex(mat, args, tokens):
     mtex.texture = tex
 
     for (key, val, sub) in tokens:
-        defaultKey(key, val, sub, "mtex", [], globals(), locals())
+        defaultKey(key, val, sub, mtex)
 
     return mtex
 
 def parseTexture(args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing texture %s" % args )
     name = args[0]
@@ -828,35 +811,32 @@ def parseTexture(args, tokens):
             tex.use_nodes = True
             parseNodeTree(tex.node_tree, val, sub)
         else:
-            defaultKey(key, val,  sub, "tex", ['use_nodes', 'use_textures', 'contrast', 'use_alpha'], globals(), locals())
+            defaultKey(key, val, sub, tex, ['use_nodes', 'use_textures', 'contrast', 'use_alpha'])
 
     return tex
 
 def parseRamp(data, args, tokens):
-    nvar = "data.%s" % args[0]
-    use = "data.use_%s = True" % args[0]
-    exec(use)
-    ramp = eval(nvar)
+    setattr(data, "use_%s" % args[0], True)
+    ramp = getattr(data, args[0])
     elts = ramp.elements
     n = 0
     for (key, val, sub) in tokens:
-        # print("Ramp", key, val)
         if key == 'Element':
             elts[n].color = eval(val[0])
             elts[n].position = eval(val[1])
             n += 1
         else:
-            defaultKey(key, val,  sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
+            defaultKey(key, val, sub, tex, ['use_nodes', 'use_textures', 'contrast'])
 
 def parseSSS(mat, args, tokens):
     sss = mat.subsurface_scattering
     for (key, val, sub) in tokens:
-        defaultKey(key, val, sub, "sss", [], globals(), locals())
+        defaultKey(key, val, sub, sss)
 
 def parseStrand(mat, args, tokens):
     strand = mat.strand
     for (key, val, sub) in tokens:
-        defaultKey(key, val, sub, "strand", [], globals(), locals())
+        defaultKey(key, val, sub, strand)
 
 #
 #    parseNodeTree(tree, args, tokens):
@@ -873,7 +853,7 @@ def parseNodeTree(tree, args, tokens):
         if key == 'Node':
             parseNodes(tree.nodes, val, sub)
         else:
-            defaultKey(key, val, sub, "tree", [], globals(), locals())
+            defaultKey(key, val, sub, tree)
 
 def parseNodes(nodes, args, tokens):
     print("Nodes", nodes, args)
@@ -885,7 +865,7 @@ def parseNodes(nodes, args, tokens):
         elif key == 'Outputs':
             parseSocket(node.outputs, val, sub)
         else:
-            defaultKey(key, val, sub, "node", [], globals(), locals())
+            defaultKey(key, val, sub, node)
 
 def parseNode(node, args, tokens):
     print("Node", node, args)
@@ -897,7 +877,7 @@ def parseNode(node, args, tokens):
         elif key == 'Outputs':
             parseSocket(node.outputs, val, sub)
         else:
-            defaultKey(key, val, sub, "node", [], globals(), locals())
+            defaultKey(key, val, sub, node)
 
 def parseSocket(socket, args, tokens):
     print("Socket", socket, args)
@@ -906,7 +886,7 @@ def parseSocket(socket, args, tokens):
         if key == 'Node':
             parseNode(tree.nodes, val, sub)
         else:
-            defaultKey(key, val, sub, "tree", [], globals(), locals())
+            defaultKey(key, val, sub, tree)
 
 
 
@@ -932,7 +912,6 @@ def loadImage(relFilepath):
 
 
 def parseImage(args, tokens):
-    global todo
     imgName = args[0]
     img = None
     for (key, val, sub) in tokens:
@@ -945,7 +924,7 @@ def parseImage(args, tokens):
                 return None
             img.name = imgName
         else:
-            defaultKey(key, val,  sub, "img", ['depth', 'dirty', 'has_data', 'size', 'type', 'use_premultiply'], globals(), locals())
+            defaultKey(key, val, sub, img, ['depth', 'dirty', 'has_data', 'size', 'type', 'use_premultiply'])
     print ("Image %s" % img )
     loadedData['Image'][imgName] = img
     return img
@@ -997,7 +976,7 @@ def parseObject(args, tokens):
         elif key == 'FieldSettings':
             parseDefault(ob.field, sub, {}, [])
         else:
-            defaultKey(key, val, sub, "ob", ['type', 'data'], globals(), locals())
+            defaultKey(key, val, sub, ob, ['type', 'data'])
 
     if bpy.context.object == ob:
         if ob.type == 'MESH':
@@ -1061,7 +1040,7 @@ def parseModifier(ob, args, tokens):
             else:
                 MyError("Unknown hook %s" % val)
         else:
-            defaultKey(key, val, sub, 'mod', [], globals(), locals())
+            defaultKey(key, val, sub, mod)
     return mod
 
 def hookAssignNth(mod, n, select, points):
@@ -1106,7 +1085,7 @@ def parseParticleSystem(ob, args, tokens):
         if key == 'Particles':
             parseParticles(psys, val, sub)
         else:
-            defaultKey(key, val, sub, 'psys', [], globals(), locals())
+            defaultKey(key, val, sub, psys)
     return psys
 
 def parseParticles(psys, args, tokens):
@@ -1119,7 +1098,7 @@ def parseParticles(psys, args, tokens):
             n += 1
         else:
             for par in particles:
-                defaultKey(key, val, sub, 'par', [], globals(), locals())
+                defaultKey(key, val, sub, par)
     bpy.ops.particle.particle_edit_toggle()
     return particles
 
@@ -1153,7 +1132,7 @@ def unpackList(list_of_tuples):
 #
 
 def parseMesh (args, tokens):
-    global todo, BMeshAware
+    global BMeshAware
     if verbosity > 2:
         print( "Parsing mesh %s" % args )
 
@@ -1214,7 +1193,7 @@ def parseMesh (args, tokens):
             if mat:
                 me.materials.append(mat)
         else:
-            defaultKey(key, val,  sub, "me", [], globals(), locals())
+            defaultKey(key, val, sub, me)
 
     for (key, val, sub) in tokens:
         if key == 'Faces':
@@ -1333,7 +1312,7 @@ def parseUvTextureBMesh(args, tokens, me):
         if key == 'Data':
             parseUvTexDataBMesh(val, sub, uvloop.data)
         else:
-            defaultKey(key, val,  sub, "uvtex", [], globals(), locals())
+            defaultKey(key, val, sub, uvtex)
     return
 
 def parseUvTexDataBMesh(args, tokens, data):
@@ -1359,7 +1338,7 @@ def parseUvTextureNoBMesh(args, tokens, me):
         if key == 'Data':
             parseUvTexDataNoBMesh(val, sub, uvtex.data)
         else:
-            defaultKey(key, val,  sub, "uvtex", [], globals(), locals())
+            defaultKey(key, val, sub, uvtex)
     return
 
 def parseUvTexDataNoBMesh(args, tokens, data):
@@ -1388,7 +1367,7 @@ def parseVertColorLayer(args, tokens, me):
         if key == 'Data':
             parseVertColorData(val, sub, vcol.data)
         else:
-            defaultKey(key, val,  sub, "vcol", [], globals(), locals())
+            defaultKey(key, val, sub, vcol)
     return
 
 def parseVertColorData(args, tokens, data):
@@ -1509,7 +1488,7 @@ def addShapeKey(ob, name, vgroup, tokens):
             pt[1] += theScale*float(val[2])
             pt[2] += theScale*float(val[3])
         else:
-            defaultKey(key, val,  sub, "skey", [], globals(), locals())
+            defaultKey(key, val, sub, skey)
 
     return
 
@@ -1560,7 +1539,7 @@ def parseArmature (args, tokens):
                 bone['Roll'] = rolls[bone.name]
             bpy.ops.object.mode_set(mode='EDIT')
         else:
-            defaultKey(key, val,  sub, "amt", ['MetaRig'], globals(), locals())
+            defaultKey(key, val, sub, amt, ['MetaRig'])
     bpy.ops.object.mode_set(mode='OBJECT')
 
     return amt
@@ -1570,8 +1549,6 @@ def parseArmature (args, tokens):
 #
 
 def parseBone(bone, amt, tokens, heads, tails):
-    global todo
-
     for (key, val, sub) in tokens:
         if key == "head":
             bone.head = (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2]))
@@ -1582,7 +1559,7 @@ def parseBone(bone, amt, tokens, heads, tails):
         elif key == 'hide' and val[0] == 'True':
             name = bone.name
         else:
-            defaultKey(key, val,  sub, "bone", [], globals(), locals())
+            defaultKey(key, val, sub, bone)
     return bone
 
 #
@@ -1590,7 +1567,6 @@ def parseBone(bone, amt, tokens, heads, tails):
 #
 
 def parsePose (args, tokens):
-    global todo
     name = args[0]
     ob = loadedData['Object'][name]
     bpy.context.scene.objects.active = ob
@@ -1610,7 +1586,7 @@ def parsePose (args, tokens):
             pb = pbones[bone]
             pb[prop] = value
         else:
-            defaultKey(key, val,  sub, "ob.pose", [], globals(), locals())
+            defaultKey(key, val, sub, ob.pose)
     bpy.ops.object.mode_set(mode='OBJECT')
     return ob
 
@@ -1621,7 +1597,6 @@ def parsePose (args, tokens):
 #
 
 def parseBoneGroup(pose, nGrps, args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing bonegroup %s" % args )
     name = args[0]
@@ -1629,11 +1604,10 @@ def parseBoneGroup(pose, nGrps, args, tokens):
     bg = pose.bone_groups.active
     loadedData['BoneGroup'][name] = bg
     for (key, val, sub) in tokens:
-        defaultKey(key, val,  sub, "bg", [], globals(), locals())
+        defaultKey(key, val, sub, bg)
     return
 
 def parsePoseBone(pbones, ob, args, tokens):
-    global todo
     if invalid(args[1]):
         return
     name = args[0]
@@ -1648,8 +1622,7 @@ def parsePoseBone(pbones, ob, args, tokens):
         elif key == 'bpyops':
             amt.bones.active = pb.bone
             expr = "bpy.ops.%s" % val[0]
-            print(expr)
-            exec(expr)
+            raise MhxError("MHX bug: Must not exec %s" % expr)
         elif key == 'ik_dof':
             parseArray(pb, ["ik_dof_x", "ik_dof_y", "ik_dof_z"], val)
         elif key == 'ik_limit':
@@ -1666,16 +1639,13 @@ def parsePoseBone(pbones, ob, args, tokens):
             #bpy.ops.object.mode_set(mode='POSE')
 
         else:
-            defaultKey(key, val,  sub, "pb", [], globals(), locals())
-    #print("pb %s done" % name)
+            defaultKey(key, val, sub, pb)
     return
 
 def parseArray(data, exts, args):
     n = 1
     for ext in exts:
-        expr = "data.%s = %s" % (ext, args[n])
-        # print(expr)
-        exec(expr)
+        setattr(data, ext, eval(args[n]))
         n += 1
     return
 
@@ -1714,7 +1684,7 @@ def parseConstraint(constraints, pb, args, tokens):
         elif key == 'rot_lock':
             parseArray(cns, ["lock_rotation_x", "lock_rotation_y", "lock_rotation_z"], val)
         else:
-            defaultKey(key, val,  sub, "cns", ["use_target"], globals(), locals())
+            defaultKey(key, val, sub, cns, ["use_target"])
 
 
     #print("cns %s done" % cns.name)
@@ -1729,7 +1699,6 @@ def parseConstraint(constraints, pb, args, tokens):
 #
 
 def parseCurve (args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing curve %s" % args )
     bpy.ops.object.add(type='CURVE')
@@ -1739,11 +1708,10 @@ def parseCurve (args, tokens):
         if key == 'Spline':
             parseSpline(cu, val, sub)
         else:
-            defaultKey(key, val, sub, "cu", [], globals(), locals())
+            defaultKey(key, val, sub, cu)
     return
 
 def parseTextCurve (args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing text curve %s" % args )
     bpy.ops.object.text_add()
@@ -1761,7 +1729,7 @@ def parseTextCurve (args, tokens):
         elif key == 'TextBox':
             parseCollection(txt.body_format, sub, [])
         else:
-            defaultKey(key, val, sub, "txt", [], globals(), locals())
+            defaultKey(key, val, sub, txt)
     return
 
 
@@ -1786,7 +1754,7 @@ def parseSpline(cu, args, tokens):
             parsePoint(spline.points[n], val, sub)
             n += 1
         else:
-            defaultKey(key, val, sub, "spline", [], globals(), locals())
+            defaultKey(key, val, sub, spline)
     return
 
 def parseBezier(bez, args, tokens):
@@ -1809,7 +1777,6 @@ def parsePoint(pt, args, tokens):
 #
 
 def parseLattice (args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing lattice %s" % args )
     bpy.ops.object.add(type='LATTICE')
@@ -1818,11 +1785,10 @@ def parseLattice (args, tokens):
         if key == 'Points':
             parseLatticePoints(val, sub, lat.points)
         else:
-            defaultKey(key, val, sub, "lat", [], globals(), locals())
+            defaultKey(key, val, sub, lat)
     return
 
 def parseLatticePoints(args, tokens, points):
-    global todo
     n = 0
     for (key, val, sub) in tokens:
         if key == 'pt':
@@ -1839,7 +1805,6 @@ def parseLatticePoints(args, tokens, points):
 #
 
 def parseLamp (args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing lamp %s" % args )
     bpy.ops.object.add(type='LAMP')
@@ -1848,7 +1813,7 @@ def parseLamp (args, tokens):
         if key == 'FalloffCurve':
             parseFalloffCurve(lamp.falloff_curve, val, sub)
         else:
-            defaultKey(key, val, sub, "lamp", [], globals(), locals())
+            defaultKey(key, val, sub, lamp)
     return
 
 def parseFalloffCurve(focu, args, tokens):
@@ -1860,7 +1825,6 @@ def parseFalloffCurve(focu, args, tokens):
 #
 
 def parseGroup (args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing group %s" % args )
 
@@ -1871,11 +1835,10 @@ def parseGroup (args, tokens):
         if key == 'Objects':
             parseGroupObjects(val, sub, grp)
         else:
-            defaultKey(key, val, sub, "grp", [], globals(), locals())
+            defaultKey(key, val, sub, grp)
     return
 
 def parseGroupObjects(args, tokens, grp):
-    global todo
     rig = None
     for (key, val, sub) in tokens:
         if key == 'ob':
@@ -1898,7 +1861,6 @@ def parseGroupObjects(args, tokens, grp):
 #
 
 def parseWorld (args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing world %s" % args )
     world = bpy.context.scene.world
@@ -1910,7 +1872,7 @@ def parseWorld (args, tokens):
         elif key == 'Stars':
             parseDefault(world.stars, sub, {}, [])
         else:
-            defaultKey(key, val, sub, "world", [], globals(), locals())
+            defaultKey(key, val, sub, world)
     return
 
 #
@@ -1920,7 +1882,6 @@ def parseWorld (args, tokens):
 #
 
 def parseScene (args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing scene %s" % args )
     scn = bpy.context.scene
@@ -1947,11 +1908,10 @@ def parseScene (args, tokens):
         elif key == 'UnitSettings':
             parseDefault(scn.unit_settings, sub, {}, [])
         else:
-            defaultKey(key, val, sub, "scn", [], globals(), locals())
+            defaultKey(key, val, sub, scn)
     return
 
 def parseRenderSettings(render, args, tokens):
-    global todo
     if verbosity > 2:
         print( "Parsing RenderSettings %s" % args )
     for (key, val, sub) in tokens:
@@ -1959,7 +1919,7 @@ def parseRenderSettings(render, args, tokens):
             pass
             #parseDefault(scn.layers, sub, [])
         else:
-            defaultKey(key, val, sub, "render", [], globals(), locals())
+            defaultKey(key, val, sub, render)
     return
 
 #
@@ -1967,15 +1927,13 @@ def parseRenderSettings(render, args, tokens):
 #
 
 def parseDefineProperty(args, tokens):
-    expr = "bpy.types.Object.%s = %sProperty" % (args[0], args[1])
+    prop = "%sProperty" % (args[1])
     c = '('
     for option in args[2:]:
-        expr += "%s %s" % (c, option)
+        prop += "%s %s" % (c, option)
         c = ','
-    expr += ')'
-    #print(expr)
-    exec(expr)
-    #print("Done")
+    prop += ')'
+    setattr(bpy.types.Object, args[0], prop)
     return
 
 #
@@ -2074,7 +2032,7 @@ def deleteDiamonds(ob):
     return
 
 #
-#    defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
+#    defaultKey(ext, args, tokens, data, exclude):
 #
 
 theProperty = None
@@ -2107,7 +2065,7 @@ def propNames(string):
         return string, '["%s"]' % string
 
 
-def defProp(args, var, glbals, lcals):
+def defProp(args, var):
     proptype = args[0]
     name = propNames(args[1])[0]
     value = args[2]
@@ -2116,74 +2074,68 @@ def defProp(args, var, glbals, lcals):
         rest += ", " + args[4]
 
     if name:
-        #expr = 'bpy.types.Object.%s = %sProperty(%s)' % (name, proptype, rest)
-        expr = '%s["%s"] = %s' % (var, name, value)
-        exec(expr, glbals, lcals)
+        var[name] = value
 
 
 def defNewProp(name, proptype, rest):
-    expr = 'bpy.types.Object.%s = %sProperty(%s)' % (name, proptype, rest)
-    print(expr)
-    exec(expr)
+    prop = "%sProperty(%s)" % (proptype, rest)
+    setattr(bpy.types.Object, name, eval(prop))
 
 
-def setProperty(args, var, glbals, lcals):
+def setProperty(args, var):
     global theProperty
     tip = ""
     name = propNames(args[0])[0]
-    value = args[1]
+    value = eval(args[1])
+    print("setProp", var, name, value)
     if name:
-        expr = '%s["%s"] = %s' % (var, name, value)
-        exec(expr, glbals, lcals)
-
+        var[name] = value
         if len(args) > 2:
             tip = 'description="%s"' % args[2].replace("_", " ")
-        if value in ["True", "False"]:
-            proptype = "Bool"
-        elif value[0] in ["'",'"']:
-            proptype = "String"
-        elif "." in value:
-            proptype = "Float"
-        else:
-            proptype = "Int"
-        theProperty = (name, tip, proptype)
+        theProperty = (name, tip, value)
 
 
-def defineProperty(args):
+def setPropKeys(args):
     global theProperty
     if theProperty is None:
         return
-    (name, tip, proptype) = theProperty
-    if len(args) >= 2 and proptype != "Bool":
+    (name, tip, value) = theProperty
+    if len(args) >= 2 and not isinstance(value, bool):
         if "BOOLEAN" in args[1]:
-            proptype = "Bool"
+            value = bool(value)
         else:
             tip = tip + "," + args[1].replace(":", "=").replace('"', " ")
-    expr = "bpy.types.Object.%s = %sProperty(%s)" % (name, proptype, tip)
+    #expr = "bpy.types.Object.%s = %sProperty(%s)" % (name, proptype, tip)
+    if isinstance(value, bool):
+        prop = BoolProperty(tip)
+    elif isinstance(value, int):
+        prop = IntProperty(tip)
+    elif isinstance(value, float):
+        prop = FloatProperty(tip)
+    elif isinstance(value, string):
+        prop = StringProperty(tip)
+    print("SetPK", theProperty, name, prop)
+    setattr(bpy.types.Object, name, prop)
     theProperty = None
 
 
-def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
-    global todo
-
+def defaultKey(ext, args, tokens, var, exclude=[]):
     if ext == 'Property':
-        return setProperty(args, var, glbals, lcals)
+        return setProperty(args, var)
     elif ext == 'PropKeys':
-        return defineProperty(args)
+        return setPropKeys(args)
     elif ext == 'DefProp':
-        return defProp(args, var, glbals, lcals)
+        return defProp(args, var)
 
     if ext == 'bpyops':
         expr = "bpy.ops.%s" % args[0]
         print(expr)
-        exec(expr)
-        return
+        raise MhxError("MHX bug: calling %s" % expr)
 
-    nvar = "%s.%s" % (var, ext)
-    #print(ext)
     if ext in exclude:
         return
-    #print("D", nvar)
+    #nvar = "%s.%s" % (var, ext)
+    nvar = getattr(var, ext)
 
     if len(args) == 0:
         MyError("Key length 0: %s" % ext)
@@ -2202,7 +2154,8 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
         typ = args[1]
         name = args[2]
         try:
-            data = eval(nvar, glbals, lcals)
+            #data = eval(nvar)
+            data = getattr(var, ext)
         except:
             data = None
         # print("Old structrna", nvar, data)
@@ -2226,31 +2179,27 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
 
         if data:
             for (key, val, sub) in tokens:
-                defaultKey(key, val, sub, "data", [], globals(), locals())
-
-        print("Struct done", nvar)
+                defaultKey(key, val, sub, data)
         return
 
     elif rnaType == 'PropertyRNA':
         MyError("PropertyRNA!")
         #print("PropertyRNA ", ext, var)
         for (key, val, sub) in tokens:
-            defaultKey(ext, val, sub, nvar, [], glbals, lcals)
+            defaultKey(ext, val, sub, nvar, [])
         return
 
     elif rnaType == 'Array':
         for n in range(1, len(args)):
-            expr = "%s[%d] = %s" % (nvar, n-1, args[n])
-            exec(expr, glbals, lcals)
+            nvar[n-1] = eval(args[n])
         if len(args) > 0:
-            expr = "%s[0] = %s" % (nvar, args[1])
-            exec(expr, glbals, lcals)
+            nvar[0] = eval(args[1])
         return
 
     elif rnaType == 'List':
         data = []
         for (key, val, sub) in tokens:
-            elt = eval(val[1], glbals, lcals)
+            elt = eval(val[1])
             data.append(elt)
 
     elif rnaType == 'Matrix':
@@ -2260,8 +2209,7 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
         for (key, val, sub) in tokens:
             if key == 'row':
                 for j in range(n):
-                    expr = "%s[%d][%d] = %g" % (nvar, i, j, float(val[j]))
-                    exec(expr, glbals, lcals)
+                    nvar[i][j] = float(val[j])
                 i += 1
         return
 
@@ -2273,23 +2221,17 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
         except:
             data = rnaType
 
-    #print(var, ext, data)
-    expr = "%s = %s" % (nvar, data)
-    try:
-        exec(expr, glbals, lcals)
-    except:
-        pushOnTodoList(var, expr, glbals, lcals)
+    setattr(var, ext, eval(data))
     return
 
 #
 #
 #
 
-def pushOnTodoList(var, expr, glbals, lcals):
-    global todo
+def pushOnTodoList(var, expr):
     print("Unrecognized expression", expr)
     return
-    print(dir(eval(var, glbals, lcals)))
+    print(dir(eval(var)))
     MyError(
         "Unrecognized expression %s.\n"  % expr +
         "This can mean that Blender's python API has changed\n" +
@@ -2297,8 +2239,6 @@ def pushOnTodoList(var, expr, glbals, lcals):
         "from an up-to-date MakeHuman nightly build.\n" +
         "Alternatively, your Blender version may be obsolete.\n" +
         "Download an up-to-date version from www.graphicall.org")
-    todo.append((expr, glbals, lcals))
-    return
 
 
 #
@@ -2337,9 +2277,10 @@ def parseDefault(data, tokens, subkeys, exclude):
     for (key, val, sub) in tokens:
         if key in subkeys.keys():
             for (key2, val2, sub2) in sub:
-                defaultKey(key2, val2, sub2, "data.%s" % subkeys[key], [], globals(), locals())
+                ndata = getattr(data, subkeys[key])
+                defaultKey(key2, val2, sub2, ndata)
         else:
-            defaultKey(key, val, sub, "data", exclude, globals(), locals())
+            defaultKey(key, val, sub, data, exclude)
 
 def parseCollection(data, tokens, exclude):
     return
@@ -2787,7 +2728,7 @@ def fixConstraint(cns1, cns2, gen, bones):
         if ((key[0] != "_") and
             (key not in ["bl_rna", "type", "rna_type", "is_valid", "error_location", "error_rotation"])):
             expr = ("cns2.%s = cns1.%s" % (key, key))
-            exec(expr)
+            setattr(cns2, key, getattr(cns1, key))
 
     cns2.target = gen
 
@@ -2974,8 +2915,8 @@ class ImportMhx(bpy.types.Operator, ImportHelper):
     scale = FloatProperty(name="Scale", description="Default meter, decimeter = 1.0", default = theScale)
     advanced = BoolProperty(name="Advanced settings", description="Use advanced import settings", default=False)
     for (prop, name, desc, flag) in MhxBoolProps:
-        expr = '%s = BoolProperty(name="%s", description="%s", default=(toggleSettings&%s != 0))' % (prop, name, desc, flag)
-        exec(expr)
+        expr = 'BoolProperty(name="%s", description="%s", default=(toggleSettings&%s != 0))' % (name, desc, flag)
+        prop = eval(expr)
 
 
     def draw(self, context):
@@ -3020,8 +2961,7 @@ class ImportMhx(bpy.types.Operator, ImportHelper):
         readDefaults()
         self.scale = theScale
         for (prop, name, desc, flag) in MhxBoolProps:
-            expr = 'self.%s = (toggle&%s != 0)' % (prop, flag)
-            exec(expr)
+            setattr(self, prop, eval('(toggle&%s != 0)' % flag))
         context.window_manager.fileselect_add(self)
         return {'RUNNING_MODAL'}
 
@@ -3948,7 +3888,10 @@ def matchIkLeg(legIk, toeFk, mBall, mToe, mHeel, auto):
     ty = rmat.col[1]
     tail = tHead + ty * toeFk.bone.length
 
-    zBall = mBall.matrix.col[3][2]
+    try:
+        zBall = mBall.matrix.col[3][2]
+    except AttributeError:
+        return
     zToe = mToe.matrix.col[3][2]
     zHeel = mHeel.matrix.col[3][2]
 
@@ -4177,11 +4120,15 @@ def getSnapBones(rig, key, suffix):
     constraints = []
     for name in names:
         if name:
-            pb = rig.pose.bones[name+suffix]
+            try:
+                pb = rig.pose.bones[name+suffix]
+            except KeyError:
+                pb = None
             pbones.append(pb)
-            for cns in pb.constraints:
-                if cns.type == 'LIMIT_ROTATION' and not cns.mute:
-                    constraints.append(cns)
+            if pb is not None:
+                for cns in pb.constraints:
+                    if cns.type == 'LIMIT_ROTATION' and not cns.mute:
+                        constraints.append(cns)
         else:
             pbones.append(None)
     return tuple(pbones),constraints
@@ -4552,8 +4499,8 @@ MhxLayers = [
     (( 9,    'Tweak', 'MhxTweak'),
      (10,    'Head', 'MhxHead')),
     (( 1,    'FK Spine', 'MhxFKSpine'),
-     (17,    'IK Spine', 'MhxIKSpine')),
-    ((13,    'Inv FK Spine', 'MhxInvFKSpine'),
+     #(17,    'IK Spine', 'MhxIKSpine')),
+     #((13,    'Inv FK Spine', 'MhxInvFKSpine'),
      (16,    'Clothes', 'MhxClothes')),
     ('Left', 'Right'),
     (( 2,    'IK Arm', 'MhxIKArm'),