def fileOnMelPath( file ): """ Return True if this file is on the mel path. """ file = util.path(file) info = mel.whatIs( file.basename() ).split(': ', 1) if len(info) < 2: # If there wasn't a ':' character, the result was probably 'Unknown, or something similar - # anyway, not what we're looking for return False if info[0] not in ('Mel procedure found in', 'Script found in'): return False path = util.path(info[1]) return path.samepath(file)
def fileOnMelPath(file): """ Return True if this file is on the mel path. """ file = util.path(file) info = pm.mel.whatIs(file.basename()).split(': ', 1) if len(info) < 2: # If there wasn't a ':' character, the result was probably 'Unknown, or something similar - # anyway, not what we're looking for return False if info[0] not in ('Mel procedure found in', 'Script found in'): return False path = util.path(info[1]) return path.samepath(file)
def source(cls, script, language='mel'): """use this to source mel or python scripts. :Parameters: language : {'mel', 'python'} When set to 'python', the source command will look for the python equivalent of this mel file, if it exists, and attempt to import it. This is particularly useful when transitioning from mel to python via `pymel.tools.mel2py`, with this simple switch you can change back and forth from sourcing mel to importing python. """ if language == 'mel': cls.eval( """source "%s";""" % script ) elif language == 'python': script = util.path(script) modulePath = script.namebase folder = script.parent print modulePath if not sys.modules.has_key(modulePath): print "importing" module = __import__(modulePath, globals(), locals(), ['']) sys.modules[modulePath] = module else: raise TypeError, "language keyword expects 'mel' or 'python'. got '%s'" % language
def source(cls, script, language='mel'): """use this to source mel or python scripts. :Parameters: language : {'mel', 'python'} When set to 'python', the source command will look for the python equivalent of this mel file, if it exists, and attempt to import it. This is particularly useful when transitioning from mel to python via `pymel.tools.mel2py`, with this simple switch you can change back and forth from sourcing mel to importing python. """ if language == 'mel': cls.eval("""source "%s";""" % script) elif language == 'python': script = util.path(script) modulePath = script.namebase folder = script.parent print modulePath if not sys.modules.has_key(modulePath): print "importing" module = __import__(modulePath, globals(), locals(), ['']) sys.modules[modulePath] = module else: raise TypeError, "language keyword expects 'mel' or 'python'. got '%s'" % language
def resolvePath(melobj, recurse=False, exclude=(), melPathOnly=False, basePackage=''): """ if passed a directory, get all mel files in the directory if passed a file, ensure it is a mel file if passed a procedure name, find its file Returns tuples of the form (moduleName, melfile). """ if basePackage is None: basePackage = '' files = [] recursedResults = [] filepath = util.path(melobj) if filepath.isfile(): if filepath.ext == '.mel': files = [filepath.truepath()] else: log.warning("File is not a mel script: %s" % (filepath)) files = [] elif filepath.isdir(): files = [f.truepath() for f in filepath.files('[a-zA-Z]*.mel')] if recurse: for dir in filepath.dirs(): recursedResults.extend( resolvePath(dir, recurse=recurse, exclude=exclude, melPathOnly=melPathOnly, basePackage=basePackage + '.' + melparse.pythonizeName(dir.basename()))) #elif not filepath.exists(): else: # see if it's a procedure that we can derive a path from try: info = pm.mel.whatIs(melobj).split(': ')[-1] assert info != 'Unknown', "If providing a procedure or a short file name, ensure the appropriate script is sourced" melfile = util.path(info) files = [melfile.truepath()] except Exception, msg: log.warning("Could not determine mel script from input '%s': %s." % (filepath, msg))
def nameFromFile(self, pathname): try: fpPathObj = pu.path(pathname) fpFileObj = pu.path.basename(fpPathObj) fpFile = fpFileObj.split(".") fpName = fpFile[0] return fpName except: return "imgPlane"
def _updateCurrentModules( newResults ): currentModules = melparse.batchData.currentModules for moduleName, melfile in newResults: if not isinstance(melfile, Path): melfile = util.path(melfile) if melfile in currentModules.values(): oldModule = currentModules.get_key(melfile) if oldModule == moduleName: continue if moduleName.count('.') >= oldModule.count('.'): continue elif moduleName in currentModules: raise RuntimeError('two mel files result in same python module name: %s, %s => %s' % (currentModules[moduleName], melfile, moduleName)) currentModules[moduleName] = melfile
def resolvePath( melobj, recurse=False, exclude=(), melPathOnly=False, basePackage='' ): """ if passed a directory, get all mel files in the directory if passed a file, ensure it is a mel file if passed a procedure name, find its file Returns tuples of the form (moduleName, melfile). """ if basePackage is None: basePackage = '' files = [] recursedResults = [] filepath = util.path( melobj ) if filepath.isfile(): if filepath.ext == '.mel': files = [ filepath.canonicalpath() ] else: log.warning( "File is not a mel script: %s" % (filepath) ) files = [] elif filepath.isdir(): files = [ f.canonicalpath() for f in filepath.files( '[a-zA-Z]*.mel') ] if recurse: for dir in filepath.dirs(): recursedResults.extend(resolvePath(dir, recurse=recurse, exclude=exclude, melPathOnly=melPathOnly, basePackage = basePackage + '.' + pythonizeName(dir.basename()))) #elif not filepath.exists(): else: # see if it's a procedure that we can derive a path from try: info = mel.whatIs( melobj ).split(': ')[-1] assert info != 'Unknown', "If providing a procedure or a short file name, ensure the appropriate script is sourced" melfile = util.path( info ) files = [ melfile.canonicalpath() ] except Exception, msg: log.warning( "Could not determine mel script from input '%s': %s." % (filepath, msg) )
def _updateCurrentModules(newResults): currentModules = melparse.batchData.currentModules for moduleName, melfile in newResults: if not isinstance(melfile, pm.Path): melfile = util.path(melfile) if melfile in currentModules.values(): oldModule = currentModules.get_key(melfile) if oldModule == moduleName: continue if moduleName.count('.') >= oldModule.count('.'): continue elif moduleName in currentModules: raise RuntimeError( 'two mel files result in same python module name: %s, %s => %s' % (currentModules[moduleName], melfile, moduleName)) currentModules[moduleName] = melfile
def findMelOnlyCommands(): """ Using maya's documentation, find commands which were not ported to python. """ docs = util.path( _factories.mayaDocsLocation() ) melCmds = set([ x.namebase for x in ( docs / 'Commands').files('*.html') ]) pyCmds = set([ x.namebase for x in ( docs / 'CommandsPython').files('*.html') ]) result = [] for cmd in sorted(melCmds.difference(pyCmds)): typ = pymel.mel.whatIs(cmd) if typ.startswith( 'Script') or typ.startswith( 'Mel' ): typ = 'Mel' try: func = getattr( pymel, cmd) info = func.__module__ except AttributeError: if hasattr( builtin_module, cmd): info = 'builtin' else: info = proc_remap.has_key( cmd ) result.append( (cmd, typ, info ) ) return result
def findMelOnlyCommands(): """ Using maya's documentation, find commands which were not ported to python. """ docs = util.path(_factories.mayaDocsLocation()) melCmds = set([x.namebase for x in (docs / 'Commands').files('*.html')]) pyCmds = set( [x.namebase for x in (docs / 'CommandsPython').files('*.html')]) result = [] for cmd in sorted(melCmds.difference(pyCmds)): typ = pymel.mel.whatIs(cmd) if typ.startswith('Script') or typ.startswith('Mel'): typ = 'Mel' try: func = getattr(pymel, cmd) info = func.__module__ except AttributeError: if hasattr(melparse.builtin_module, cmd): info = 'builtin' else: info = melparse.proc_remap.has_key(cmd) result.append((cmd, typ, info)) return result
def mel2py(input, outputDir=None, pymelNamespace='', forceCompatibility=False, verbosity=0, test=False, recurse=False, exclude=(), melPathOnly=False, basePackage=None): """ Batch convert an entire directory :Parameters: input May be a directory, a list of directories, the name of a mel file, a list of mel files, or the name of a sourced procedure. If only the name of the mel file is passed, mel2py will attempt to determine the location of the file using the 'whatIs' mel command, which relies on the script already being sourced by maya. outputDir : `str` Directory where resulting python files will be written to pymelNamespace : `str` the namespace into which pymel will be imported. the default is '', which means ``from pymel.all import *`` forceCompatibility : `bool` If True, the translator will attempt to use non-standard python types in order to produce python code which more exactly reproduces the behavior of the original mel file, but which will produce "uglier" code. Use this option if you wish to produce the most reliable code without any manual cleanup. verbosity : `int` Set to non-zero for a *lot* of feedback test : `bool` After translation, attempt to import the modules to test for errors recurse : `bool` If the input is a directory, whether or not to recursively search subdirectories as well. Subdirectories will be converted into packages, and any mel files within those subdirectories will be submodules of that package. exclude : `str` A comma-separated list of files/directories to exclude from processing, if input is a directory. melPathOnly : `bool` If true, will only translate mel files found on the mel script path. basePackage : `str` Gives the package that all translated modules will be a part of; if None or an empty string, all translated modules are assumed to have no base package. """ if basePackage is None: basePackage = '' melparse.batchData = melparse.BatchData() batchData = melparse.batchData batchData.basePackage = basePackage if outputDir is not None: outputDir = util.path(outputDir) batchData.outputDir = outputDir if outputDir and not os.path.exists(outputDir): os.makedirs(outputDir) currentFiles = _getInputFiles(input, recurse=recurse, exclude=exclude, melPathOnly=melPathOnly, basePackage=basePackage) if not currentFiles: raise ValueError, "Could not find any scripts to operate on. Please pass a directory, a list of directories, the name of a mel file, a list of mel files, or the name of a sourced procedure" _updateCurrentModules(currentFiles) _makePackages() importCnt = 0 succeeded = [] for moduleName, melfile in batchData.currentModules.iteritems(): print melfile, moduleName if melfile in batchData.scriptPath_to_moduleText: print "Using pre-converted mel script", melfile converted = batchData.scriptPath_to_moduleText[melfile] else: data = melfile.bytes() print "Converting mel script", melfile try: converted = mel2pyStr(data, moduleName, pymelNamespace=pymelNamespace, verbosity=verbosity) except melparse.MelParseError, e: if e.file is None: e.file = melfile raise header = """%s from mel file: # %s """ % (melparse.tag, melfile) converted = header + converted splitModule = moduleName.split('.') if outputDir is None: currOutDir = melfile.parent else: currOutDir = outputDir if len(splitModule) > 1: currOutDir = currOutDir.joinpath(*splitModule[:-1]) pyfile = currOutDir.joinpath(splitModule[-1] + '.py') print "Writing converted python script: %s" % pyfile pyfile.write_bytes(converted) succeeded.append(pyfile)
basePackage=basePackage + '.' + melparse.pythonizeName(dir.basename()))) #elif not filepath.exists(): else: # see if it's a procedure that we can derive a path from try: info = pm.mel.whatIs(melobj).split(': ')[-1] assert info != 'Unknown', "If providing a procedure or a short file name, ensure the appropriate script is sourced" melfile = util.path(info) files = [melfile.truepath()] except Exception, msg: log.warning("Could not determine mel script from input '%s': %s." % (filepath, msg)) if exclude: for i, badFile in enumerate(exclude): badFile = util.path(badFile).canonicalpath() if badFile.isdir(): badFile = badFile + os.sep exclude[i] = badFile filteredFiles = [] for f in files: fileGood = True for badFile in exclude: if f.samepath(badFile) \ or (badFile.isdir() and f.canonicalpath().startswith(badFile)): fileGood = False if fileGood: filteredFiles.append(f) files = filteredFiles if melPathOnly:
def mel2py( input, outputDir=None, pymelNamespace='', forceCompatibility=False, verbosity=0 , test=False, recurse=False, exclude=(), melPathOnly=False, basePackage=None): """ Batch convert an entire directory :Parameters: input May be a directory, a list of directories, the name of a mel file, a list of mel files, or the name of a sourced procedure. If only the name of the mel file is passed, mel2py will attempt to determine the location of the file using the 'whatIs' mel command, which relies on the script already being sourced by maya. outputDir : `str` Directory where resulting python files will be written to pymelNamespace : `str` the namespace into which pymel will be imported. the default is '', which means ``from pymel.all import *`` forceCompatibility : `bool` If True, the translator will attempt to use non-standard python types in order to produce python code which more exactly reproduces the behavior of the original mel file, but which will produce "uglier" code. Use this option if you wish to produce the most reliable code without any manual cleanup. verbosity : `int` Set to non-zero for a *lot* of feedback test : `bool` After translation, attempt to import the modules to test for errors recurse : `bool` If the input is a directory, whether or not to recursively search subdirectories as well. Subdirectories will be converted into packages, and any mel files within those subdirectories will be submodules of that package. exclude : `str` A comma-separated list of files/directories to exclude from processing, if input is a directory. melPathOnly : `bool` If true, will only translate mel files found on the mel script path. basePackage : `str` Gives the package that all translated modules will be a part of; if None or an empty string, all translated modules are assumed to have no base package. """ if basePackage is None: basePackage = '' melparse.batchData = BatchData() batchData = melparse.batchData batchData.basePackage = basePackage if outputDir is not None: outputDir = util.path(outputDir) batchData.outputDir = outputDir if outputDir and not os.path.exists(outputDir): os.makedirs(outputDir) currentFiles = _getInputFiles( input, recurse=recurse, exclude=exclude, melPathOnly=melPathOnly, basePackage=basePackage ) if not currentFiles: raise ValueError, "Could not find any scripts to operate on. Please pass a directory, a list of directories, the name of a mel file, a list of mel files, or the name of a sourced procedure" _updateCurrentModules(currentFiles) _makePackages() importCnt = 0 succeeded = [] for moduleName, melfile in batchData.currentModules.iteritems(): print melfile, moduleName if melfile in batchData.scriptPath_to_moduleText: print "Using pre-converted mel script", melfile converted = batchData.scriptPath_to_moduleText[melfile] else: data = melfile.bytes() print "Converting mel script", melfile try: converted = mel2pyStr( data, moduleName, pymelNamespace=pymelNamespace, verbosity=verbosity ) except MelParseError, e: if e.file is None: e.file = melfile raise header = """%s from mel file: # %s """ % (tag, melfile) converted = header + converted splitModule = moduleName.split('.') if outputDir is None: currOutDir = melfile.parent else: currOutDir = outputDir if len(splitModule) > 1: currOutDir = currOutDir.joinpath(*splitModule[:-1]) pyfile = currOutDir.joinpath(splitModule[-1] + '.py') print "Writing converted python script: %s" % pyfile pyfile.write_bytes(converted) succeeded.append( pyfile )
recursedResults.extend(resolvePath(dir, recurse=recurse, exclude=exclude, melPathOnly=melPathOnly, basePackage = basePackage + '.' + pythonizeName(dir.basename()))) #elif not filepath.exists(): else: # see if it's a procedure that we can derive a path from try: info = mel.whatIs( melobj ).split(': ')[-1] assert info != 'Unknown', "If providing a procedure or a short file name, ensure the appropriate script is sourced" melfile = util.path( info ) files = [ melfile.canonicalpath() ] except Exception, msg: log.warning( "Could not determine mel script from input '%s': %s." % (filepath, msg) ) if exclude: for i, badFile in enumerate(exclude): badFile = util.path(badFile).canonicalpath() if badFile.isdir(): badFile = badFile + os.sep exclude[i] = badFile filteredFiles = [] for f in files: fileGood = True for badFile in exclude: if f.samepath(badFile) \ or (badFile.isdir() and f.startswith(badFile)): fileGood = False if fileGood: filteredFiles.append(f) files = filteredFiles if melPathOnly:
def resolvePath(melobj, recurse=False, exclude=(), melPathOnly=False, basePackage=''): """ if passed a directory, get all mel files in the directory if passed a file, ensure it is a mel file if passed a procedure name, find its file Returns tuples of the form (moduleName, melfile). """ if basePackage is None: basePackage = '' files = [] recursedResults = [] filepath = util.path(melobj) if filepath.isfile(): if filepath.ext == '.mel': files = [filepath.truepath()] else: log.warning("File is not a mel script: %s" % (filepath)) files = [] elif filepath.isdir(): files = [f.truepath() for f in filepath.files('[a-zA-Z]*.mel')] if recurse: for dir in filepath.dirs(): recursedResults.extend( resolvePath(dir, recurse=recurse, exclude=exclude, melPathOnly=melPathOnly, basePackage=basePackage + '.' + melparse.pythonizeName(dir.basename()))) # elif not filepath.exists(): else: # see if it's a procedure that we can derive a path from try: info = pm.mel.whatIs(melobj).split(': ')[-1] assert info != 'Unknown', "If providing a procedure or a short file name, ensure the appropriate script is sourced" melfile = util.path(info) files = [melfile.truepath()] except Exception as msg: log.warning("Could not determine mel script from input '%s': %s." % (filepath, msg)) if exclude: for i, badFile in enumerate(exclude): badFile = util.path(badFile).canonicalpath() if badFile.isdir(): badFile = badFile + os.sep exclude[i] = badFile filteredFiles = [] for f in files: fileGood = True for badFile in exclude: if f.samepath(badFile) \ or (badFile.isdir() and f.canonicalpath().startswith(badFile)): fileGood = False if fileGood: filteredFiles.append(f) files = filteredFiles if melPathOnly: files = [x for x in files if fileOnMelPath(x)] if basePackage and basePackage[-1] != '.': basePackage = basePackage + '.' return [(basePackage + melparse.getModuleBasename(x), x) for x in files] + recursedResults