def mayaDocsLocation(version=None): docLocation = None if (version == None or version == versions.installName() ) and mayaIsRunning(): # Return the doc location for the running version of maya from maya.cmds import showHelp docLocation = showHelp("", q=True, docs=True) # Older implementations had no trailing slash, but the result returned by # showHelp has a trailing slash... so eliminate any trailing slashes for # consistency while docLocation != "" and os.path.basename(docLocation) == "": docLocation = os.path.dirname(docLocation) # Want the docs for a different version, or maya isn't initialized yet if not docLocation or not os.path.isdir(docLocation): docLocation = getMayaLocation(version) # use original version if docLocation is None and version is not None: docLocation = getMayaLocation(None) _logger.warning("Could not find an installed Maya for exact version %s, using first installed Maya location found in %s" % (version, docLocation) ) if version: short_version = versions.parseVersionStr(version, extension=False) else: short_version = versions.shortName() if platform.system() == 'Darwin': docLocation = os.path.dirname(os.path.dirname(docLocation)) docLocation = os.path.join(docLocation , 'docs/Maya%s/en_US' % short_version) return os.path.realpath(docLocation)
def initMEL(): if 'PYMEL_SKIP_MEL_INIT' in os.environ or pymel_options.get('skip_mel_init', False): _logger.info("Skipping MEL initialization") return _logger.debug("initMEL") mayaVersion = versions.installName() prefsDir = getUserPrefsDir() if prefsDir is None: _logger.error("could not initialize user preferences: MAYA_APP_DIR not set") elif not os.path.isdir(prefsDir): _logger.error("could not initialize user preferences: %s does not exist" % prefsDir) # TODO : use cmds.internalVar to get paths # got this startup sequence from autodesk support startup = [ #'defaultRunTimeCommands.mel', # sourced automatically # os.path.join( prefsDir, 'userRunTimeCommands.mel'), # sourced automatically 'createPreferencesOptVars.mel', 'createGlobalOptVars.mel', os.path.join(prefsDir, 'userPrefs.mel') if prefsDir else None, 'initialStartup.mel', #$HOME/Documents/maya/projects/default/workspace.mel 'initialPlugins.mel', #'initialGUI.mel', #GUI #'initialLayout.mel', #GUI # os.path.join( prefsDir, 'windowPrefs.mel'), #GUI # os.path.join( prefsDir, 'menuSetPrefs.mel'), #GUI #'hotkeySetup.mel', #GUI 'namedCommandSetup.mel', os.path.join(prefsDir, 'userNamedCommands.mel') if prefsDir else None, #'initAfter.mel', #GUI os.path.join(prefsDir, 'pluginPrefs.mel') if prefsDir else None ] if pymel_options.get('skip_initial_plugins', False): # initialPlugins.mel is not sourced when running maya -batch, but has been included # in the pymel startup sequence since time immemorial. see pymel.conf for more info _logger.info("Skipping loading Initial Plugins") startup.remove('initialPlugins.mel') try: for f in startup: _logger.debug("running: %s" % f) if f is not None: if os.path.isabs(f) and not os.path.exists(f): _logger.warning("Maya startup file %s does not exist" % f) else: # need to encode backslashes (used for windows paths) if isinstance(f, unicode): encoding = 'unicode_escape' else: encoding = 'string_escape' #import pymel.core.language as lang #lang.mel.source( f.encode(encoding) ) import maya.mel maya.mel.eval('source "%s"' % f.encode(encoding)) except Exception, e: _logger.error("could not perform Maya initialization sequence: failed on %s: %s" % (f, e))
def __init__(self, apiModule, version=None, verbose=False): version = versions.installName() if version is None else version self.apiModule = apiModule self.verbose = verbose self.docloc = mayaDocsLocation('2009' if version=='2008' else version) if not os.path.isdir(self.docloc): raise IOError, "Cannot find maya documentation. Expected to find it at %s" % self.docloc
def __init__(self, apiModule, version=None, verbose=False, enumClass=tuple): self.version = versions.installName() if version is None else version self.apiModule = apiModule self.verbose = verbose self.docloc = mayaDocsLocation('2009' if self.version=='2008' else self.version) self.enumClass = enumClass if not os.path.isdir(self.docloc): raise IOError, "Cannot find maya documentation. Expected to find it at %s" % self.docloc self.enums = {} self.pymelEnums = {} self.methods=util.defaultdict(list) self.currentMethod=None self.badEnums = []
def __init__(self, exceptions=True ): self._exceptions = exceptions self._optionVars = OptionVarDict() bin_path = os.path.join( _internal.getMayaAppDir(), versions.installName(), "prefs", "prefs.bin") try: self._shelve = shelve.open(bin_path) except _db.DBPermissionsError: _logger.warn( 'Permission Error accessing "prefs.bin". Python-only options vars will not be saved.' ) self._shelve = {} _id = _api.MEventMessage.addEventCallback( 'quitApplication', self._close )
def getMayaLocation(version=None): """ Get the path to the Maya install directory. .. note:: The Maya location is defined as the directory above /bin. Uses the ``MAYA_LOCATION`` environment variable and ``sys.executable`` path. Parameters ---------- version : bool if passed, will attempt to find a matching Maya location. If the version found above does not match the requested version, this function uses a simple find/replace heuristic to modify the path and test if the desired version exists. Returns ------- str or None The path to Maya's installation directory or None, if not found """ try: loc = os.path.realpath(os.environ['MAYA_LOCATION']) except: loc = os.path.dirname(os.path.dirname(sys.executable)) # get the path of a different maya version than current if version: # note that a recursive loop between getMayaLocation / getMayaVersion # is avoided because getMayaVersion always calls getMayaLocation with # version == None actual_long_version = versions.installName() actual_short_version = versions.shortName() if version != actual_long_version: short_version = versions.parseVersionStr(version, extension=False) if version == short_version: try_version = actual_long_version.replace(actual_short_version, short_version) else: try_version = version try_loc = loc.replace(actual_long_version, try_version) if os.path.exists(try_loc): loc = try_loc else: _logger.warn("No Maya found for version %s" % version) loc = None return loc
def getMayaAppDir(versioned=False): # type: (bool) -> Optional[str] """ Get the path to the current user's Maya application directory. First checks ``MAYA_APP_DIR``, then tries OS-specific defaults. Returns None, if not found Parameters ---------- versioned : bool if True, the current Maya version including '-x64' suffix, if applicable, will be appended. Returns ------- Optional[str] """ appDir = os.environ.get('MAYA_APP_DIR', None) if appDir is None: if os.name == 'nt': appDir = os.environ.get('USERPROFILE', os.environ.get('HOME', None)) if appDir is None: return None # Vista or newer... version() returns "6.x.x" if int(platform.version().split('.')[0]) > 5: appDir = os.path.join(appDir, 'Documents') else: appDir = os.path.join(appDir, 'My Documents') else: appDir = os.environ.get('HOME', None) if appDir is None: return None if platform.system() == 'Darwin': appDir = os.path.join(appDir, 'Library/Preferences/Autodesk/maya') else: appDir = os.path.join(appDir, 'maya') if versioned and appDir: appDir = os.path.join(appDir, versions.installName()) return appDir
def getMayaLocation(version=None): """ Get the path to the Maya install directory. .. note:: The Maya location is defined as the directory above /bin. Uses the ``MAYA_LOCATION`` environment variable and ``sys.executable`` path. Returns None if not found. :Parameters: version : bool if passed, will attempt to find a matching Maya location. If the version found above does not match the requested version, this function uses a simple find/replace heuristic to modify the path and test if the desired version exists. :rtype: str or None """ try: loc = os.path.realpath(os.environ['MAYA_LOCATION']) except: loc = os.path.dirname(os.path.dirname(sys.executable)) # get the path of a different maya version than current if version: # note that a recursive loop between getMayaLocation / getMayaVersion # is avoided because getMayaVersion always calls getMayaLocation with # version == None actual_long_version = versions.installName() actual_short_version = versions.shortName() if version != actual_long_version: short_version = versions.parseVersionStr(version, extension=False) if version == short_version: try_version = actual_long_version.replace( actual_short_version, short_version) else: try_version = version try_loc = loc.replace(actual_long_version, try_version) if os.path.exists(try_loc): loc = try_loc else: _logger.warn("No Maya found for version %s" % version) loc = None return loc
def getMayaAppDir(versioned=False): """ Get the path to the current user's Maya application directory First checks ``MAYA_APP_DIR``, then tries OS-specific defaults. Parameters ---------- versioned : bool if True, the current Maya version including '-x64' suffix, if applicable, will be appended. Returns ------- str or None The path to Maya's application directory or None, if not found """ appDir = os.environ.get('MAYA_APP_DIR', None) if appDir is None: if os.name == 'nt': appDir = os.environ.get('USERPROFILE', os.environ.get('HOME', None)) if appDir is None: return # Vista or newer... version() returns "6.x.x" if int(platform.version().split('.')[0]) > 5: appDir = os.path.join(appDir, 'Documents') else: appDir = os.path.join(appDir, 'My Documents') else: appDir = os.environ.get('HOME', None) if appDir is None: return if platform.system() == 'Darwin': appDir = os.path.join(appDir, 'Library/Preferences/Autodesk/maya') else: appDir = os.path.join(appDir, 'maya') if versioned and appDir: appDir = os.path.join(appDir, versions.installName()) return appDir
def __init__(self, apiModule, version=None, verbose=False, enumClass=tuple): self.version = versions.installName() if version is None else version self.apiModule = apiModule self.verbose = verbose self.docloc = mayaDocsLocation('2009' if self.version == '2008' else self.version) self.enumClass = enumClass if not os.path.isdir(self.docloc): raise IOError, "Cannot find maya documentation. Expected to find it at %s" % self.docloc self.enums = {} self.pymelEnums = {} self.methods = util.defaultdict(list) self.currentMethod = None self.badEnums = []
def initMEL(): if 'PYMEL_SKIP_MEL_INIT' in os.environ or pymel_options.get('skip_mel_init', False): _logger.info("Skipping MEL initialization") return _logger.debug("initMEL") mayaVersion = versions.installName() prefsDir = getUserPrefsDir() if prefsDir is None: _logger.error("could not initialize user preferences: MAYA_APP_DIR not set") elif not os.path.isdir(prefsDir): _logger.error("could not initialize user preferences: %s does not exist" % prefsDir) # TODO : use cmds.internalVar to get paths # got this startup sequence from autodesk support startup = [ #'defaultRunTimeCommands.mel', # sourced automatically # os.path.join( prefsDir, 'userRunTimeCommands.mel'), # sourced automatically 'createPreferencesOptVars.mel', 'createGlobalOptVars.mel', os.path.join(prefsDir, 'userPrefs.mel') if prefsDir else None, 'initialStartup.mel', #$HOME/Documents/maya/projects/default/workspace.mel 'initialPlugins.mel', #'initialGUI.mel', #GUI #'initialLayout.mel', #GUI # os.path.join( prefsDir, 'windowPrefs.mel'), #GUI # os.path.join( prefsDir, 'menuSetPrefs.mel'), #GUI #'hotkeySetup.mel', #GUI 'namedCommandSetup.mel', os.path.join(prefsDir, 'userNamedCommands.mel') if prefsDir else None, #'initAfter.mel', #GUI os.path.join(prefsDir, 'pluginPrefs.mel') if prefsDir else None ] if pymel_options.get('skip_initial_plugins', False): # initialPlugins.mel is not sourced when running maya -batch, but has been included # in the pymel startup sequence since time immemorial. see pymel.conf for more info _logger.info("Skipping loading Initial Plugins") startup.remove('initialPlugins.mel') import maya.mel callbacks = om.MCallbackIdArray() toDelete = [] # initialStartup.mel will run a `file -f -new`. This is dangerous, for # obvoius resons, so we disable all file news while we run these... def rejectNewCallback(boolPtr_retCode, clientData): om.MScriptUtil.setBool(boolPtr_retCode, False) callbacks.append(om.MSceneMessage.addCheckCallback( om.MSceneMessage.kBeforeNewCheck, rejectNewCallback)) try: # additionally, userPrefs.mel will apparently create a bunch of ikSolver # nodes (apparently just to set some global ik prefs?) # make sure we clean those up... def logIkSolverCreation(nodeObj, clientData): toDelete.append(om.MObjectHandle(nodeObj)) callbacks.append(om.MDGMessage.addNodeAddedCallback( logIkSolverCreation, "ikSolver")) for f in startup: _logger.debug("running: %s" % f) if f is not None: if os.path.isabs(f) and not os.path.exists(f): _logger.warning("Maya startup file %s does not exist" % f) else: if PY2: # need to encode backslashes (used for windows paths) if isinstance(f, unicode): encoding = 'unicode_escape' else: encoding = 'string_escape' f = f.encode(encoding) else: # encoding to unicode_escape should add escape # sequences, but also make sure everything is in basic # ascii - so if we decode utf-8 (or ascii), it should # give us a string which is escaped f = f.encode('unicode_escape').decode('utf-8') maya.mel.eval('source "%s"' % f) except Exception as e: _logger.error("could not perform Maya initialization sequence: failed " "on %s: %s" % (f, e)) finally: om.MMessage.removeCallbacks(callbacks) # clean up the created ik solvers dgMod = om.MDGModifier() for objHandle in toDelete: if objHandle.isValid(): dgMod.deleteNode(objHandle.object()) dgMod.doIt() try: # make sure it exists res = maya.mel.eval('whatIs "userSetup.mel"') if res != 'Unknown': maya.mel.eval('source "userSetup.mel"') except RuntimeError: pass _logger.debug("done running mel files")
def rebuild(self) : """Build and save to disk the list of Maya Python commands and their arguments""" # With extension can't get docs on unix 64 # path is # /usr/autodesk/maya2008-x64/docs/Maya2008/en_US/Nodes/index_hierarchy.html # and not # /usr/autodesk/maya2008-x64/docs/Maya2008-x64/en_US/Nodes/index_hierarchy.html _logger.info("Rebuilding the list of Maya commands...") long_version = versions.installName() self.nodeHierarchy = _getNodeHierarchy(long_version) nodeFunctions = [ x[0] for x in self.nodeHierarchy ] nodeFunctions += nodeTypeToNodeCommand.values() #nodeHierarchyTree = trees.IndexedTree(self.nodeHierarchy) self.uiClassList = UI_COMMANDS self.nodeCommandList = [] for moduleName, longname in moduleNameShortToLong.items(): moduleNameShortToLong[moduleName] = getModuleCommandList( longname, long_version ) tmpCmdlist = inspect.getmembers(cmds, callable) #self.moduleCmds = defaultdict(list) self.moduleCmds = dict( (k,[]) for k in moduleNameShortToLong.keys() ) self.moduleCmds.update( {'other':[], 'runtime': [], 'context': [], 'uiClass': [] } ) for funcName, data in tmpCmdlist : # determine to which module this function belongs module = None if funcName in ['eval', 'file', 'filter', 'help', 'quit']: module = None elif funcName.startswith('ctx') or funcName.endswith('Ctx') or funcName.endswith('Context'): module = 'context' #elif funcName in self.uiClassList: # module = 'uiClass' #elif funcName in nodeHierarchyTree or funcName in nodeTypeToNodeCommand.values(): # module = 'node' else: for moduleName, commands in moduleNameShortToLong.iteritems(): if funcName in commands: module = moduleName break if module is None: if mm.eval('whatIs "%s"' % funcName ) == 'Run Time Command': module = 'runtime' else: module = 'other' cmdInfo = {} if module: self.moduleCmds[module].append(funcName) if module != 'runtime': cmdInfo = getCmdInfo(funcName, long_version) if module != 'windows': if funcName in nodeFunctions: self.nodeCommandList.append(funcName) cmdInfo = testNodeCmd( funcName, cmdInfo, nodeCmd=True, verbose=True ) #elif module != 'context': # cmdInfo = testNodeCmd( funcName, cmdInfo, nodeCmd=False, verbose=True ) cmdInfo['type'] = module flags = getCallbackFlags(cmdInfo) if flags: cmdInfo['callbackFlags'] = flags self.cmdlist[funcName] = cmdInfo # # func, args, (usePyNode, baseClsName, nodeName) # # args = dictionary of command flags and their data # # usePyNode = determines whether the class returns its 'nodeName' or uses PyNode to dynamically return # # baseClsName = for commands which should generate a class, this is the name of the superclass to inherit # # nodeName = most creation commands return a node of the same name, this option is provided for the exceptions # try: # self.cmdlist[funcName] = args, pymelCmdsList[funcName] ) # except KeyError: # # context commands generate a class based on unicode (which is triggered by passing 'None' to baseClsName) # if funcName.startswith('ctx') or funcName.endswith('Ctx') or funcName.endswith('Context'): # self.cmdlist[funcName] = (funcName, args, (False, None, None) ) # else: # self.cmdlist[funcName] = (funcName, args, () ) # split the cached data for lazy loading cmdDocList = {} examples = {} for cmdName, cmdInfo in self.cmdlist.iteritems(): try: examples[cmdName] = cmdInfo.pop('example') except KeyError: pass newCmdInfo = {} if 'description' in cmdInfo: newCmdInfo['description'] = cmdInfo.pop('description') newFlagInfo = {} if 'flags' in cmdInfo: for flag, flagInfo in cmdInfo['flags'].iteritems(): newFlagInfo[flag] = { 'docstring' : flagInfo.pop('docstring') } newCmdInfo['flags'] = newFlagInfo if newCmdInfo: cmdDocList[cmdName] = newCmdInfo CmdDocsCache().write(cmdDocList) CmdExamplesCache().write(examples)
def initMEL(): if 'PYMEL_SKIP_MEL_INIT' in os.environ or pymel_options.get( 'skip_mel_init', False): _logger.info("Skipping MEL initialization") return _logger.debug("initMEL") mayaVersion = versions.installName() prefsDir = getUserPrefsDir() if prefsDir is None: _logger.error( "could not initialize user preferences: MAYA_APP_DIR not set") elif not os.path.isdir(prefsDir): _logger.error( "could not initialize user preferences: %s does not exist" % prefsDir) # TODO : use cmds.internalVar to get paths # got this startup sequence from autodesk support startup = [ #'defaultRunTimeCommands.mel', # sourced automatically # os.path.join( prefsDir, 'userRunTimeCommands.mel'), # sourced automatically 'createPreferencesOptVars.mel', 'createGlobalOptVars.mel', os.path.join(prefsDir, 'userPrefs.mel') if prefsDir else None, 'initialStartup.mel', #$HOME/Documents/maya/projects/default/workspace.mel 'initialPlugins.mel', #'initialGUI.mel', #GUI #'initialLayout.mel', #GUI # os.path.join( prefsDir, 'windowPrefs.mel'), #GUI # os.path.join( prefsDir, 'menuSetPrefs.mel'), #GUI #'hotkeySetup.mel', #GUI 'namedCommandSetup.mel', os.path.join(prefsDir, 'userNamedCommands.mel') if prefsDir else None, #'initAfter.mel', #GUI os.path.join(prefsDir, 'pluginPrefs.mel') if prefsDir else None ] if pymel_options.get('skip_initial_plugins', False): # initialPlugins.mel is not sourced when running maya -batch, but has been included # in the pymel startup sequence since time immemorial. see pymel.conf for more info _logger.info("Skipping loading Initial Plugins") startup.remove('initialPlugins.mel') try: for f in startup: _logger.debug("running: %s" % f) if f is not None: if os.path.isabs(f) and not os.path.exists(f): _logger.warning("Maya startup file %s does not exist" % f) else: # need to encode backslashes (used for windows paths) if isinstance(f, unicode): encoding = 'unicode_escape' else: encoding = 'string_escape' #import pymel.core.language as lang #lang.mel.source( f.encode(encoding) ) import maya.mel maya.mel.eval('source "%s"' % f.encode(encoding)) except Exception, e: _logger.error( "could not perform Maya initialization sequence: failed on %s: %s" % (f, e))
def rebuild(self) : """Build and save to disk the list of Maya Python commands and their arguments WARNING: will unload existing plugins, then (re)load all maya-installed plugins, without making an attempt to return the loaded plugins to the state they were at before this command is run. Also, the act of loading all the plugins may crash maya, especially if done from a non-GUI session """ # Put in a debug, because this can be crashy _logger.debug("Starting CmdCache.rebuild...") # With extension can't get docs on unix 64 # path is # /usr/autodesk/maya2008-x64/docs/Maya2008/en_US/Nodes/index_hierarchy.html # and not # /usr/autodesk/maya2008-x64/docs/Maya2008-x64/en_US/Nodes/index_hierarchy.html long_version = versions.installName() from parsers import mayaDocsLocation cmddocs = os.path.join(mayaDocsLocation(long_version), 'CommandsPython') assert os.path.exists(cmddocs), "Command documentation does not exist: %s" % cmddocs _logger.info("Rebuilding the maya node hierarchy...") # Load all plugins to get the nodeHierarchy / nodeFunctions import pymel.api.plugins as plugins # We don't want to add in plugin nodes / commands - let that be done # by the plugin callbacks. However, unloading mechanism is not 100% # ... sometimes functions get left in maya.cmds... and then trying # to use those left-behind functions can cause crashes (ie, # FBXExportQuaternion). So check which methods SHOULD be unloaded # first, so we know to skip those if we come across them even after # unloading the plugin pluginCommands = set() loadedPlugins = cmds.pluginInfo(q=True, listPlugins=True) if loadedPlugins: for plug in loadedPlugins: plugCmds = plugins.pluginCommands(plug) if plugCmds: pluginCommands.update(plugCmds) plugins.unloadAllPlugins() self.nodeHierarchy = _getNodeHierarchy(long_version) nodeFunctions = [ x[0] for x in self.nodeHierarchy ] nodeFunctions += nodeTypeToNodeCommand.values() _logger.info("Rebuilding the list of Maya commands...") #nodeHierarchyTree = trees.IndexedTree(self.nodeHierarchy) self.uiClassList = UI_COMMANDS self.nodeCommandList = [] tmpModuleCmds = {} for moduleName, longname in moduleNameShortToLong.items(): tmpModuleCmds[moduleName] = getModuleCommandList( longname, long_version ) tmpCmdlist = inspect.getmembers(cmds, callable) #self.moduleCmds = defaultdict(list) self.moduleCmds = dict( (k,[]) for k in moduleNameShortToLong.keys() ) self.moduleCmds.update( {'other':[], 'runtime': [], 'context': [], 'uiClass': [] } ) def addCommand(funcName): _logger.debug('adding command: %s' % funcName) module = getModule(funcName, tmpModuleCmds) cmdInfo = {} if module: self.moduleCmds[module].append(funcName) if module != 'runtime': cmdInfo = getCmdInfo(funcName, long_version) if module != 'windows': if funcName in nodeFunctions: self.nodeCommandList.append(funcName) cmdInfo = testNodeCmd( funcName, cmdInfo, nodeCmd=True, verbose=True ) #elif module != 'context': # cmdInfo = testNodeCmd( funcName, cmdInfo, nodeCmd=False, verbose=True ) cmdInfo['type'] = module flags = getCallbackFlags(cmdInfo) if flags: cmdInfo['callbackFlags'] = flags self.cmdlist[funcName] = cmdInfo # # func, args, (usePyNode, baseClsName, nodeName) # # args = dictionary of command flags and their data # # usePyNode = determines whether the class returns its 'nodeName' or uses PyNode to dynamically return # # baseClsName = for commands which should generate a class, this is the name of the superclass to inherit # # nodeName = most creation commands return a node of the same name, this option is provided for the exceptions # try: # self.cmdlist[funcName] = args, pymelCmdsList[funcName] ) # except KeyError: # # context commands generate a class based on unicode (which is triggered by passing 'None' to baseClsName) # if funcName.startswith('ctx') or funcName.endswith('Ctx') or funcName.endswith('Context'): # self.cmdlist[funcName] = (funcName, args, (False, None, None) ) # else: # self.cmdlist[funcName] = (funcName, args, () ) for funcName, _ in tmpCmdlist : if funcName in pluginCommands: _logger.debug("command %s was a plugin command that should have been unloaded - skipping" % funcName) continue addCommand(funcName) # split the cached data for lazy loading cmdDocList = {} examples = {} for cmdName, cmdInfo in self.cmdlist.iteritems(): try: examples[cmdName] = cmdInfo.pop('example') except KeyError: pass newCmdInfo = {} if 'description' in cmdInfo: newCmdInfo['description'] = cmdInfo.pop('description') newFlagInfo = {} if 'flags' in cmdInfo: for flag, flagInfo in cmdInfo['flags'].iteritems(): newFlagInfo[flag] = { 'docstring' : flagInfo.pop('docstring') } newCmdInfo['flags'] = newFlagInfo if newCmdInfo: cmdDocList[cmdName] = newCmdInfo CmdDocsCache().write(cmdDocList) CmdExamplesCache().write(examples)