Esempio n. 1
0
def run_once(options, args):
  """Run one command.

  Keyword arguments:
    options: Options instance as built and returned by optparse.
    args: Arguments to GoogleCL, also as returned by optparse.

  """
  global discovery

  # If we haven't gotten the list of discovery APIs yet, and they're asking for
  # a discovery API, figure out their email address and then get a list of
  # APIs.
  if apis and not discovery:
    if (args[0] not in AVAILABLE_SERVICES) or \
       (args[0] == 'help' and len(args) == 1) or \
       (args[0] == 'help' and len(args)>1 and \
        args[1] not in AVAILABLE_SERVICES):
      # Is there a better approach than using the calendar API to get the email
      # address?
      service_class, tasks, section_header, config = import_service('calendar',
                                                                    None)
      email = config.lazy_get(section_header, 'user')
      discovery = DiscoveryManager(email)
      global AVAILABLE_APIS
      AVAILABLE_APIS = discovery.apis_list()

  init_args = args[:]
  try:
    service = args.pop(0)
    task_name = args.pop(0)
  except IndexError:
    if service == 'help':
      print_help()
    else:
      LOG.error('Must specify at least a service and a task!')
    return

  if apis and service == 'refresh' and task_name == 'apis':
    discovery.docManager.load(force=True)
    AVAILABLE_APIS = discovery.apis_list()
    return

  if apis and service == 'edit' and task_name == 'config':
    import subprocess
    subprocess.call((discovery.dataManager.editor,
                   googlecl.config.get_config_path()))
    return

  if service == 'help' and task_name == 'more':
    print_more_help()
    return

  # Detects if GData is not provided a version number or the path is too long
  conflict = (task_name[0] == 'v' and task_name[1].isdigit()) or (service == 'help' and args)
  # Prioritizes using existing GData APIs over Discovery.
  # May have to change if/when those are brought over to Discovery...
  if service == 'help':
    if task_name in AVAILABLE_SERVICES and not conflict:
      service_class, tasks, section_header, config = import_service(task_name,
                                                                options.config)
      if tasks:
        print_help(task_name, tasks)
        return
    else:
      if apis and task_name in AVAILABLE_APIS:
        discovery.run(init_args)
      elif not apis:
        LOG.error('Did not recognize service.')
        LOG.error('If you wanted a Discovery service, make sure you have')
        LOG.error('google-api-python-client installed.')
      else:
        LOG.error('Did not recognize service.')
      return
  elif service in AVAILABLE_SERVICES and not conflict:
      service_class, tasks, section_header, config = import_service(service,
                                                                options.config)
  else:
    if apis and service in AVAILABLE_APIS:
      discovery.run(init_args)
    elif not apis:
      LOG.error('Did not recognize service.')
      LOG.error('If you wanted a Discovery service, make sure you have')
      LOG.error('google-api-python-client installed.')
    else:
      LOG.error('Did not recognize service.')
    return
  if not service_class:
    return
  client = service_class(config)
  # Activate debugging output from HTTP requests. "service" clients only!
  # "client" versions need to set self.http_client.debug in their own __init__
  client.debug = config.lazy_get(section_header,
                                 'debug',
                                 default=options.debug,
                                 option_type=bool)
  # XXX: Not the best place for this.
  if hasattr(client, 'http_client'):
    client.http_client.debug = client.debug
  try:
    task = tasks[task_name]
    task.name = task_name
  except KeyError:
    LOG.error('Did not recognize task, please use one of ' + \
              str(tasks.keys()))
    return

  if 'devkey' in task.required:
    # If a devkey is required, and there is none specified via an option
    # BEFORE fill_out_options, insert the key from file or the key given
    # to GoogleCL.
    # You can get your own key at http://code.google.com/apis/youtube/dashboard
    if not options.devkey:
      options.devkey = googlecl.read_devkey() or 'AI39si4d9dBo0dX7TnGyfQ68bNiKfEeO7wORCfY3HAgSStFboTgTgAi9nQwJMfMSizdGIs35W9wVGkygEw8ei3_fWGIiGSiqnQ'

  # fill_out_options will read the key from file if necessary, but will not set
  # it since it will always get a non-empty value beforehand.
  fill_out_options(args, section_header, task, options, config)
  client.email = options.user

  if options.blog:
    config.set_missing_default(section_header, 'blog', options.blog)
  if options.devkey:
    client.developer_key = options.devkey
    # This may save an invalid dev key -- it's up to the user to specify a
    # valid dev key eventually.
    # TODO: It would be nice to make this more efficient.
    googlecl.write_devkey(options.devkey)

  # Unicode-ize options and args
  for attr_name in dir(options):
    attr = getattr(options, attr_name)
    if not attr_name.startswith('_') and isinstance(attr, str):
      setattr(options, attr_name, safe_decode(attr, googlecl.TERMINAL_ENCODING))
  if args:
    args = [safe_decode(string, googlecl.TERMINAL_ENCODING) for string in args]

  # Expand options.src. The goal is to expand things like
  # --src=~/Photos/album1/* (which does not normally happen)
  # XXX: This ought to be in fill_out_options(), along with unicode-ize above.
  if options.src:
    expanded_args = glob.glob(options.src)
    if expanded_args:
      options.src = expanded_args
    else:
      options.src = [options.src]
  else:
    options.src = []

  # Take a gander at the options filled in.
  if LOG.getEffectiveLevel() == logging.DEBUG:
    import inspect
    for attr_name in dir(options):
      if not attr_name.startswith('_'):
        attr = getattr(options, attr_name)
        if attr is not None and not inspect.ismethod(attr):
          LOG.debug(safe_encode('Option ' + attr_name + ': ' + unicode(attr)))
  LOG.debug(safe_encode('args: ' + unicode(args)))

  auth_manager = googlecl.authentication.AuthenticationManager(service, client)
  authenticated = authenticate(auth_manager, options, config, section_header)

  if not authenticated:
    LOG.debug('Authentication failed, exiting run_once')
    return -1

  # If we've authenticated, save the config values we've been setting.
  # And remember the email address that worked!
  config.set_missing_default(section_header, 'user', client.email)
  config.write_out_parser()
  run_error = None
  try:
    task.run(client, options, args)
  except AttributeError, run_error:
    err_str = safe_decode(run_error)
    if err_str.startswith("'OAuth"):
      LOG.info('OAuth error.  Try re-running with --force-auth.')
    else:
      raise run_error
