Beispiel #1
0
    def __init__(self,
                 lib_sig,
                 headers,
                 config,
                 op_config,
                 url,
                 lock,
                 logger=None):
        """Inits WebService.

    Args:
      lib_sig: str Client library signature.
      headers: dict Dictionary object with populated authentication
               credentials.
      config: dict Dictionary object with populated configuration values.
      op_config: dict Dictionary object with additional configuration values
                 for this operation.
      url: str URL of the web service to call.
      lock: thread.lock Thread lock.
      logger: Logger Instance of Logger.
    """
        self._lib_sig = lib_sig
        self._headers = headers
        self._config = config
        self._op_config = op_config
        self._url = url
        self._lock = lock
        self._logger = logger
        self._start_time = 0
        self._stop_time = 0
        self._response = None

        if self._logger is None:
            self._logger = Logger(lib_sig, self._config['log_home'])
Beispiel #2
0
def main():
    logger = Logger(os.path.join(LOG_HOME))

    #获取新的token
    refresh_token = GenerateRefreshToken()

    # Load existing authentication credentials from dfa_api_auth.pkl.
    old_auth = {}
    if os.path.exists(AUTH_PKL):
        try:
            fh = open(AUTH_PKL, 'r')
            try:
                old_auth = pickle.load(fh)
            finally:
                fh.close()
        except IOError, e:
            logger.Log(LOG_NAME, e, log_level=Logger.ERROR)
Beispiel #3
0
# 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.
"""Script to run all existing unit tests."""

__author__ = '[email protected] (Stan Grinberg)'

import glob
import os
import sys
sys.path.append(os.path.join('..', '..', '..'))
import unittest

from adspygoogle.adwords import LIB_SIG
from adspygoogle.common.Logger import Logger

LOG_NAME = 'adwords_api_lib'
LOGGER = Logger(LIB_SIG, os.path.join('..', '..', '..', 'logs'))

suite = unittest.TestSuite()
tests = [test[:-3] for test in glob.glob('*_unittest.py')]
for test in tests:
    module = __import__(test)
    suite.addTest(unittest.TestLoader().loadTestsFromModule(module))

if __name__ == '__main__':
    LOGGER.Log(LOG_NAME, 'Start all unit tests.', log_level=Logger.DEBUG)
    unittest.TextTestRunner(verbosity=1).run(suite)
    LOGGER.Log(LOG_NAME, 'End all unit tests.', log_level=Logger.DEBUG)
  def __init__(self, headers=None, config=None, path=None):
    """Inits Client.

    Args:
      [optional]
      headers: dict Object with populated authentication credentials.
      config: dict Object with client configuration values.
      path: str Relative or absolute path to home directory (i.e. location of
            pickles and logs/).

    Example:
      headers = {
        'email': '*****@*****.**',
        'password': '******',
        'authToken': '...',
        'applicationName': 'GoogleTest',
        'networkCode': 'ca-01234567',
        'oauth2credentials': 'See use_oauth2.py'
      }
      config = {
        'home': '/path/to/home',
        'log_home': '/path/to/logs/home',
        'proxy': 'http://example.com:8080',
        'xml_parser': '1', # PYXML = 1, ELEMENTREE = 2
        'debug': 'n',
        'raw_debug': 'n',
        'xml_log': 'y',
        'request_log': 'y',
        'raw_response': 'n',
        'strict': 'y',
        'pretty_xml': 'y',
        'compress': 'y',
        'access': ''
      }
      path = '/path/to/home'
    """
    super(DfpClient, self).__init__(headers, config, path)

    self.__lock = thread.allocate_lock()
    self.__loc = None

    if path is not None:
      # Update absolute path for a given instance of DfpClient, based on
      # provided relative path.
      if os.path.isabs(path):
        DfpClient.home = path
      else:
        # NOTE(api.sgrinberg): Keep first parameter of join() as os.getcwd(),
        # do not change it to DfpClient.home. Otherwise, may break when
        # multiple instances of DfpClient exist during program run.
        DfpClient.home = os.path.join(os.getcwd(), path)

      # If pickles don't exist at given location, default to "~".
      if (not headers and not config and
          (not os.path.exists(os.path.join(DfpClient.home,
                                           DfpClient.auth_pkl_name)) or
           not os.path.exists(os.path.join(DfpClient.home,
                                           DfpClient.config_pkl_name)))):
        DfpClient.home = os.path.expanduser('~')
    elif not headers:
      DfpClient.home = os.path.expanduser('~')

    # Update location for both pickles.
    DfpClient.auth_pkl = os.path.join(DfpClient.home,
                                      DfpClient.auth_pkl_name)
    DfpClient.config_pkl = os.path.join(DfpClient.home,
                                        DfpClient.config_pkl_name)

    # Only load from the pickle if config wasn't specified.
    self._config = config or self.__LoadConfigValues()
    self._config = self.__SetMissingDefaultConfigValues(self._config)
    self._config['home'] = DfpClient.home

    # Validate XML parser to use.
    SanityCheck.ValidateConfigXmlParser(self._config['xml_parser'])

    # Only load from the pickle if 'headers' wasn't specified.
    if headers is None:
      self._headers = self.__LoadAuthCredentials()
    else:
      if Utils.BoolTypeConvert(self._config['strict']):
        SanityCheck.ValidateRequiredHeaders(headers, REQUIRED_SOAP_HEADERS)
      self._headers = headers

    # Load/set authentication token.
    try:
      if headers and 'authToken' in headers and headers['authToken']:
        self._headers['authToken'] = headers['authToken']
      elif 'email' in self._headers and 'password' in self._headers:
        self._headers['authToken'] = Utils.GetAuthToken(
            self._headers['email'], self._headers['password'],
            AUTH_TOKEN_SERVICE, LIB_SIG, self._config['proxy'])
      elif (self._headers.get('oauth2credentials')):
        # If they have oauth2credentials, that's also fine.
        pass
      else:
        msg = ('Authentication data, email or/and password, OAuth2 credentials '
               'is missing.')
        raise ValidationError(msg)
      self._config['auth_token_epoch'] = time.time()
    except AuthTokenError:
      # We would end up here if non-valid Google Account's credentials were
      # specified.
      self._headers['authToken'] = None
      self._config['auth_token_epoch'] = 0

    # Initialize logger.
    self.__logger = Logger(LIB_SIG, self._config['log_home'])
