Class: Dependabot::Python::PoetryErrorHandler

Inherits:
UpdateChecker
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/python/update_checker/poetry_version_resolver.rb

Constant Summary collapse

INVALID_CONFIGURATION =

if a valid config value is not found in project.toml file

/The Poetry configuration is invalid:(?<config>.*)/
INVALID_VERSION =

if .toml has incorrect version specification i.e. <0.2.0app

/Could not parse version constraint: (?<ver>.*)/
/No valid distribution links found for package: "(?<dep>.*)" version: "(?<ver>.*)"/
PYTHON_RANGE_NOT_SATISFIED =

Python version range mentioned in .toml [tool.poetry.dependencies] python = “x.x” is not satisfied by dependency

/(?<dep>.*) requires Python (?<req_ver>.*), so it will not be satisfied for Python (?<men_ver>.*)/
PACKAGE_NOT_FOUND =

package version mentioned in .toml not found in package index

/Package (?<pkg>.*) ((?<req_ver>.*)) not found./
INCOMPATIBLE_ENRICH_CONSTRAINTS =
/
  Cannot\senrich\sdependency\swith\sincompatible\sconstraints:\s+
  (?<dep>[^\s(]+)\s*\((?<ver_range_a>[^)]+)\)\s+and\s+
  (?<dep_b>[^\s(]+)\s*\((?<ver_range_b>[^)]+)\)
/x
CLIENT_ERROR_CODES =

client access error codes while accessing package index

T.let(
  {
    error401: /401 Client Error/,
    error403: /403 Client Error/,
    error404: /404 Client Error/,
    http403: /HTTP error 403/,
    http404: /HTTP error 404/
  }.freeze,
  T::Hash[T.nilable(String), Regexp]
)
SERVER_ERROR_CODES =

server response error codes while accessing package index

T.let(
  {
    server500: /500 Server Error/,
    server502: /502 Server Error/,
    server503: /503 Server Error/,
    server504: /504 Server Error/
  }.freeze,
  T::Hash[T.nilable(String), Regexp]
)
POETRY_VIRTUAL_ENV_CONFIG =

invalid configuration in pyproject.toml

%r{pypoetry/virtualenvs(.|\n)*list index out of range}
ERR_LOCAL_PROJECT_PATH =

error related to local project as dependency in pyproject.toml

/Path (?<path>.*) for (?<dep>.*) does not exist/
TIME_OUT_ERRORS =
T.let(
  {
    time_out_max_retries: /Max retries exceeded/,
    time_out_read_timed_out: /Read timed out/,
    time_out_inactivity: /Timed out due to inactivity/
  }.freeze,
  T::Hash[T.nilable(String), Regexp]
)
PACKAGE_RESOLVER_ERRORS =
T.let(
  {
    package_info_error: /Unable to determine package info/,
    self_dep_error: /Package '(?<path>.*)' is listed as a dependency of itself./,
    incompatible_constraints: /Incompatible constraints in requirements/
  }.freeze,
  T::Hash[T.nilable(String), Regexp]
)

Constants inherited from UpdateChecker

UpdateChecker::MAIN_PYPI_INDEXES, UpdateChecker::VERSION_REGEX

Instance Method Summary collapse

Methods inherited from UpdateChecker

#latest_resolvable_version, #latest_resolvable_version_with_no_unlock, #latest_version, #lowest_resolvable_security_fix_version, #lowest_security_fix_version, #requirements_unlocked_or_can_be?, #requirements_update_strategy, #updated_requirements

Constructor Details

#initialize(dependencies:, dependency_files:) ⇒ PoetryErrorHandler

Returns a new instance of PoetryErrorHandler.



477
478
479
480
# File 'lib/dependabot/python/update_checker/poetry_version_resolver.rb', line 477

def initialize(dependencies:, dependency_files:)
  @dependencies = T.let(dependencies, Dependabot::Dependency)
  @dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
end

Instance Method Details

#handle_poetry_error(error) ⇒ Object

Raises:

  • (DependencyFileNotResolvable)


505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
# File 'lib/dependabot/python/update_checker/poetry_version_resolver.rb', line 505

def handle_poetry_error(error)
  Dependabot.logger.warn(error.message)

  if (msg = error.message.match(PoetryVersionResolver::INCOMPATIBLE_CONSTRAINTS) ||
      error.message.match(INVALID_CONFIGURATION) || error.message.match(INVALID_VERSION) ||
      error.message.match(INVALID_LINK))
    raise DependencyFileNotResolvable, msg
  end

  if (msg = error.message.match(PACKAGE_NOT_FOUND))
    raise DependencyFileNotResolvable, msg
  end

  handle_enrich_constraints(error)

  raise DependencyFileNotResolvable, error.message if error.message.match(PYTHON_RANGE_NOT_SATISFIED)

  if error.message.match(POETRY_VIRTUAL_ENV_CONFIG) || error.message.match(ERR_LOCAL_PROJECT_PATH)
    msg = "Error while resolving pyproject.toml file"
    raise DependencyFileNotResolvable, msg
  end

  SERVER_ERROR_CODES.each do |(_error_codes, error_regex)|
    next unless error.message.match?(error_regex)

    index_url = URI.extract(error.message.to_s).last.then { sanitize_url(_1) }
    raise InconsistentRegistryResponse, index_url
  end

  TIME_OUT_ERRORS.each do |(_error_codes, error_regex)|
    next unless error.message.match?(error_regex)

    raise InconsistentRegistryResponse, "Inconsistent registry response"
  end

  CLIENT_ERROR_CODES.each do |(_error_codes, error_regex)|
    next unless error.message.match?(error_regex)

    index_url = URI.extract(error.message.to_s).last.then { sanitize_url(_1) }
    raise PrivateSourceAuthenticationFailure, index_url
  end

  PACKAGE_RESOLVER_ERRORS.each do |(_error_codes, error_regex)|
    next unless error.message.match?(error_regex)

    message = "Package solving failed while resolving manifest file"
    raise DependencyFileNotResolvable, message
  end
end