def __init__(self, xml_parser=None, pretty_xml=False): """Inits SoapBuffer. Args: xml_parser: str XML parser to use. pretty_xml: bool Indicator for whether to prettify XML. """ super(SoapBuffer, self).__init__() self._buffer = '' self.__dump = {} self.__xml_parser = xml_parser # Pick a default XML parser, if none was set. if not self.__xml_parser: for parser, status in [(PYXML, PYXML_LIB), (ETREE, ETREE_LIB)]: if status: self.__xml_parser = parser # Validate current state of the chosen XML parser. if self.__xml_parser == PYXML and not PYXML_LIB: msg = 'PyXML v%s or newer is required.' % MIN_PYXML_VERSION raise MissingPackageError(msg) elif self.__xml_parser == ETREE and not ETREE_LIB: msg = 'ElementTree v%s or newer is required.' % MIN_ETREE_VERSION raise MissingPackageError(msg) elif self.__xml_parser != PYXML and self.__xml_parser != ETREE: msg = ('Invalid input for XML parser, expecting one of %s.' % sorted(set(PYXML + ETREE))) raise InvalidInputError(msg) # Set XML parser signature. if self.__xml_parser == PYXML: self.__xml_parser_sig = '%s v%s' % (PYXML_NAME, MIN_PYXML_VERSION) elif self.__xml_parser == ETREE: self.__xml_parser_sig = '%s v%s' % (ETREE_NAME, ETREE_VERSION) self.__pretty_xml = pretty_xml
LIB_HOME = os.path.abspath(os.path.join(os.path.dirname(__file__))) LIB_NAME = 'AdWords API Python Client Library' LIB_SHORT_NAME = 'AwApi-Python' LIB_URL = 'http://code.google.com/p/google-api-adwords-python-lib' LIB_AUTHOR = 'Stan Grinberg' LIB_AUTHOR_EMAIL = '*****@*****.**' LIB_VERSION = '14.2.1' LIB_MIN_COMMON_VERSION = '2.0.0' LIB_SIG = '%s-%s' % (LIB_SHORT_NAME, LIB_VERSION) if VERSION > LIB_MIN_COMMON_VERSION: msg = ( 'Unsupported version of the core module is detected. Please download ' 'the latest version of client library at %s.' % LIB_URL) raise MissingPackageError(msg) # Tuple of tuples representing API versions, where each inner tuple is a # combination of the API vesrion and whether API used JAXB. API_VERSIONS_MAP = (('v13', False), ('v200909', True), ('v201003', True), ('v201008', True), ('v201101', True)) API_VERSIONS = [version for version, is_jaxb_api in API_VERSIONS_MAP] MIN_API_VERSION = API_VERSIONS[4] # Accepted combinations of headers which user has to provide. Either one of # these is required in order to make a succesful API request. REQUIRED_SOAP_HEADERS = (('email', 'password', 'useragent', 'developerToken'), ('email', 'password', 'userAgent', 'developerToken'), ('authToken', 'userAgent', 'developerToken'), ('userAgent', 'developerToken'))
def __GetBufferAsDict(self): """Parse HTTP headers and SOAP data. Returns: dict Request's HTTP headers and SOAP data. """ tags = (('Outgoing HTTP headers', 'dumpHeadersOut'), ('Outgoing SOAP', 'dumpSoapOut'), ('Incoming HTTP headers', 'dumpHeadersIn'), ('Incoming SOAP', 'dumpSoapIn')) xml_dumps = self.GetBufferAsStr().split('_' * 33) if len(xml_dumps) > 1: # The HTTP and SOAP messages were delivered via ZSI. if not PYXML_LIB: msg = 'PyXML v%s or newer is required.' % MIN_PYXML_VERSION raise MissingPackageError(msg) for xml_part in xml_dumps: xml_part = xml_part.lstrip('\n').rstrip('\n') if not xml_part: continue xml_part = '\n'.join(xml_part.split('\n')[1:]) in_parts = xml_part.split('\n\n', 1) if len(in_parts) == 1: from ZSI.version import Version xml_out = '<?xml version="1.0" encoding="UTF-8"?>\n%s' % xml_part if self.__pretty_xml: xml_out = self.__PrettyPrintXml(xml_out, 1) self.__dump['dumpHeadersOut'] = ( '%s Outgoing HTTP headers %s\n' 'User-Agent: ZSI %s (http://pywebsvcs.sf.net); %s\n' '%s' % ('*' * 3, '*' * 46, '.'.join(map( str, Version)), self.__xml_parser_sig, '*' * 72)) self.__dump['dumpSoapOut'] = ( '%s Outgoing SOAP %s\n%s\n%s' % ('*' * 3, '*' * 54, xml_out, '*' * 72)) elif len(in_parts) == 2: sub_parts = in_parts[0].split('-' * 7) xml_in = ('<?xml version="1.0" encoding="UTF-8"?>\n%s' % in_parts[1].lstrip('\n')) if self.__pretty_xml: xml_in = self.__PrettyPrintXml(xml_in, 1) self.__dump['dumpHeadersIn'] = ( '%s Incoming HTTP headers %s\n' '%s\n%s' % ('*' * 3, '*' * 46, (' '.join(sub_parts[0].split('\n')) + sub_parts[1]).replace('\r', ''), '*' * 72)) self.__dump['dumpSoapIn'] = ( '%s Incoming SOAP %s\n%s\n%s' % ('*' * 3, '*' * 54, xml_in, '*' * 72)) else: pass else: # The HTTP and SOAP messages were delivered via SOAPpy or httplib.HTTPS. xml_dumps = self.GetBufferAsStr().split('*' * 72) for xml_part in xml_dumps: xml_part = xml_part.lstrip('\n').rstrip('\n') for name, tag in tags: if xml_part.find(name) > -1: # Insert XML parser signature into the SOAP header. trigger = xml_part[xml_part.lower( ).find('content-type' ):xml_part.lower().find('content-type') + 12] if trigger and tag == 'dumpHeadersOut': xml_part = xml_part.replace( trigger, 'XML-parser: %s\n%s' % (self.__xml_parser_sig, trigger)) if self.__pretty_xml: doc = [] banner = '' for line in xml_part.split('\n'): if line.rfind('SOAP %s' % ('*' * 46)) > -1: banner = line continue doc.append(line) if banner: xml_part = '%s\n%s' % (banner, self.__PrettyPrintXml( '\n'.join(doc), 1)) self.__dump[tag] = (xml_part + '\n' + '*' * 72) break return self.__dump