Esempio n. 2
0
def run_once(options, args):
    """Run one command.

    Keyword arguments:
      options: Options instance as built and returned by optparse.
      args: Arguments to GoogleCL, also as returned by optparse.

    """
    global discovery

    # If we haven't gotten the list of discovery APIs yet, and they're asking for
    # a discovery API, figure out their email address and then get a list of
    # APIs.
    if apis and not discovery:
        if (args[0] not in AVAILABLE_SERVICES) or \
           (args[0] == 'help' and len(args) == 1) or \
           (args[0] == 'help' and len(args) > 1 and
                args[1] not in AVAILABLE_SERVICES):
            # Is there a better approach than using the calendar API to get the email
            # address?
            service_class, tasks, section_header, config = import_service('calendar',
                                                                          None)
            email = config.lazy_get(section_header, 'user')
            discovery = DiscoveryManager(email)
            global AVAILABLE_APIS
            AVAILABLE_APIS = discovery.apis_list()

    init_args = args[:]
    try:
        service = args.pop(0)
        task_name = args.pop(0)
    except IndexError:
        if service == 'help':
            print_help()
        else:
            LOG.error('Must specify at least a service and a task!')
        return

    if apis and service == 'refresh' and task_name == 'apis':
        discovery.docManager.load(force=True)
        AVAILABLE_APIS = discovery.apis_list()
        return

    if apis and service == 'edit' and task_name == 'config':
        import subprocess
        subprocess.call((discovery.dataManager.editor,
                         googlecl.config.get_config_path()))
        return

    if service == 'help' and task_name == 'more':
        print_more_help()
        return

    # Detects if GData is not provided a version number or the path is too long
    conflict = (task_name[0] == 'v' and task_name[
                1].isdigit()) or (service == 'help' and args)
    # Prioritizes using existing GData APIs over Discovery.
    # May have to change if/when those are brought over to Discovery...
    if service == 'help':
        if task_name in AVAILABLE_SERVICES and not conflict:
            service_class, tasks, section_header, config = import_service(task_name,
                                                                          options.config)
            if tasks:
                print_help(task_name, tasks)
                return
        else:
            if apis and task_name in AVAILABLE_APIS:
                discovery.run(init_args)
            elif not apis:
                LOG.error('Did not recognize service.')
                LOG.error(
                    'If you wanted a Discovery service, make sure you have')
                LOG.error('google-api-python-client installed.')
            else:
                LOG.error('Did not recognize service.')
            return
    elif service in AVAILABLE_SERVICES and not conflict:
        service_class, tasks, section_header, config = import_service(service,
                                                                      options.config)
    else:
        if apis and service in AVAILABLE_APIS:
            discovery.run(init_args)
        elif not apis:
            LOG.error('Did not recognize service.')
            LOG.error('If you wanted a Discovery service, make sure you have')
            LOG.error('google-api-python-client installed.')
        else:
            LOG.error('Did not recognize service.')
        return
    if not service_class:
        return
    client = service_class(config)
    # Activate debugging output from HTTP requests. "service" clients only!
    # "client" versions need to set self.http_client.debug in their own __init__
    client.debug = config.lazy_get(section_header,
                                   'debug',
                                   default=options.debug,
                                   option_type=bool)
    # XXX: Not the best place for this.
    if hasattr(client, 'http_client'):
        client.http_client.debug = client.debug
    try:
        task = tasks[task_name]
        task.name = task_name
    except KeyError:
        LOG.error('Did not recognize task, please use one of ' +
                  str(tasks.keys()))
        return

    if 'devkey' in task.required:
        # If a devkey is required, and there is none specified via an option
        # BEFORE fill_out_options, insert the key from file or the key given
        # to GoogleCL.
        # You can get your own key at
        # http://code.google.com/apis/youtube/dashboard
        if not options.devkey:
            options.devkey = googlecl.read_devkey(
            ) or 'AI39si4d9dBo0dX7TnGyfQ68bNiKfEeO7wORCfY3HAgSStFboTgTgAi9nQwJMfMSizdGIs35W9wVGkygEw8ei3_fWGIiGSiqnQ'

    # fill_out_options will read the key from file if necessary, but will not set
    # it since it will always get a non-empty value beforehand.
    fill_out_options(args, section_header, task, options, config)
    client.email = options.user

    if options.blog:
        config.set_missing_default(section_header, 'blog', options.blog)
    if options.devkey:
        client.developer_key = options.devkey
        # This may save an invalid dev key -- it's up to the user to specify a
        # valid dev key eventually.
        # TODO: It would be nice to make this more efficient.
        googlecl.write_devkey(options.devkey)

    # Unicode-ize options and args
    for attr_name in dir(options):
        attr = getattr(options, attr_name)
        if not attr_name.startswith('_') and isinstance(attr, str):
            setattr(options, attr_name, safe_decode(
                attr, googlecl.TERMINAL_ENCODING))
    if args:
        args = [safe_decode(string, googlecl.TERMINAL_ENCODING)
                for string in args]

    # Expand options.src. The goal is to expand things like
    # --src=~/Photos/album1/* (which does not normally happen)
    # XXX: This ought to be in fill_out_options(), along with unicode-ize
    # above.
    if options.src:
        expanded_args = glob.glob(options.src)
        if expanded_args:
            options.src = expanded_args
        else:
            options.src = [options.src]
    else:
        options.src = []

    # Take a gander at the options filled in.
    if LOG.getEffectiveLevel() == logging.DEBUG:
        import inspect
        for attr_name in dir(options):
            if not attr_name.startswith('_'):
                attr = getattr(options, attr_name)
                if attr is not None and not inspect.ismethod(attr):
                    LOG.debug(safe_encode(
                        'Option ' + attr_name + ': ' + unicode(attr)))
    LOG.debug(safe_encode('args: ' + unicode(args)))

    auth_manager = googlecl.authentication.AuthenticationManager(
        service, client)
    authenticated = authenticate(auth_manager, options, config, section_header)

    if not authenticated:
        LOG.debug('Authentication failed, exiting run_once')
        return -1

    # If we've authenticated, save the config values we've been setting.
    # And remember the email address that worked!
    config.set_missing_default(section_header, 'user', client.email)
    config.write_out_parser()
    run_error = None
    try:
        task.run(client, options, args)
    except AttributeError, run_error:
        err_str = safe_decode(run_error)
        if err_str.startswith("'OAuth"):
            LOG.info('OAuth error.  Try re-running with --force-auth.')
        else:
            raise run_error
