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 parse(self, apiClassName): self.enums = {} self.pymelEnums = {} self.methods=util.defaultdict(list) self.currentMethod=None self.badEnums = [] for proto in self.iterProto(apiClassName): methodName, returnType = self.getMethodNameAndOutput(proto) if methodName is None: continue # convert to unicode self.currentMethod = str(methodName) if self.currentMethod == 'void(*': continue # ENUMS if returnType == 'enum': self.xprint( "ENUM", returnType) #print returnType, methodName try: #print enumList enumData = self.parseEnums(proto) self.enums[self.currentMethod] = enumData[0] self.pymelEnums[self.currentMethod] = enumData[1] except AttributeError, msg: _logger.error("FAILED ENUM: %s", msg) import traceback _logger.debug(traceback.format_exc()) # ARGUMENTS else: self.xprint( "RETURN", returnType) # Static methods static = False try: res = proto.findAll('code') if res: code = res[-1].string if code and code.strip() == '[static]': static = True except IndexError: pass if self.isObsolete(proto): continue names, types, typeQualifiers, defaults = self.parseTypes(proto) try: directions, docs, methodDoc, returnDoc, deprecated = self.parseMethodArgs(proto, returnType, names, types, typeQualifiers) except AssertionError, msg: _logger.error(self.formatMsg("FAILED", str(msg))) continue except AttributeError: import traceback _logger.error(self.formatMsg(traceback.format_exc())) continue
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, apiModule, version=None, verbose=False, enumClass=tuple, docLocation=None): self.version = versions.installName() if version is None else version self.apiModule = apiModule self.verbose = verbose if docLocation is None: docLocation = mayaDocsLocation('2009' if self.version=='2008' else self.version) self.docloc = docLocation 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 parse(self, apiClassName): self.enums = {} self.pymelEnums = {} self.methods=util.defaultdict(list) self.currentMethod=None self.badEnums = [] self.apiClassName = apiClassName self.apiClass = getattr(self.apiModule, self.apiClassName) self.docfile = os.path.join( self.docloc , 'API', self.getClassFilename() + '.html' ) _logger.info( "parsing file %s" , self.docfile ) f = open( self.docfile ) soup = BeautifulSoup( f.read(), convertEntities='html' ) f.close() for proto in soup.body.findAll( 'div', **{'class':'memproto'} ): returnDoc = '' # NAME AND RETURN TYPE memb = proto.findAll( 'td', **{'class':'memname'} )[0] buf = [ x.strip() for x in memb.findAll( text=True )] if len(buf) ==1: buf = [ x for x in buf[0].split() if x not in ['const', 'unsigned'] ] if len(buf)==1: returnType = None methodName = buf[0] else: returnType = ''.join(buf[:-1]) methodName = buf[-1] else: returnType = buf[0] methodName = buf[1] buf = [ x for x in buf[0].split() if x not in ['const', 'unsigned'] ] if len(buf) > 1: returnType += buf[0] methodName = buf[1] methodName = methodName.split('::')[-1] # convert operators to python special methods if methodName.startswith('operator'): methodName = self.getOperatorName(methodName) if methodName is None: continue # no MStatus in python if returnType in ['MStatus', 'void']: returnType = None else: returnType = self.handleEnums(returnType) # convert to unicode self.currentMethod = str(methodName) #constructors and destructors if self.currentMethod.startswith('~') or self.currentMethod == self.apiClassName: continue # ENUMS if returnType == 'enum': self.xprint( "ENUM", returnType) #print returnType, methodName try: enumValues={} enumDocs={} for em in proto.findNextSiblings( 'div', limit=1)[0].findAll( 'em'): enumKey = str(em.contents[-1]) try: enumVal = getattr(self.apiClass, enumKey) except: _logger.warn( "%s.%s of enum %s does not exist" % ( self.apiClassName, enumKey, self.currentMethod)) enumVal = None enumValues[ enumKey ] = enumVal docItem = em.next.next.next.next.next if isinstance( docItem, NavigableString ): enumDocs[enumKey] = str(docItem).strip() else: enumDocs[enumKey] = str(docItem.contents[0]).strip() pymelEnumList = self.getPymelEnums( enumValues ) for val, pyval in zip(enumValues,pymelEnumList): enumDocs[pyval] = enumDocs[val] enumInfo = {'values' : util.Enum(self.currentMethod, enumValues, multiKeys=True), 'valueDocs' : enumDocs, #'doc' : methodDoc } #print enumList self.enums[self.currentMethod] = enumInfo self.pymelEnums[self.currentMethod] = util.Enum(self.currentMethod, pymelEnumList, multiKeys=True) except AttributeError, msg: _logger.error( "FAILED ENUM: %s", msg ) # ARGUMENTS else: self.xprint( "RETURN", returnType) argInfo={} argList=[] defaults={} names=[] directions={} docs={} inArgs=[] outArgs=[] types ={} typeQualifiers={} methodDoc = '' deprecated = False # Static methods static = False try: code = proto.findAll('code')[-1].string if code and code.strip() == '[static]': static = True except IndexError: pass tmpTypes=[] # TYPES for paramtype in proto.findAll( 'td', **{'class':'paramtype'} ) : buf = [] [ buf.extend(x.split()) for x in paramtype.findAll( text=True ) ] #if x.strip() not in ['', '*', '&', 'const', 'unsigned'] ] buf = [ str(x.strip()) for x in buf if x.strip() ] i=0 for i, each in enumerate(buf): if each not in [ '*', '&', 'const', 'unsigned']: argtype = buf.pop(i) break else: # We didn't find any arg type - therefore everything # in buf is in the set('*', '&', 'const', 'unsigned') # ... so it's implicitly an unsigned int argtype = 'int' if 'unsigned' in buf and argtype in ('char','int', 'int2', 'int3', 'int4'): argtype = 'u' + argtype argtype = self.handleEnums(argtype) #print '\targtype', argtype, buf tmpTypes.append( (argtype, buf) ) # ARGUMENT NAMES i = 0 for paramname in proto.findAll( 'td', **{'class':'paramname'} ) : buf = [ x.strip() for x in paramname.findAll( text=True ) if x.strip() not in['',','] ] if buf: argname = buf[0] data = buf[1:] type, qualifiers = tmpTypes[i] default=None joined = ''.join(data).strip() if joined: # break apart into index and defaults : '[3] = NULL' brackets, default = re.search( '([^=]*)(?:\s*=\s*(.*))?', joined ).groups() if brackets: numbuf = re.split( r'\[|\]', brackets) if len(numbuf) > 1: # Note that these two args need to be cast differently: # int2 foo; # int bar[2]; # ... so, instead of storing the type of both as # 'int2', we make the second one 'int__array2' type = type + '__array' + numbuf[1] else: print "this is not a bracketed number", repr(brackets), joined if default is not None: try: # Constants default = { 'true' : True, 'false': False, 'NULL' : None }[default] except KeyError: try: if type in ['int', 'uint','long', 'uchar']: default = int(default) elif type in ['float', 'double']: # '1.0 / 24.0' if '/' in default: default = eval(default.encode('ascii', 'ignore')) # '1.0e-5F' --> '1.0e-5' elif default.endswith('F'): default = float(default[:-1]) else: default = float(default) else: default = self.handleEnumDefaults(default, type) except ValueError: default = self.handleEnumDefaults(default, type) # default must be set here, because 'NULL' may be set to back to None, but this is in fact the value we want self.xprint('DEFAULT', default) defaults[argname] = default types[argname] = type typeQualifiers[argname] = qualifiers names.append(argname) i+=1 try: # ARGUMENT DIRECTION AND DOCUMENTATION addendum = proto.findNextSiblings( 'div', limit=1)[0] #try: self.xprint( addendum.findAll(text=True ) ) #except: pass #if addendum.findAll( text = re.compile( '(This method is obsolete.)|(Deprecated:)') ): if addendum.findAll( text=lambda x: x in self.OBSOLETE_MSG ): self.xprint( "OBSOLETE" ) self.currentMethod = None continue #if self.currentMethod == 'createColorSet': raise NotImplementedError if addendum.findAll( text=lambda x: x in self.DEPRECATED_MSG ): self.xprint( "DEPRECATED" ) #print self.apiClassName + '.' + self.currentMethod + ':' + ' DEPRECATED' deprecated = True methodDoc = ' '.join( addendum.p.findAll( text=True ) ) tmpDirs = [] tmpNames = [] tmpDocs = [] #extraInfo = addendum.dl.table extraInfos = addendum.findAll('table') if extraInfos: #print "NUMBER OF TABLES", len(extraInfos) for extraInfo in extraInfos: tmpDirs += extraInfo.findAll( text=lambda text: text in ['[in]', '[out]'] ) #tmpNames += [ em.findAll( text=True, limit=1 )[0] for em in extraInfo.findAll( 'em') ] tmpNames = [] for tr in extraInfo.findAll( 'tr'): assert tr, "could not find name tr" em = tr.findNext( 'em' ) assert tr, "could not find name em" name = em.findAll( text=True, limit=1 )[0] tmpNames.append(name) # for td in extraInfo.findAll( 'td' ): # assert td, "could not find doc td" # for doc in td.findAll( text=lambda text: text.strip(), recursive=False) : # if doc: tmpDocs.append( ''.join(doc) ) for doc in [td.findAll( text=lambda text: text.strip(), recursive=False) for td in extraInfo.findAll( 'td' )]: if doc: tmpDocs.append( ''.join(doc) ) assert len(tmpDirs) == len(tmpNames) == len(tmpDocs), 'names and types lists are of unequal lengths: %s vs. %s vs. %s' % (tmpDirs, tmpNames, tmpDocs) assert sorted(tmpNames) == sorted(typeQualifiers.keys()), 'name list mismatch %s %s' % (sorted(tmpNames), sorted(typeQualifiers.keys()) ) #self.xprint( sorted(tmpNames), sorted(typeQualifiers.keys()), sorted(typeQualifiers.keys()) ) for name, dir, doc in zip(tmpNames, tmpDirs, tmpDocs) : if dir == '[in]': # attempt to correct bad in/out docs if re.search(r'\b([fF]ill|[sS]tor(age)|(ing))|([rR]esult)', doc ): _logger.warn( "%s.%s(%s): Correcting suspected output argument '%s' based on doc '%s'" % ( self.apiClassName,self.currentMethod,', '.join(names), name, doc)) dir = 'out' elif not re.match( 'set[A-Z]', self.currentMethod) and '&' in typeQualifiers[name] and types[name] in ['int', 'double', 'float', 'uint', 'uchar']: _logger.warn( "%s.%s(%s): Correcting suspected output argument '%s' based on reference type '%s &' ('%s')'" % ( self.apiClassName,self.currentMethod,', '.join(names), name, types[name], doc)) dir = 'out' else: dir = 'in' elif dir == '[out]': if types[name] == 'MAnimCurveChange': _logger.warn( "%s.%s(%s): Setting MAnimCurveChange argument '%s' to an input arg (instead of output)" % ( self.apiClassName,self.currentMethod,', '.join(names), name)) dir = 'in' else: dir = 'out' else: raise assert name in names directions[name] = dir docs[name] = doc # Documentation for Return Values if returnType: try: returnDocBuf = addendum.findAll( 'dl', limit=1, **{'class':'return'} )[0].findAll( text=True ) except IndexError: pass else: if returnDocBuf: returnDoc = ''.join( returnDocBuf[1:] ).strip('\n') self.xprint( 'RETURN_DOC', repr(returnDoc) ) except (AttributeError, AssertionError), msg: self.xprint( "FAILED", str(msg) ) pass # print names # print types # print defaults # print directions # print docs for argname in names[:] : type = types[argname] direction = directions.get(argname, 'in') doc = docs.get( argname, '') if type == 'MStatus': types.pop(argname) defaults.pop(argname,None) directions.pop(argname,None) docs.pop(argname,None) idx = names.index(argname) names.pop(idx) else: if direction == 'in': inArgs.append(argname) else: outArgs.append(argname) argInfo[ argname ] = {'type': type, 'doc': doc } # correct bad outputs if self.isGetMethod() and not returnType and not outArgs: for argname in names: if '&' in typeQualifiers[argname]: doc = docs.get(argname, '') directions[argname] = 'out' idx = inArgs.index(argname) inArgs.pop(idx) outArgs.append(argname) _logger.warn( "%s.%s(%s): Correcting suspected output argument '%s' because there are no outputs and the method is prefixed with 'get' ('%s')" % ( self.apiClassName,self.currentMethod, ', '.join(names), argname, doc)) # now that the directions are correct, make the argList for argname in names: type = types[argname] direction = directions.get(argname, 'in') data = ( argname, type, direction) if self.verbose: self.xprint( "ARG", data ) argList.append( data ) methodInfo = { 'argInfo': argInfo, 'returnInfo' : { 'type' : returnType, 'doc' : returnDoc }, 'args' : argList, 'returnType' : returnType, 'inArgs' : inArgs, 'outArgs' : outArgs, 'doc' : methodDoc, 'defaults' : defaults, #'directions' : directions, 'types' : types, 'static' : static, 'typeQualifiers' : typeQualifiers, 'deprecated' : deprecated } self.methods[self.currentMethod].append(methodInfo) # reset self.currentMethod=None
def _defaultdictdict(cls, val=None): if val is None: return _util.defaultdict(dict) else: return _util.defaultdict(dict, val)
def parse(self, apiClassName): self.enums = {} self.pymelEnums = {} self.methods = util.defaultdict(list) self.currentMethod = None self.badEnums = [] self.apiClassName = apiClassName self.apiClass = getattr(self.apiModule, self.apiClassName) self.docfile = os.path.join(self.docloc, 'API', self.getClassFilename() + '.html') _logger.info("parsing file %s", self.docfile) f = open(self.docfile) soup = BeautifulSoup(f.read(), convertEntities='html') f.close() for proto in soup.body.findAll('div', **{'class': 'memproto'}): returnDoc = '' # NAME AND RETURN TYPE memb = proto.findAll('td', **{'class': 'memname'})[0] buf = [x.strip() for x in memb.findAll(text=True)] if len(buf) == 1: buf = [ x for x in buf[0].split() if x not in ['const', 'unsigned'] ] if len(buf) == 1: returnType = None methodName = buf[0] else: returnType = ''.join(buf[:-1]) methodName = buf[-1] else: returnType = buf[0] methodName = buf[1] buf = [ x for x in buf[0].split() if x not in ['const', 'unsigned'] ] if len(buf) > 1: returnType += buf[0] methodName = buf[1] methodName = methodName.split('::')[-1] # convert operators to python special methods if methodName.startswith('operator'): methodName = self.getOperatorName(methodName) if methodName is None: continue # no MStatus in python if returnType in ['MStatus', 'void']: returnType = None else: returnType = self.handleEnums(returnType) # convert to unicode self.currentMethod = str(methodName) #constructors and destructors if self.currentMethod.startswith( '~') or self.currentMethod == self.apiClassName: continue # ENUMS if returnType == 'enum': self.xprint("ENUM", returnType) #print returnType, methodName try: enumValues = {} enumDocs = {} for em in proto.findNextSiblings('div', limit=1)[0].findAll('em'): enumKey = str(em.contents[-1]) try: enumVal = getattr(self.apiClass, enumKey) except: _logger.warn("%s.%s of enum %s does not exist" % (self.apiClassName, enumKey, self.currentMethod)) enumVal = None enumValues[enumKey] = enumVal docItem = em.next.next.next.next.next if isinstance(docItem, NavigableString): enumDocs[enumKey] = str(docItem).strip() else: enumDocs[enumKey] = str( docItem.contents[0]).strip() pymelEnumList = self.getPymelEnums(enumValues) for val, pyval in zip(enumValues, pymelEnumList): enumDocs[pyval] = enumDocs[val] enumInfo = { 'values': util.Enum(self.currentMethod, enumValues, multiKeys=True), 'valueDocs': enumDocs, #'doc' : methodDoc } #print enumList self.enums[self.currentMethod] = enumInfo self.pymelEnums[self.currentMethod] = util.Enum( self.currentMethod, pymelEnumList, multiKeys=True) except AttributeError, msg: _logger.error("FAILED ENUM: %s", msg) # ARGUMENTS else: self.xprint("RETURN", returnType) argInfo = {} argList = [] defaults = {} names = [] directions = {} docs = {} inArgs = [] outArgs = [] types = {} typeQualifiers = {} methodDoc = '' deprecated = False # Static methods static = False try: code = proto.findAll('code')[-1].string if code and code.strip() == '[static]': static = True except IndexError: pass tmpTypes = [] # TYPES for paramtype in proto.findAll('td', **{'class': 'paramtype'}): buf = [] [ buf.extend(x.split()) for x in paramtype.findAll(text=True) ] #if x.strip() not in ['', '*', '&', 'const', 'unsigned'] ] buf = [str(x.strip()) for x in buf if x.strip()] i = 0 for i, each in enumerate(buf): if each not in ['*', '&', 'const', 'unsigned']: argtype = buf.pop(i) break else: # We didn't find any arg type - therefore everything # in buf is in the set('*', '&', 'const', 'unsigned') # ... so it's implicitly an unsigned int argtype = 'int' if 'unsigned' in buf and argtype in ('char', 'int', 'int2', 'int3', 'int4'): argtype = 'u' + argtype argtype = self.handleEnums(argtype) #print '\targtype', argtype, buf tmpTypes.append((argtype, buf)) # ARGUMENT NAMES i = 0 for paramname in proto.findAll('td', **{'class': 'paramname'}): buf = [ x.strip() for x in paramname.findAll(text=True) if x.strip() not in ['', ','] ] if buf: argname = buf[0] data = buf[1:] type, qualifiers = tmpTypes[i] default = None joined = ''.join(data).strip() if joined: joined = joined.encode('ascii', 'ignore') # break apart into index and defaults : '[3] = NULL' brackets, default = re.search( '([^=]*)(?:\s*=\s*(.*))?', joined).groups() if brackets: numbuf = re.split(r'\[|\]', brackets) if len(numbuf) > 1: # Note that these two args need to be cast differently: # int2 foo; # int bar[2]; # ... so, instead of storing the type of both as # 'int2', we make the second one 'int__array2' type = type + '__array' + numbuf[1] else: print "this is not a bracketed number", repr( brackets), joined if default is not None: try: # Constants default = { 'true': True, 'false': False, 'NULL': None }[default] except KeyError: try: if type in [ 'int', 'uint', 'long', 'uchar' ]: default = int(default) elif type in ['float', 'double']: # '1.0 / 24.0' if '/' in default: default = eval(default) # '1.0e-5F' --> '1.0e-5' elif default.endswith('F'): default = float(default[:-1]) else: default = float(default) else: default = self.handleEnumDefaults( default, type) except ValueError: default = self.handleEnumDefaults( default, type) # default must be set here, because 'NULL' may be set to back to None, but this is in fact the value we want self.xprint('DEFAULT', default) defaults[argname] = default types[argname] = type typeQualifiers[argname] = qualifiers names.append(argname) i += 1 try: # ARGUMENT DIRECTION AND DOCUMENTATION addendum = proto.findNextSiblings('div', limit=1)[0] #try: self.xprint( addendum.findAll(text=True ) ) #except: pass #if addendum.findAll( text = re.compile( '(This method is obsolete.)|(Deprecated:)') ): if addendum.findAll(text=lambda x: x in self.OBSOLETE_MSG): self.xprint("OBSOLETE") self.currentMethod = None continue #if self.currentMethod == 'createColorSet': raise NotImplementedError if addendum.findAll( text=lambda x: x in self.DEPRECATED_MSG): self.xprint("DEPRECATED") #print self.apiClassName + '.' + self.currentMethod + ':' + ' DEPRECATED' deprecated = True methodDoc = ' '.join(addendum.p.findAll(text=True)) tmpDirs = [] tmpNames = [] tmpDocs = [] #extraInfo = addendum.dl.table extraInfos = addendum.findAll('table') if extraInfos: #print "NUMBER OF TABLES", len(extraInfos) for extraInfo in extraInfos: tmpDirs += extraInfo.findAll( text=lambda text: text in ['[in]', '[out]']) #tmpNames += [ em.findAll( text=True, limit=1 )[0] for em in extraInfo.findAll( 'em') ] tmpNames = [] for tr in extraInfo.findAll('tr'): assert tr, "could not find name tr" em = tr.findNext('em') assert tr, "could not find name em" name = em.findAll(text=True, limit=1)[0] tmpNames.append(name) # for td in extraInfo.findAll( 'td' ): # assert td, "could not find doc td" # for doc in td.findAll( text=lambda text: text.strip(), recursive=False) : # if doc: tmpDocs.append( ''.join(doc) ) for doc in [ td.findAll(text=lambda text: text.strip(), recursive=False) for td in extraInfo.findAll('td') ]: if doc: tmpDocs.append(''.join(doc)) assert len(tmpDirs) == len(tmpNames) == len( tmpDocs ), 'names and types lists are of unequal lengths: %s vs. %s vs. %s' % ( tmpDirs, tmpNames, tmpDocs) assert sorted(tmpNames) == sorted(typeQualifiers.keys( )), 'name list mismatch %s %s' % ( sorted(tmpNames), sorted(typeQualifiers.keys())) #self.xprint( sorted(tmpNames), sorted(typeQualifiers.keys()), sorted(typeQualifiers.keys()) ) for name, dir, doc in zip(tmpNames, tmpDirs, tmpDocs): if dir == '[in]': # attempt to correct bad in/out docs if re.search( r'\b([fF]ill|[sS]tor(age)|(ing))|([rR]esult)', doc): _logger.warn( "%s.%s(%s): Correcting suspected output argument '%s' based on doc '%s'" % (self.apiClassName, self.currentMethod, ', '.join(names), name, doc)) dir = 'out' elif not re.match( 'set[A-Z]', self.currentMethod ) and '&' in typeQualifiers[name] and types[ name] in [ 'int', 'double', 'float', 'uint', 'uchar' ]: _logger.warn( "%s.%s(%s): Correcting suspected output argument '%s' based on reference type '%s &' ('%s')'" % (self.apiClassName, self.currentMethod, ', '.join(names), name, types[name], doc)) dir = 'out' else: dir = 'in' elif dir == '[out]': if types[name] == 'MAnimCurveChange': _logger.warn( "%s.%s(%s): Setting MAnimCurveChange argument '%s' to an input arg (instead of output)" % (self.apiClassName, self.currentMethod, ', '.join(names), name)) dir = 'in' else: dir = 'out' else: raise assert name in names directions[name] = dir docs[name] = doc # Documentation for Return Values if returnType: try: returnDocBuf = addendum.findAll( 'dl', limit=1, **{'class': 'return'})[0].findAll(text=True) except IndexError: pass else: if returnDocBuf: returnDoc = ''.join( returnDocBuf[1:]).strip('\n') self.xprint('RETURN_DOC', repr(returnDoc)) except (AttributeError, AssertionError), msg: self.xprint("FAILED", str(msg)) pass # print names # print types # print defaults # print directions # print docs for argname in names[:]: type = types[argname] direction = directions.get(argname, 'in') doc = docs.get(argname, '') if type == 'MStatus': types.pop(argname) defaults.pop(argname, None) directions.pop(argname, None) docs.pop(argname, None) idx = names.index(argname) names.pop(idx) else: if direction == 'in': inArgs.append(argname) else: outArgs.append(argname) argInfo[argname] = {'type': type, 'doc': doc} # correct bad outputs if self.isGetMethod() and not returnType and not outArgs: for argname in names: if '&' in typeQualifiers[argname]: doc = docs.get(argname, '') directions[argname] = 'out' idx = inArgs.index(argname) inArgs.pop(idx) outArgs.append(argname) _logger.warn( "%s.%s(%s): Correcting suspected output argument '%s' because there are no outputs and the method is prefixed with 'get' ('%s')" % (self.apiClassName, self.currentMethod, ', '.join(names), argname, doc)) # now that the directions are correct, make the argList for argname in names: type = types[argname] direction = directions.get(argname, 'in') data = (argname, type, direction) if self.verbose: self.xprint("ARG", data) argList.append(data) methodInfo = { 'argInfo': argInfo, 'returnInfo': { 'type': returnType, 'doc': returnDoc }, 'args': argList, 'returnType': returnType, 'inArgs': inArgs, 'outArgs': outArgs, 'doc': methodDoc, 'defaults': defaults, #'directions' : directions, 'types': types, 'static': static, 'typeQualifiers': typeQualifiers, 'deprecated': deprecated } self.methods[self.currentMethod].append(methodInfo) # reset self.currentMethod = None