Beispiel #5
0
class WebService(object):
    """Implements WebService.

  Responsible for sending and recieving SOAP XML requests.
  """
    def __init__(self,
                 lib_sig,
                 headers,
                 config,
                 op_config,
                 url,
                 lock,
                 logger=None):
        """Inits WebService.

    Args:
      lib_sig: str Client library signature.
      headers: dict Dictionary object with populated authentication
               credentials.
      config: dict Dictionary object with populated configuration values.
      op_config: dict Dictionary object with additional configuration values
                 for this operation.
      url: str URL of the web service to call.
      lock: thread.lock Thread lock.
      logger: Logger Instance of Logger.
    """
        self._lib_sig = lib_sig
        self._headers = headers
        self._config = config
        self._op_config = op_config
        self._url = url
        self._lock = lock
        self._logger = logger
        self._start_time = 0
        self._stop_time = 0
        self._response = None

        if self._logger is None:
            self._logger = Logger(lib_sig, self._config['log_home'])

    def _ManageSoap(self,
                    buf,
                    log_handlers,
                    lib_url,
                    errors,
                    start_time,
                    stop_time,
                    error={}):
        """Manage SOAP XML message.

    Args:
      buf: SoapBuffer SOAP buffer.
      log_handlers: list Log handlers.
      lib_url: str URL of the project's home.
      errors: dict Map of errors available for the API.
      start_time: str Time before service call was invoked.
      stop_time: str Time after service call was invoked.
      [optional]
      error: dict Error, if any.
    """
        # Load trace errors, if any.
        if error and 'trace' in error:
            error_msg = error['trace']
        else:
            error_msg = ''

        # Check if response was successful or not.
        if error and 'data' in error:
            is_fault = True
        else:
            is_fault = False

        # Forward SOAP XML, errors, and other debugging data to console, external
        # file, both, or ignore. Each handler supports the following elements,
        #   tag: Config value for this handler. If left empty, will never write
        #        data to file.
        #   target: Target/destination represented by this handler (i.e. FILE,
        #           CONSOLE, etc.). Initially, it should be set to Logger.NONE.
        #   name: Name of the log file to use.
        #   data: Data to write.
        for handler in log_handlers:
            if handler['tag'] == 'xml_log':
                handler['target'] = Logger.NONE
                handler['data'] += str(
                    'StartTime: %s\n%s\n%s\n%s\n%s\nEndTime: %s' %
                    (start_time, buf.GetHeadersOut(), buf.GetSoapOut(),
                     buf.GetHeadersIn(), buf.GetSoapIn(), stop_time))
            elif handler['tag'] == 'request_log':
                handler['target'] = Logger.NONE
                handler['data'] += ' isFault=%s' % is_fault
            elif handler['tag'] == '':
                handler['target'] = Logger.NONE
                handler['data'] += 'DEBUG: %s' % error_msg
        for handler in log_handlers:
            if (handler['tag']
                    and Utils.BoolTypeConvert(self._config[handler['tag']])):
                handler['target'] = Logger.FILE
            # If debugging is On, raise handler's target two levels,
            #   NONE -> CONSOLE
            #   FILE -> FILE_AND_CONSOLE.
            if Utils.BoolTypeConvert(self._config['debug']):
                handler['target'] += 2

            if (handler['target'] != Logger.NONE and handler['data']
                    and handler['data'] != 'None'
                    and handler['data'] != 'DEBUG: '):
                self._logger.Log(handler['name'],
                                 handler['data'],
                                 log_level=Logger.DEBUG,
                                 log_handler=handler['target'])

        # If raw response is requested, no need to validate and throw appropriate
        # error. Up to the end user to handle successful or failed request.
        if Utils.BoolTypeConvert(self._config['raw_response']): return

        # Report SOAP fault.
        if is_fault:
            try:
                fault = buf.GetFaultAsDict()
                if not fault: msg = error['data']
            except:
                fault = None
                # An error is not a SOAP fault, but check if some other error.
                if error_msg:
                    msg = error_msg
                else:
                    msg = ('Unable to parse incoming SOAP XML. Please, file '
                           'a bug at %s/issues/list.' % lib_url)
            # Release thread lock.
            if self._lock.locked(): self._lock.release()
            if not fault and msg: return msg
            return fault
        return None

    def CallMethod(self,
                   headers,
                   config,
                   method_name,
                   params,
                   buf,
                   is_jaxb_api,
                   lib_sig,
                   lib_url,
                   service_name=None,
                   loc=None,
                   request=None):
        """Make an API call to specified method.

    Args:
      headers: dict Dictionary object with populated authentication
               credentials.
      config: dict Dictionary object with populated configuration values.
      method_name: str API method name.
      params: list List of parameters to send to the API method.
      buf: SoapBuffer SOAP buffer.
      is_jaxb_api: str Whether API uses JAXB.
      lib_sig: str Signature of the client library.
      lib_url: str URL of the project's home.
      [optional]
      service_name: str API service name.
      loc: Service locator.
      request: instance Holder of the SOAP request.

    Returns:
      tuple/str Response from the API method. If 'raw_response' flag enabled a
                string is returned, tuple otherwise.
    """
        # Temporarily redirect HTTP headers and SOAP from STDOUT into a buffer.
        if not Utils.BoolTypeConvert(self._config['raw_debug']):
            old_stdout = sys.stdout
            sys.stdout = buf

        response = ()
        error = {}
        try:
            # Fire off API request and handle the response.
            if config['soap_lib'] == SOAPPY:
                from adspygoogle.common.soappy import MessageHandler
                service = MessageHandler.GetServiceConnection(
                    headers, config, self._url, self._op_config['http_proxy'],
                    is_jaxb_api)

                if not is_jaxb_api:
                    response = MessageHandler.UnpackResponseAsDict(
                        service.invoke(method_name, params))
                else:
                    if not params: params = ('')
                    response = MessageHandler.UnpackResponseAsDict(
                        service._callWithBody(
                            MessageHandler.SetRequestParams(
                                config, method_name, params)))
            elif config['soap_lib'] == ZSI:
                from adspygoogle.common.zsi import MessageHandler
                service = MessageHandler.GetServiceConnection(
                    headers, config, self._op_config, self._url, service_name,
                    loc)
                request = MessageHandler.SetRequestParams(
                    request, params, is_jaxb_api)

                response = MessageHandler.UnpackResponseAsTuple(
                    eval('service.%s(request)' % method_name))

                # The response should always be tuple. If it's not, there must be
                # something wrong with MessageHandler.UnpackResponseAsTuple().
                if len(response) == 1 and isinstance(response[0], list):
                    response = tuple(response[0])

            if isinstance(response, list):
                response = tuple(response)
            elif isinstance(response, tuple):
                pass
            else:
                if response:
                    response = (response, )
                else:
                    response = ()
        except Exception, e:
            error['data'] = e

        # Restore STDOUT.
        if not Utils.BoolTypeConvert(self._config['raw_debug']):
            sys.stdout = old_stdout

        # When debugging mode is ON, fetch last traceback.
        if Utils.BoolTypeConvert(self._config['debug']):
            if Utils.LastStackTrace() and Utils.LastStackTrace() != 'None':
                error['trace'] = Utils.LastStackTrace()

        # Catch local errors prior to going down to the SOAP layer, which may not
        # exist for this error instance.
        if 'data' in error and not buf.IsHandshakeComplete():
            # Check if buffer contains non-XML data, most likely an HTML page. This
            # happens in the case of 502 errors (and similar). Otherwise, this is a
            # local error and API request was never made.
            html_error = Utils.GetErrorFromHtml(buf.GetBufferAsStr())
            if html_error:
                msg = '%s' % html_error
            else:
                msg = str(error['data'])
                if Utils.BoolTypeConvert(self._config['debug']):
                    msg += '\n%s' % error['trace']

            # When debugging mode is ON, store the raw content of the buffer.
            if Utils.BoolTypeConvert(self._config['debug']):
                error['raw_data'] = buf.GetBufferAsStr()

            # Catch errors from AuthToken and ValidationError levels, raised during
            # try/except above.
            if isinstance(error['data'], AuthTokenError):
                raise AuthTokenError(msg)
            elif isinstance(error['data'], ValidationError):
                raise ValidationError(error['data'])
            if 'raw_data' in error:
                msg = '%s [RAW DATA: %s]' % (msg, error['raw_data'])
            return Error(msg)

        if Utils.BoolTypeConvert(self._config['raw_response']):
            response = buf.GetRawSOAPIn()
        if error: response = error
        return response
