2

I'm working in Maya using Python 2.5, writing a dynamic hotkey manager class and ran into trouble trying to assign commands that are instance specific since nameCommands get represented as strings in mel. I end up with commands that look like:

<bla.Bla instance at 0x0000000028F04388>.thing = 'Dude'

I've seen quite a bit on the topic of repr and eval but my test example below fails.

class Foo:
    pass

f = Foo()
f.thing = 'Jeff'
rep = repr(f)
y = eval(rep) # errors here
name = y.thing

# Error: invalid syntax
# Traceback (most recent call last):
#   File "<maya console>", line 7, in <module>
#   File "<string>", line 1
#     <__main__.Foo instance at 0x00000000294D8188>
#     ^
# SyntaxError: invalid syntax # 

I assume what I want is some way to get a proper object of that instance from a string. I could format the string to an evaluate-able command if I knew what that looked like. see my cgtalk post for more usage info

SO related topics:

This one says it's not possible but users also wanted a use case, which I hope I've provided. How to obtain an object from a string?

Others: When is the output of repr useful? How to print a class or objects of class using print()? Allowing the repr() of my class's instances to be parsed by eval() Main purpose of __repr__ in python how do you obtain the address of an instance after overriding the __str__ method in python Python repr for classes how to use 'pickle'

Community
  • 1
  • 1
Paul Lohman
  • 56
  • 1
  • 8

2 Answers2

2

For eval to work, the builtin __repr__ function needs to be overriden. I don't see you mentioning that, so I figure you didn't do it. I'm pasting a code snippet I wrote a while back. Just for the sake of demonstration. In this example, eval works because __repr__ was overriden:

class element :
    def __init__(self, a, m):
        self.name = a ;
        self.atomic_mass = m ;

    def __str__(self):
        return "{0} has atomic mass {1}".format(self.name, self.atomic_mass)

    def __repr__(self):
        return "element(\"{0}\", \"{1}\")".format(self.name, self.atomic_mass)

H = element("Hydrogen", 1.00794)
print H
print repr(H)
print eval(repr(H))

More here : http://www.muqube.com/python/string-representation-of-python-objects/

Raiyan
  • 1,589
  • 1
  • 14
  • 28
  • it looks like this creates a *new* instance rather than calling a method of the *existing* instance – mhlester Feb 21 '14 at 04:55
  • think I just found a way actually using id rather then the rep string. http://stackoverflow.com/a/15702647/1495017 will fully implement to see if I run into any gotcha's. – Paul Lohman Feb 21 '14 at 05:05
  • @PaulLohman, I was just testing the same thing. It works beautifully – mhlester Feb 21 '14 at 05:10
  • woot, using it as so; command = ("python(\"ctypes.cast(%s,ctypes.py_object).value.thing=False\")")%(id(self)) nameCommand = cmds.nameCommand( 'setThingOnPress', annotation='', command=command ) – Paul Lohman Feb 21 '14 at 05:24
  • @PaulLohman, you should post it as a new answer, and accept it. That way future visitors can see and learn from it. Be sure to also include a link to that other valuable answer you'd found – mhlester Feb 21 '14 at 05:34
  • Is this all intended to rewrite parameters inside the runTimeCommand? If you have the runtimeCommand's name you can just change the text with cmds.runTimeCommand(name, e=True, commmand='your text here') – theodox Feb 21 '14 at 21:47
1

found a method that seems to work for me here using the id as a string and ctypes

class Foo:
    pass

f = Foo()
f.thing = 'Jeff'

import ctypes    
long_f = id(f)
y = ctypes.cast(long_f,ctypes.py_object).value
name = y.thing

and here, an example usage in Maya;

command = ("python(\"ctypes.cast(%s,ctypes.py_object).value.thing=False\")")%(id(self))
nameCommand = cmds.nameCommand( 'setThingOnPress', annotation='', command=command )
cmds.hotkey( keyShortcut='b', name=nameCommand)
Community
  • 1
  • 1
Paul Lohman
  • 56
  • 1
  • 8