In order to fuse the many disparate parts of maya’s python package into a cohesive whole PyMEL requires a great deal of data describing how each MEL command and API class works: the arguments they require, the results they return, and their relationships to each other. Some of this data is parsed and cached, while other bits are manually maintained.
Below is a description of how each major cache is created.
create a dictionary of MEL-commands to the maya nodes they create, query, and edit
create a dictionary of MEL-commands to the ui elements they create, query, and edit
run tests on node commands to gather additional information required to ensure values returned by queries are compatible with values required for edits
pickle this info into two separate caches: one used for auto-wraps and the other for doc strings. the latter data can be lazily loaded on request since it is not required for the wrap itself.
pickle this info into two separate caches: one for auto-wraps and the other for doc strings
A special control-panel GUI is used to manage a dictionary controlling how MEL and API interact to produce PyNode classes. It is known as the bridge. The bridge allows us to:
When PyMEL is imported it uses the cached data to generate the wrapped functions and classes you’ve come to know and love. Here’s how in a nutshell.
Every command is wrapped in up to 3 stages.
pymel.internal.pmcmds wraps every function in maya.cmds such that any arguments that are passed to it are first converted into datatypes that maya.cmds will accept (string, int, float, or list/tuple thereof). The way we do this is simple yet powerful: if the argument has a __melobject__ method, we evaluate it and use the result in place of the original value. It is the responsibility of this method to return a “MEL-friendly” representation of the object’s data. For example, core.PyNode.__melobject__ returns its object’s name as a string, and datatypes.Matrix.__melobject__ returns itself converted into a flat 16-item list.
Optional manual wraps are created for cases that cannot be handled automatically or semi-automatically (below). They can use the auto-wrapped function in pmcmds as a starting point
Certain wraps are applied automatically based on information attained during parsing. If a manual wrap of the function is found, it is used as the starting point, otherwise the lower-level pmcmds wrap is used.
For each function:
for each node and UI type:
choose the appropriate metaclass
The PyMEL project hosts its issues and wiki on googlecode, but we found Git + Github to be a better solution for managing our code.
When you “push” your changes up to Github, we’ll be able to track them, give you feedback, and cherry-pick what we like. You, in turn, will be able to easily pull new changes from our repo into yours.
PyMEL has a suite of unit tests. You should write a test for every major addition or change that you make. To run the tests, you need ‘nose’, which is a discovery-based test runner, that builds on python’s unittest module and makes writing running a lot of tests a lot easier. Here’s the easiest way to get nose.
sudo mayapy setup.py easy_install nose
mayapy.exe setup.py easy_install nose
This assumes that you’ve properly setup your environment, which you should definitely know how to do before contributing to PyMEL.