Exemplo n.º 1
0
def _parse_project(_project, require_project=False):
  """Parse `--project` argument into `(name, project)`.

  :param _project: `--project` argument.
  :param require_project: Fail if we fail to load the project.

  Note that `name` is guaranteed to be non-`None` (this function will throw an
  exception otherwise) but `project` can be.

  The rules are as follows:

  + If at least one `':'` is found in `_project` then the rightmost one is
    interpreted as delimitor between the path to the module and the project
    name.

  + Else:

    + We first try to interpret `_project` as a module path and find a unique
      project inside.

    + If the above attempt raises an `ImportError`, we interpret it as a name.

  """
  default_project = Config().get_option('azkaban', 'default.project', 'jobs')
  exceptions = {}
  projects = {}

  def try_load(path):
    try:
      projects.update(Project.load(path))
      return True
    except Exception:
      exceptions[path] = format_exc()
      return False

  _project = _project or default_project
  if ':' in _project:
    # unambiguous case
    path, name = _project.rsplit(':', 1)
    if ':' in default_project:
      try_load(Project.load(path))
    else:
      # adding the default here lets options like `-p :name` work as intended
      try_load(path or default_project)
  else:
    # the option could be a name or module
    if not try_load(_project): # try first as a module
      # if that fails, try as a name
      name = _project
      if not ':' in default_project:
        path = default_project
      else:
        path = default_project.rsplit(':', 1)[0]
        # if the default project could be a mdule, try loading it
      try_load(path)
    else:
      name = None
      path = _project

  if exceptions:
    footer = '\nErrors occurred while loading the following modules:\n'
    for t in exceptions.items():
      footer += '\n> %r\n\n%s' % t
  else:
    footer = ''

  if name:
    if name in projects:
      return name, projects[name]
    elif projects:
      # harder consistency requirement
      raise AzkabanError(
        'Project %r not found. Available projects: %s\n'
        'You can also specify another location using the `--project` option.'
        '%s'
        % (name, ', '.join(projects), footer)
      )
    elif require_project:
      raise AzkabanError(
        'This command requires a project configuration module.\n'
        'You can specify another location using the `--project` option.'
        '%s'
        % (footer, )
      )
    else:
      return name, None
  else:
    if not projects:
      raise AzkabanError(
        'No registered project found in %r.\n'
        'You can specify another location using the `--project` option.'
        '%s'
        % (path, footer)
      )
    elif len(projects) > 1:
      raise AzkabanError(
        'Multiple registered projects found: %s\n'
        'You can use the `--project` option to disambiguate.'
        '%s'
        % (', '.join(projects), footer)
      )
    else:
      return projects.popitem()
Exemplo n.º 2
0
def _parse_project(_project, require_project=False):
  """Parse `--project` argument into `(name, project)`.

  :param _project: `--project` argument.
  :param require_project: Fail if we fail to load the project.

  Note that `name` is guaranteed to be non-`None` (this function will throw an
  exception otherwise) but `project` can be.

  The rules are as follows:

  + If at least one `':'` is found in `_project` then the rightmost one is
    interpreted as delimitor between the path to the module and the project
    name.

  + Else:

    + We first try to interpret `_project` as a module path and find a unique
      project inside.

    + If the above attempt raises an `ImportError`, we interpret it as a name.

  """
  default_project = Config().get_option('azkaban', 'default.project', 'jobs')
  exceptions = {}
  projects = {}

  def try_load(path):
    try:
      projects.update(Project.load(path))
      return True
    except Exception:
      exceptions[path] = format_exc()
      return False

  _project = _project or default_project
  if ':' in _project:
    # unambiguous case
    path, name = _project.rsplit(':', 1)
    if ':' in default_project:
      try_load(Project.load(path))
    else:
      # adding the default here lets options like `-p :name` work as intended
      try_load(path or default_project)
  else:
    # the option could be a name or module
    if not try_load(_project): # try first as a module
      # if that fails, try as a name
      name = _project
      if not ':' in default_project:
        path = default_project
      else:
        path = default_project.rsplit(':', 1)[0]
        # if the default project could be a mdule, try loading it
      try_load(path)
    else:
      name = None
      path = _project

  if exceptions:
    footer = '\nErrors occurred while loading the following modules:\n'
    for t in exceptions.items():
      footer += '\n> %r\n\n%s' % t
  else:
    footer = ''

  if name:
    if name in projects:
      return name, projects[name]
    elif projects:
      # harder consistency requirement
      raise AzkabanError(
        'Project %r not found. Available projects: %s\n'
        'You can also specify another location using the `--project` option.'
        '%s'
        % (name, ', '.join(projects), footer)
      )
    elif require_project:
      raise AzkabanError(
        'This command requires a project configuration module.\n'
        'You can specify another location using the `--project` option.'
        '%s'
        % (footer, )
      )
    else:
      return name, None
  else:
    if not projects:
      raise AzkabanError(
        'No registered project found in %r.\n'
        'You can specify another location using the `--project` option.'
        '%s'
        % (path, footer)
      )
    elif len(projects) > 1:
      raise AzkabanError(
        'Multiple registered projects found: %s\n'
        'You can use the `--project` option to disambiguate.'
        '%s'
        % (', '.join(projects), footer)
      )
    else:
      return projects.popitem()