Esempio n. 3
0
            browser = webbrowser.get(browser_str)
          except webbrowser.Error, err:
            LOG.warn(safe_encode(u'Could not get browser "%s": %s' %
                                 (browser_str, err)))
            browser = None
      else:
        try:
          browser = webbrowser.get()
        except webbrowser.Error, err:
          LOG.warn(safe_encode(u'Could not get default browser: %s' % err))
          browser = None

      valid_token = auth_manager.retrieve_access_token(display_name, browser)
    if valid_token:
      LOG.debug('Retrieved valid access token')
      config.set_missing_default(section_header, 'skip_auth', True)
      return True
    else:
      LOG.debug('Could not retrieve valid access token')
      return False
  else:
    # Already set an access token and we're not being forced to authenticate
    return True


# I don't know if this and shlex.split() can replace expand_as_command_line
# because of the behavior of globbing characters that are in ""
def expand_args(args, on_linesep, on_glob, on_homepath):
  """Expands arguments list.

  Args:
Esempio n. 4
0
                        LOG.warn(safe_encode(u'Could not get browser "%s": %s' %
                                             (browser_str, err)))
                        browser = None
            else:
                try:
                    browser = webbrowser.get()
                except webbrowser.Error, err:
                    LOG.warn(safe_encode(
                        u'Could not get default browser: %s' % err))
                    browser = None

            valid_token = auth_manager.retrieve_access_token(
                display_name, browser)
        if valid_token:
            LOG.debug('Retrieved valid access token')
            config.set_missing_default(section_header, 'skip_auth', True)
            return True
        else:
            LOG.debug('Could not retrieve valid access token')
            return False
    else:
        # Already set an access token and we're not being forced to
        # authenticate
        return True


# I don't know if this and shlex.split() can replace expand_as_command_line
# because of the behavior of globbing characters that are in ""
def expand_args(args, on_linesep, on_glob, on_homepath):
    """Expands arguments list.