mvantellingen / python-zeep

A Python SOAP client
http://docs.python-zeep.org
Other
1.9k stars 586 forks source link

UnresolvedType class missing is_global attribute definition #1053

Open lemasson-h opened 4 years ago

lemasson-h commented 4 years ago

Hello,

I have encountered the following issue:

--- Logging error ---
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/logging/__init__.py", line 994, in emit
    msg = self.format(record)
  File "/usr/local/lib/python3.6/logging/__init__.py", line 840, in format
    return fmt.format(record)
  File "get_ga_accounts.py", line 15, in format
    str(current_arg) for current_arg in record.args
  File "get_ga_accounts.py", line 15, in <genexpr>
    str(current_arg) for current_arg in record.args
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/types/complex.py", line 73, in __str__
    return "%s(%s)" % (self.__class__.__name__, self.signature())
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/types/complex.py", line 475, in signature
    part = element.signature(schema, standalone=False)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/elements/indicators.py", line 255, in signature
    value = element.signature(schema, standalone=False)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/elements/element.py", line 309, in signature
    if self.type.is_global or (not standalone and self.is_global):
AttributeError: 'UnresolvedType' object has no attribute 'is_global'
Call stack:
  File "get_ga_accounts.py", line 73, in <module>
    main(adwords_client)
  File "get_ga_accounts.py", line 33, in main
    'ManagedCustomerService', version='v201809')
  File "/usr/local/lib/python3.6/site-packages/googleads/adwords.py", line 315, in GetService
    cache=self.cache)
  File "/usr/local/lib/python3.6/site-packages/googleads/common.py", line 774, in __init__
    endpoint, transport=transport, plugins=plugins)
  File "/usr/local/lib/python3.6/site-packages/zeep/client.py", line 68, in __init__
    self.wsdl = Document(wsdl, self.transport, settings=self.settings)
  File "/usr/local/lib/python3.6/site-packages/zeep/wsdl/wsdl.py", line 82, in __init__
    root_definitions = Definition(self, document, self.location)
  File "/usr/local/lib/python3.6/site-packages/zeep/wsdl/wsdl.py", line 184, in __init__
    self.parse_types(doc)
  File "/usr/local/lib/python3.6/site-packages/zeep/wsdl/wsdl.py", line 316, in parse_types
    self.types.add_documents(schema_nodes, self.location)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/schema.py", line 113, in add_documents
    document = self.create_new_document(node, location)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/schema.py", line 213, in create_new_document
    schema.load(self, node)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/schema.py", line 440, in load
    visitor.visit_schema(node)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/visitor.py", line 160, in visit_schema
    self.process(child, parent=node)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/visitor.py", line 88, in process
    result = visit_func(self, node, parent)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/visitor.py", line 635, in visit_complex_type
    self.register_type(qname, xsd_type)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/visitor.py", line 73, in register_type
    self.document.register_type(qname, instance)
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/schema.py", line 499, in register_type
    self._add_component(qname, value, self._types, "type")
  File "/usr/local/lib/python3.6/site-packages/zeep/xsd/schema.py", line 580, in _add_component
    logger.debug("register_%s(%r, %r)", item_name, name, value)
Message: 'register_%s(%r, %r)'
Arguments: ('type', '{https://adwords.google.com/api/adwords/mcm/v201809}AccountLabel', <zeep.xsd.dynamic_types.AccountLabel object at 0x7fb17908fb70>)

Basically the problem seems to come from 2 things:

The combination of those two, means that this line: logger.debug("register_%s(%r, %r)", item_name, name, value) in zeep/xsd/schema.py, line 580 is calling a logger, which when forcing the arguments to be stringified, is calling the element signature, where it is expecting the type attribute to have the attribute is_global. While if we don't pass through str, but through repr (default behaviour with the default formatter from python), it is fine as it doesn't try to access the is_global attribute on the type.

I have tried by updating UnresolvedType init to call the parent and it resolved the problem.

Would it be possible to find a solution to resolve it, please?

By the way, I am not controlling the logging formatter, I am using a framework called airflow, which has its own logger formatter which is responsible for forcing the arguments to be transformed into string instances.

  1. Versions python 3.6 zeep==3.4.0 googleads==22.0.*

  2. The wsdl https://adwords.google.com/api/adwords/mcm/v201809/ManagedCustomerService?wsdl

  3. Script A simple version, could be something like that:

    
    #!/usr/bin/env python
    #
    # Copyright 2016 Google Inc. All Rights Reserved.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.

"""This example gets the account hierarchy under the current account. The LoadFromStorage method is pulling credentials and properties from a "googleads.yaml" file. By default, it looks for this file in your home directory. For more information, see the "Caching authentication information" section of our README. """ import logging from googleads import adwords

PAGE_SIZE = 500

class FormatterForcingStrMagicMethodInsteadOfReprMagicMethod(logging.Formatter): """ Define a formatter that forces the arguments to be stringify instead of letting the repr be used by the logger by default. """ def format(self, record): if isinstance(record.args, (tuple, list)): record.args = tuple( str(current_arg) for current_arg in record.args )

    return super().format(record)

logging.getLogger('zeep.xsd.schema').setLevel(logging.DEBUG) handler = logging.StreamHandler() formatter = FormatterForcingStrMagicMethodInsteadOfReprMagicMethod( '[%(asctime)s] %(levelname)s - %(name)s: %(message)s' ) handler.setFormatter(formatter) logging.getLogger('zeep.xsd.schema').addHandler(handler)

def main(client):

Initialize appropriate service.

managed_customer_service = client.GetService(
    'ManagedCustomerService', version='v201809')

# Construct selector to get all accounts.
offset = 0
selector = {
    'fields': ['CustomerId', 'Name'],
    'paging': {
        'startIndex': str(offset),
        'numberResults': str(PAGE_SIZE)
    }
}
more_pages = True
accounts = list()

while more_pages:
    # Get serviced account graph.
    page = managed_customer_service.get(selector)
    if 'entries' in page and page['entries']:
        # Map from customerID to account.
        for account in page['entries']:
            accounts.append(account)
    offset += PAGE_SIZE
    selector['paging']['startIndex'] = str(offset)
    more_pages = offset < int(page['totalNumEntries'])

print("Accounts", accounts[0])

if name == 'main':

Initialize client object.

data = """

adwords: #############################################################################

Required Fields

############################################################################# developer_token: INSERT_DEVELOPER_TOKEN_HERE #############################################################################

Optional Fields

#############################################################################

client_customer_id: INSERT_CLIENT_CUSTOMER_ID_HERE

user_agent: INSERT_USER_AGENT_HERE

partial_failure: True

validate_only: True

#############################################################################

OAuth2 Configuration

Below you may provide credentials for either the installed application or

service account flows. Remove or comment the lines for the flow you're

not using.

#############################################################################

The following values configure the client for the installed application

flow.

client_id: INSERT_OAUTH_2_CLIENT_ID_HERE client_secret: INSERT_CLIENT_SECRET_HERE refresh_token: INSERT_REFRESH_TOKEN_HERE """ adwords_client = adwords.AdWordsClient.LoadFromString(data) main(adwords_client)



As you will see this depends on the python library from google: https://github.com/googleads/googleads-python-lib and will require to have an account to actually get the credentials to run the script.
alexxxnf commented 3 years ago

@lemasson-h Did you find a solution to your problem?

I’m facing same behavior with logging. However my issue has nothing to do with googleads.