def build(self, rebuildAllButClassInfo=False): """ Used to rebuild api cache, either by loading from a cache file, or rebuilding from scratch. Set 'rebuildAllButClassInfo' to True to force rebuilding of all info BUT self.apiClassInfo - this is useful for versions < 2009, as these versions cannot parse the api docs; by setting this to False, you can rebuild all other api information. """ # Need to initialize this to possibly pass into _buildself.apiTypeHierarchy, if rebuildAllButClassInfo self.apiClassInfo = None data = startup.loadCache( 'mayaApi', 'the API cache', compressed=True ) self._buildMayaReservedTypes() if data is not None: #self.reservedMayaTypes = data[0] #self.reservedApiTypes = data[1] self.apiTypesToApiEnums = data[2] self.apiEnumsToApiTypes = data[3] self.mayaTypesToApiTypes = data[4] self.apiTypesToApiClasses = data[5] self.apiTypeHierarchy = data[6] self.apiClassInfo = data[7] if not rebuildAllButClassInfo: # Note that even if rebuildAllButClassInfo, we still want to load # the cache file, in order to grab self.apiClassInfo return _logger.info( "Rebuilding the API Caches..." ) # fill out the data structures self._buildApiTypesList() #self.apiTypesToApiEnums, self.apiTypesToApiClasses = self._buildApiTypesList() #_buildMayaTypesList() if not rebuildAllButClassInfo: self.apiClassInfo = None self._buildApiTypeHierarchy() # merge in the manual overrides: we only do this when we're rebuilding or in the pymelControlPanel _logger.info( 'merging in dictionary of manual api overrides') _util.mergeCascadingDicts( apiClassOverrides, self.apiClassInfo, allowDictToListMerging=True ) startup.writeCache( ( self.reservedMayaTypes, self.reservedApiTypes, self.apiTypesToApiEnums, self.apiEnumsToApiTypes, self.mayaTypesToApiTypes, self.apiTypesToApiClasses, self.apiTypeHierarchy, self.apiClassInfo ), 'mayaApi', 'the API cache' ) return
def loadApiToMelBridge(): data = startup.loadCache( 'mayaApiMelBridge', 'the API-MEL bridge', useVersion=False, compressed=True ) if data is not None: # maya 8.5 fix: convert dict to defaultdict bridge, overrides = data bridge = _util.defaultdict(dict, bridge) return bridge, overrides # no bridge cache exists. create default bridge = _util.defaultdict(dict) # no api overrides exist. create default overrides = {} return bridge, overrides
def buildCachedData() : """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 long_version = versions.installName() data = startup.loadCache( 'mayaCmdsList', 'the list of Maya commands' ) if data is not None: cmdlist,nodeHierarchy,uiClassList,nodeCommandList,moduleCmds = data else: # or not isinstance(cmdlist,list): cmdlist = {} _logger.info("Rebuilding the list of Maya commands...") nodeHierarchy = _getNodeHierarchy(long_version) nodeFunctions = [ x[0] for x in nodeHierarchy ] nodeFunctions += nodeTypeToNodeCommand.values() #nodeHierarchyTree = trees.IndexedTree(nodeHierarchy) uiClassList = UI_COMMANDS nodeCommandList = [] for moduleName, longname in moduleNameShortToLong.items(): moduleNameShortToLong[moduleName] = getModuleCommandList( longname, long_version ) tmpCmdlist = inspect.getmembers(cmds, callable) cmdlist = {} #moduleCmds = defaultdict(list) moduleCmds = dict( (k,[]) for k in moduleNameShortToLong.keys() ) 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 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: moduleCmds[module].append(funcName) if module != 'runtime': cmdInfo = getCmdInfo(funcName, long_version) if module != 'windows': if funcName in nodeFunctions: 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 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: # 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'): # cmdlist[funcName] = (funcName, args, (False, None, None) ) # else: # cmdlist[funcName] = (funcName, args, () ) # split the cached data for lazy loading cmdDocList = {} examples = {} for cmdName, cmdInfo in 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 startup.writeCache( (cmdlist,nodeHierarchy,uiClassList,nodeCommandList,moduleCmds), 'mayaCmdsList', 'the list of Maya commands',compressed=True ) startup.writeCache( cmdDocList, 'mayaCmdsDocs', 'the Maya command documentation',compressed=True ) startup.writeCache( examples, 'mayaCmdsExamples', 'the list of Maya command examples',compressed=True ) # corrections that are always made, to both loaded and freshly built caches util.mergeCascadingDicts( cmdlistOverrides, cmdlist ) # add in any nodeCommands added after cache rebuild nodeCommandList = set(nodeCommandList).union(nodeTypeToNodeCommand.values()) nodeCommandList = sorted( nodeCommandList ) for module, funcNames in moduleCommandAdditions.iteritems(): for funcName in funcNames: currModule = cmdlist[funcName]['type'] if currModule != module: cmdlist[funcName]['type'] = module id = moduleCmds[currModule].index(funcName) moduleCmds[currModule].pop(id) moduleCmds[module].append(funcName) return (cmdlist,nodeHierarchy,uiClassList,nodeCommandList,moduleCmds)
def fixCodeExamples(style='maya', force=False): """cycle through all examples from the maya docs, replacing maya.cmds with pymel and inserting pymel output. NOTE: this can only be run from gui mode WARNING: back up your preferences before running TODO: auto backup and restore of maya prefs """ manipOptions = cmds.manipOptions( q=1, handleSize=1, scale=1 ) animOptions = [] animOptions.append( cmds.animDisplay( q=1, timeCode=True ) ) animOptions.append( cmds.animDisplay( q=1, timeCodeOffset=True ) ) animOptions.append( cmds.animDisplay( q=1, modelUpdate=True ) ) openWindows = cmds.lsUI(windows=True) examples = startup.loadCache('mayaCmdsExamples', useVersion=True) processedExamples = startup.loadCache('mayaCmdsExamples', useVersion=False) processedExamples = {} if processedExamples is None else processedExamples allCmds = set(examples.keys()) # put commands that require manual interaction first manualCmds = ['fileBrowserDialog', 'fileDialog', 'fileDialog2', 'fontDialog'] skipCmds = ['colorEditor', 'emit', 'finder', 'doBlur', 'messageLine', 'renderWindowEditor', 'ogsRender', 'webBrowser'] allCmds.difference_update(manualCmds) allCmds.difference_update(skipCmds) sortedCmds = manualCmds + sorted(allCmds) for command in sortedCmds: example = examples[command] if not force and command in processedExamples: _logger.info("%s: already completed. skipping." % command) continue _logger.info("Starting command %s", command) # change from cmds to pymel reg = re.compile(r'\bcmds\.') example = reg.sub( 'pm.', example ) #example = example.replace( 'import maya.cmds as cmds', 'import pymel as pm\npm.newFile(f=1) #fresh scene' ) lines = example.split('\n') if len(lines)==1: _logger.info("removing empty example for command %s", command) examples.pop(command) continue if style == 'doctest' : DOC_TEST_SKIP = ' #doctest: +SKIP' else: DOC_TEST_SKIP = '' lines[0] = 'import pymel.core as pm' + DOC_TEST_SKIP #lines.insert(1, 'pm.newFile(f=1) #fresh scene') # create a fresh scene. this does not need to be in the docstring unless we plan on using it in doctests, which is probably unrealistic cmds.file(new=1,f=1) newlines = [] statement = [] # narrowed down the commands that cause maya to crash to these prefixes if re.match( '(dis)|(dyn)|(poly)', command) : evaluate = False elif command in skipCmds: evaluate = False else: evaluate = True # gives a little leniency for where spaces are placed in the result line resultReg = re.compile('# Result:\s*(.*) #$') try: # funky things can happen when executing maya code: some exceptions somehow occur outside the eval/exec for i, line in enumerate(lines): res = None # replace with pymel results '# Result: 1 #' m = resultReg.match(line) if m: if evaluate is False: line = m.group(1) newlines.append(' ' + line) else: if evaluate: if line.strip().endswith(':') or line.startswith(' ') or line.startswith('\t'): statement.append(line) else: # evaluate the compiled statement using exec, which can do multi-line if statements and so on if statement: try: #_logger.debug("executing %s", statement) exec( '\n'.join(statement) ) # reset statement statement = [] except Exception, e: _logger.info("stopping evaluation %s", str(e))# of %s on line %r" % (command, line) evaluate = False try: _logger.debug("evaluating: %r" % line) res = eval( line ) #if res is not None: _logger.info("result", repr(repr(res))) #else: _logger.info("no result") except: #_logger.debug("failed evaluating:", str(e)) try: exec( line ) except (Exception, TypeError), e: _logger.info("stopping evaluation %s", str(e))# of %s on line %r" % (command, line) evaluate = False if style == 'doctest': if line.startswith(' ') or line.startswith('\t'): newlines.append(' ... ' + line ) else: newlines.append(' >>> ' + line + DOC_TEST_SKIP ) if res is not None: newlines.append( ' ' + repr(res) ) else: newlines.append(' ' + line ) if res is not None: newlines.append( ' # Result: %r #' % (res,) ) if evaluate: _logger.info("successful evaluation! %s", command) example = '\n'.join( newlines ) processedExamples[command] = example