Class: Dependabot::Python::FileUpdater::PyprojectPreparer

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/python/file_updater/pyproject_preparer.rb

Constant Summary collapse

PEP508_PREFIX =

Fixed regex for extracting the name+extras prefix from a PEP 508 entry. Does not interpolate library input, avoiding polynomial backtracking.

T.let(
  /\A(?<prefix>(?<name>[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?)(?:\[[^\]]*\])?)/i,
  Regexp
)
UNSUPPORTED_SOURCE_TYPES =
T.let(%w(directory file url).freeze, T::Array[String])

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pyproject_content:, lockfile: nil) ⇒ PyprojectPreparer

Returns a new instance of PyprojectPreparer.



95
96
97
98
99
# File 'lib/dependabot/python/file_updater/pyproject_preparer.rb', line 95

def initialize(pyproject_content:, lockfile: nil)
  @pyproject_content = pyproject_content
  @lockfile = lockfile
  @parsed_lockfile = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
end

Class Method Details

.freeze_pep621_deps!(pyproject_object, deps, &blk) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/dependabot/python/file_updater/pyproject_preparer.rb', line 54

def self.freeze_pep621_deps!(pyproject_object, deps, &blk)
  dep_arrays = collect_pep621_dep_arrays(pyproject_object)
  return if dep_arrays.empty?

  deps.each do |dep|
    next if blk && !yield(dep)
    next unless dep.version

    pin_pep621_dep_in_arrays!(dep_arrays, dep)
  end
end

Instance Method Details

#add_auth_env_vars(credentials) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/dependabot/python/file_updater/pyproject_preparer.rb', line 104

def add_auth_env_vars(credentials)
  TomlRB.parse(@pyproject_content).dig("tool", "poetry", "source")&.each do |source|
    cred = credentials&.find { |c| c["index-url"] == source["url"] }
    next unless cred

    token = cred.fetch("token", nil)
    next unless token && token.count(":") == 1

    arr = token.split(":")
    # https://python-poetry.org/docs/configuration/#using-environment-variables
    name = source["name"]&.upcase&.gsub(/\W/, "_")
    ENV["POETRY_HTTP_BASIC_#{name}_USERNAME"] = arr[0]
    ENV["POETRY_HTTP_BASIC_#{name}_PASSWORD"] = arr[1]
  end
end

#freeze_top_level_dependencies_except(dependencies) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/dependabot/python/file_updater/pyproject_preparer.rb', line 145

def freeze_top_level_dependencies_except(dependencies)
  return pyproject_content unless lockfile

  pyproject_object = TomlRB.parse(pyproject_content)
  poetry_object = pyproject_object.dig("tool", "poetry")

  return pyproject_content unless poetry_object

  excluded_names = dependencies.map(&:name) + ["python"]

  Dependabot::Python::FileParser::PyprojectFilesParser::POETRY_DEPENDENCY_TYPES.each do |key|
    next unless poetry_object[key]

    poetry_object.fetch(key).each do |dep_name, _|
      next if excluded_names.include?(normalise(dep_name))

      freeze_poetry_dep!(poetry_object[key], dep_name)
    end
  end

  # Freeze PEP 621 project.dependencies and project.optional-dependencies
  freeze_pep621_top_level_deps!(pyproject_object, excluded_names)

  TomlRB.dump(pyproject_object)
end

#sanitizeObject



135
136
137
138
139
140
# File 'lib/dependabot/python/file_updater/pyproject_preparer.rb', line 135

def sanitize
  # {{ name }} syntax not allowed
  pyproject_content
    .gsub(/\{\{.*?\}\}/, "something")
    .gsub('#{', "{")
end

#update_python_requirement(requirement) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/dependabot/python/file_updater/pyproject_preparer.rb', line 121

def update_python_requirement(requirement)
  pyproject_object = TomlRB.parse(@pyproject_content)

  if (python_specification = pyproject_object.dig("tool", "poetry", "dependencies", "python"))
    python_req = Python::Requirement.new(python_specification)
    unless python_req.satisfied_by?(requirement)
      pyproject_object["tool"]["poetry"]["dependencies"]["python"] = "~#{requirement}"
    end
  end

  TomlRB.dump(pyproject_object)
end