Beispiel #6
0
import pickle


from adspygoogle.common import SanityCheck
from adspygoogle.common.Errors import InvalidInputError
from adspygoogle.common.Logger import Logger


HOME = os.path.expanduser('~')
AUTH_PKL = os.path.join(HOME, 'dfa_api_auth.pkl')
CONFIG_PKL = os.path.join(HOME, 'dfa_api_config.pkl')
LOG_HOME = os.path.join(HOME, 'logs')
LOG_NAME = 'dfa_api_lib'


logger = Logger(os.path.join(LOG_HOME))

# Load existing authentication credentials from dfa_api_auth.pkl.
old_auth = {}
if os.path.exists(AUTH_PKL):
  try:
    fh = open(AUTH_PKL, 'r')
    try:
      old_auth = pickle.load(fh)
    finally:
      fh.close()
  except IOError, e:
    logger.Log(LOG_NAME, e, log_level=Logger.ERROR)

# Prompt user for authentication and configuration values.
print """
    def __init__(self, headers=None, config=None, path=None):
        """Inits DfaClient.

    Args:
      [optional]
      headers: dict Object with populated authentication credentials.
      config: dict Object with client configuration values.
      path: str Relative or absolute path to home directory (i.e. location of
            pickles and logs/).

    Example:
      headers = {
        'Username': '******',
        'Password': '******',
        'AuthToken': '...'
      }
      config = {
        'home': '/path/to/home',
        'log_home': '/path/to/logs/home',
        'xml_parser': '1', # PYXML = 1, ELEMENTREE = 2
        'debug': 'n',
        'raw_debug': 'n',
        'xml_log': 'y',
        'request_log': 'y',
        'raw_response': 'n',
        'strict': 'y',
        'pretty_xml': 'y',
        'compress': 'y',
      }
      path = '/path/to/home'
    """
        super(DfaClient, self).__init__(headers, config, path)

        self.__lock = threading.RLock()
        self.__loc = None

        if path is not None:
            # Update absolute path for a given instance of DfaClient, based on
            # provided relative path.
            if os.path.isabs(path):
                DfaClient.home = path
            else:
                # NOTE(api.sgrinberg): Keep first parameter of join() as os.getcwd(),
                # do not change it to DfaClient.home. Otherwise, may break when
                # multiple instances of DfaClient exist during program run.
                DfaClient.home = os.path.join(os.getcwd(), path)

            # If pickles don't exist at given location, default to "~".
            if (not headers and not config
                    and (not os.path.exists(
                        os.path.join(DfaClient.home, DfaClient.auth_pkl_name))
                         or not os.path.exists(
                             os.path.join(DfaClient.home,
                                          DfaClient.config_pkl_name)))):
                DfaClient.home = os.path.expanduser('~')
        elif not headers:
            DfaClient.home = os.path.expanduser('~')

        # Update location for both pickles.
        DfaClient.auth_pkl = os.path.join(DfaClient.home,
                                          DfaClient.auth_pkl_name)
        DfaClient.config_pkl = os.path.join(DfaClient.home,
                                            DfaClient.config_pkl_name)

        # Only load from the pickle if config wasn't specified.
        self._config = config or self.__LoadConfigValues()
        self._config = self.__SetMissingDefaultConfigValues(self._config)
        self._config['home'] = DfaClient.home

        # Validate XML parser to use.
        SanityCheck.ValidateConfigXmlParser(self._config['xml_parser'])

        # Only load from the pickle if 'headers' wasn't specified.
        if headers is None:
            self._headers = self.__LoadAuthCredentials()
        else:
            # Pass app_name from config as appName to headers if still present
            if self._config.get('app_name', None):
                headers['appName'] = self._config['app_name']

            if Utils.BoolTypeConvert(self._config['strict']):
                SanityCheck.ValidateRequiredHeaders(headers,
                                                    REQUIRED_SOAP_HEADERS)
            self._headers = headers

        # Initialize logger.
        self.__logger = Logger(LIB_SIG, self._config['log_home'])