dependabot-core 0.78.0 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/helpers/npm/lib/updater.js +11 -5
  4. data/helpers/npm/package.json +2 -2
  5. data/helpers/npm/yarn.lock +26 -28
  6. data/helpers/yarn/lib/replace-lockfile-declaration.js +15 -3
  7. data/helpers/yarn/lib/updater.js +17 -5
  8. data/helpers/yarn/package.json +2 -2
  9. data/helpers/yarn/yarn.lock +24 -31
  10. data/lib/dependabot/file_fetchers.rb +0 -2
  11. data/lib/dependabot/file_parsers.rb +0 -2
  12. data/lib/dependabot/file_updaters.rb +0 -2
  13. data/lib/dependabot/metadata_finders.rb +0 -2
  14. data/lib/dependabot/update_checkers.rb +0 -2
  15. data/lib/dependabot/utils.rb +0 -4
  16. data/lib/dependabot/version.rb +1 -1
  17. metadata +3 -34
  18. data/helpers/python/lib/__init__.py +0 -0
  19. data/helpers/python/lib/hasher.py +0 -23
  20. data/helpers/python/lib/parser.py +0 -130
  21. data/helpers/python/requirements.txt +0 -9
  22. data/helpers/python/run.py +0 -18
  23. data/lib/dependabot/file_fetchers/python/pip.rb +0 -305
  24. data/lib/dependabot/file_parsers/python/pip.rb +0 -223
  25. data/lib/dependabot/file_parsers/python/pip/pipfile_files_parser.rb +0 -154
  26. data/lib/dependabot/file_parsers/python/pip/poetry_files_parser.rb +0 -141
  27. data/lib/dependabot/file_parsers/python/pip/setup_file_parser.rb +0 -164
  28. data/lib/dependabot/file_updaters/python/pip.rb +0 -147
  29. data/lib/dependabot/file_updaters/python/pip/pip_compile_file_updater.rb +0 -363
  30. data/lib/dependabot/file_updaters/python/pip/pipfile_file_updater.rb +0 -397
  31. data/lib/dependabot/file_updaters/python/pip/pipfile_preparer.rb +0 -125
  32. data/lib/dependabot/file_updaters/python/pip/poetry_file_updater.rb +0 -289
  33. data/lib/dependabot/file_updaters/python/pip/pyproject_preparer.rb +0 -105
  34. data/lib/dependabot/file_updaters/python/pip/requirement_file_updater.rb +0 -166
  35. data/lib/dependabot/file_updaters/python/pip/requirement_replacer.rb +0 -95
  36. data/lib/dependabot/file_updaters/python/pip/setup_file_sanitizer.rb +0 -91
  37. data/lib/dependabot/file_updaters/ruby/.DS_Store +0 -0
  38. data/lib/dependabot/metadata_finders/python/pip.rb +0 -120
  39. data/lib/dependabot/update_checkers/python/pip.rb +0 -227
  40. data/lib/dependabot/update_checkers/python/pip/latest_version_finder.rb +0 -252
  41. data/lib/dependabot/update_checkers/python/pip/pip_compile_version_resolver.rb +0 -380
  42. data/lib/dependabot/update_checkers/python/pip/pipfile_version_resolver.rb +0 -559
  43. data/lib/dependabot/update_checkers/python/pip/poetry_version_resolver.rb +0 -300
  44. data/lib/dependabot/update_checkers/python/pip/requirements_updater.rb +0 -367
  45. data/lib/dependabot/utils/python/requirement.rb +0 -130
  46. data/lib/dependabot/utils/python/version.rb +0 -88
  47. data/lib/python_requirement_parser.rb +0 -33
  48. data/lib/python_versions.rb +0 -21
@@ -1,252 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "excon"
4
-
5
- require "dependabot/update_checkers/python/pip"
6
- require "dependabot/shared_helpers"
7
-
8
- module Dependabot
9
- module UpdateCheckers
10
- module Python
11
- class Pip
12
- class LatestVersionFinder
13
- def initialize(dependency:, dependency_files:, credentials:,
14
- ignored_versions:)
15
- @dependency = dependency
16
- @dependency_files = dependency_files
17
- @credentials = credentials
18
- @ignored_versions = ignored_versions
19
- end
20
-
21
- def latest_version
22
- @latest_version ||= fetch_latest_version
23
- end
24
-
25
- def latest_version_with_no_unlock
26
- @latest_version_with_no_unlock ||=
27
- fetch_latest_version_with_no_unlock
28
- end
29
-
30
- private
31
-
32
- attr_reader :dependency, :dependency_files, :credentials,
33
- :ignored_versions
34
-
35
- def fetch_latest_version
36
- versions = available_versions
37
- versions.reject! { |v| ignore_reqs.any? { |r| r.satisfied_by?(v) } }
38
- versions.reject!(&:prerelease?) unless wants_prerelease?
39
- versions.max
40
- end
41
-
42
- def fetch_latest_version_with_no_unlock
43
- versions = available_versions
44
- reqs = dependency.requirements.map do |r|
45
- reqs = (r.fetch(:requirement) || "").split(",").map(&:strip)
46
- requirement_class.new(reqs)
47
- end
48
- versions.reject!(&:prerelease?) unless wants_prerelease?
49
- versions.sort.reverse.
50
- reject { |v| ignore_reqs.any? { |r| r.satisfied_by?(v) } }.
51
- find { |v| reqs.all? { |r| r.satisfied_by?(v) } }
52
- end
53
-
54
- def wants_prerelease?
55
- if dependency.version
56
- version = version_class.new(dependency.version.tr("+", "."))
57
- return version.prerelease?
58
- end
59
-
60
- dependency.requirements.any? do |req|
61
- reqs = (req.fetch(:requirement) || "").split(",").map(&:strip)
62
- reqs.any? { |r| r.match?(/[A-Za-z]/) }
63
- end
64
- end
65
-
66
- # See https://www.python.org/dev/peps/pep-0503/ for details of the
67
- # Simple Repository API we use here.
68
- def available_versions
69
- index_urls.flat_map do |index_url|
70
- sanitized_url = index_url.gsub(%r{(?<=//).*(?=@)}, "redacted")
71
- index_response = registry_response_for_dependency(index_url)
72
-
73
- if [401, 403].include?(index_response.status) &&
74
- [401, 403].include?(registry_index_response(index_url).status)
75
- raise PrivateSourceAuthenticationFailure, sanitized_url
76
- end
77
-
78
- index_response.body.
79
- scan(%r{<a\s.*?>(.*?)</a>}m).flatten.
80
- select { |n| n.match?(name_regex) }.
81
- map do |filename|
82
- version =
83
- filename.
84
- gsub(/#{name_regex}-/i, "").
85
- split(/-|(\.tar\.)/).
86
- first
87
- next unless version_class.correct?(version)
88
-
89
- version_class.new(version)
90
- end.compact
91
- rescue Excon::Error::Timeout, Excon::Error::Socket
92
- next if MAIN_PYPI_INDEXES.include?(index_url)
93
-
94
- raise PrivateSourceAuthenticationFailure, sanitized_url
95
- end
96
- end
97
-
98
- def index_urls
99
- main_index_url =
100
- config_variable_index_urls[:main] ||
101
- pipfile_index_urls[:main] ||
102
- requirement_file_index_urls[:main] ||
103
- pip_conf_index_urls[:main] ||
104
- "https://pypi.python.org/simple/"
105
-
106
- if main_index_url
107
- main_index_url = main_index_url.strip.gsub(%r{/*$}, "") + "/"
108
- end
109
-
110
- extra_index_urls =
111
- config_variable_index_urls[:extra] +
112
- pipfile_index_urls[:extra] +
113
- requirement_file_index_urls[:extra] +
114
- pip_conf_index_urls[:extra]
115
-
116
- extra_index_urls =
117
- extra_index_urls.map { |url| url.strip.gsub(%r{/*$}, "") + "/" }
118
-
119
- [main_index_url, *extra_index_urls].uniq
120
- end
121
-
122
- def registry_response_for_dependency(index_url)
123
- Excon.get(
124
- index_url + normalised_name + "/",
125
- idempotent: true,
126
- **SharedHelpers.excon_defaults
127
- )
128
- end
129
-
130
- def registry_index_response(index_url)
131
- Excon.get(
132
- index_url,
133
- idempotent: true,
134
- **SharedHelpers.excon_defaults
135
- )
136
- end
137
-
138
- def requirement_file_index_urls
139
- urls = { main: nil, extra: [] }
140
-
141
- requirements_files.each do |file|
142
- if file.content.match?(/^--index-url\s(.+)/)
143
- urls[:main] =
144
- file.content.match(/^--index-url\s(.+)/).captures.first
145
- end
146
- urls[:extra] += file.content.scan(/^--extra-index-url\s(.+)/).
147
- flatten
148
- end
149
-
150
- urls
151
- end
152
-
153
- def pip_conf_index_urls
154
- urls = { main: nil, extra: [] }
155
-
156
- return urls unless pip_conf
157
-
158
- content = pip_conf.content
159
-
160
- if content.match?(/^index-url\s*=/x)
161
- urls[:main] = content.match(/^index-url\s*=\s*(.+)/).
162
- captures.first
163
- end
164
- urls[:extra] += content.scan(/^extra-index-url\s*=(.+)/).flatten
165
-
166
- urls
167
- end
168
-
169
- def pipfile_index_urls
170
- urls = { main: nil, extra: [] }
171
-
172
- return urls unless pipfile
173
-
174
- pipfile_object = TomlRB.parse(pipfile.content)
175
-
176
- urls[:main] = pipfile_object["source"]&.first&.fetch("url", nil)
177
-
178
- pipfile_object["source"]&.each do |source|
179
- urls[:extra] << source.fetch("url") if source["url"]
180
- end
181
- urls[:extra] = urls[:extra].uniq
182
-
183
- urls
184
- rescue TomlRB::ParseError
185
- urls
186
- end
187
-
188
- def config_variable_index_urls
189
- urls = { main: nil, extra: [] }
190
-
191
- index_url_creds = credentials.
192
- select { |cred| cred["type"] == "python_index" }
193
- urls[:main] =
194
- index_url_creds.
195
- find { |cred| cred["replaces-base"] }&.
196
- fetch("index-url")
197
- urls[:extra] =
198
- index_url_creds.
199
- reject { |cred| cred["replaces-base"] }.
200
- map { |cred| cred["index-url"] }
201
-
202
- urls
203
- end
204
-
205
- def ignore_reqs
206
- ignored_versions.map { |req| requirement_class.new(req.split(",")) }
207
- end
208
-
209
- # See https://www.python.org/dev/peps/pep-0503/#normalized-names
210
- def normalised_name
211
- dependency.name.downcase.gsub(/[-_.]+/, "-")
212
- end
213
-
214
- def name_regex
215
- parts = dependency.name.split(/[\s_.-]/).map { |n| Regexp.quote(n) }
216
- /#{parts.join("[\s_.-]")}/i
217
- end
218
-
219
- def pip_conf
220
- dependency_files.find { |f| f.name == "pip.conf" }
221
- end
222
-
223
- def pipfile
224
- dependency_files.find { |f| f.name == "Pipfile" }
225
- end
226
-
227
- def pyproject
228
- dependency_files.find { |f| f.name == "pyproject.toml" }
229
- end
230
-
231
- def requirements_files
232
- dependency_files.select { |f| f.name.match?(/requirements/x) }
233
- end
234
-
235
- def pip_compile_files
236
- dependency_files.select { |f| f.name.end_with?(".in") }
237
- end
238
-
239
- def version_class
240
- Utils.version_class_for_package_manager(dependency.package_manager)
241
- end
242
-
243
- def requirement_class
244
- Utils.requirement_class_for_package_manager(
245
- dependency.package_manager
246
- )
247
- end
248
- end
249
- end
250
- end
251
- end
252
- end
@@ -1,380 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "python_requirement_parser"
4
- require "dependabot/file_fetchers/python/pip"
5
- require "dependabot/file_parsers/python/pip"
6
- require "dependabot/update_checkers/python/pip"
7
- require "dependabot/file_updaters/python/pip/requirement_replacer"
8
- require "dependabot/file_updaters/python/pip/setup_file_sanitizer"
9
- require "dependabot/utils/python/version"
10
- require "dependabot/shared_helpers"
11
-
12
- # rubocop:disable Metrics/ClassLength
13
- module Dependabot
14
- module UpdateCheckers
15
- module Python
16
- class Pip
17
- # This class does version resolution for pip-compile. Its approach is:
18
- # - Unlock the dependency we're checking in the requirements.in file
19
- # - Run `pip-compile` and see what the result is
20
- class PipCompileVersionResolver
21
- VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-_]+)*/.freeze
22
-
23
- attr_reader :dependency, :dependency_files, :credentials
24
-
25
- def initialize(dependency:, dependency_files:, credentials:,
26
- unlock_requirement:, latest_allowable_version:)
27
- @dependency = dependency
28
- @dependency_files = dependency_files
29
- @credentials = credentials
30
- @latest_allowable_version = latest_allowable_version
31
- @unlock_requirement = unlock_requirement
32
- end
33
-
34
- def latest_resolvable_version
35
- return @latest_resolvable_version if @resolution_already_attempted
36
-
37
- @resolution_already_attempted = true
38
- @latest_resolvable_version ||= fetch_latest_resolvable_version
39
- end
40
-
41
- private
42
-
43
- attr_reader :latest_allowable_version
44
-
45
- def unlock_requirement?
46
- @unlock_requirement
47
- end
48
-
49
- def fetch_latest_resolvable_version
50
- @latest_resolvable_version_string ||=
51
- SharedHelpers.in_a_temporary_directory do
52
- SharedHelpers.with_git_configured(credentials: credentials) do
53
- write_temporary_dependency_files
54
-
55
- filenames_to_compile.each do |filename|
56
- # Shell out to pip-compile.
57
- # This is slow, as pip-compile needs to do installs.
58
- cmd = "pyenv exec pip-compile --allow-unsafe "\
59
- "-P #{dependency.name} #{filename}"
60
- run_command(cmd)
61
- end
62
-
63
- # Remove any .python-version file before parsing the reqs
64
- FileUtils.remove_entry(".python-version", true)
65
-
66
- parse_updated_files
67
- end
68
- rescue SharedHelpers::HelperSubprocessFailed => error
69
- handle_pip_compile_errors(error)
70
- end
71
- return unless @latest_resolvable_version_string
72
-
73
- Utils::Python::Version.new(@latest_resolvable_version_string)
74
- end
75
-
76
- def parse_requirements_from_cwd_files
77
- SharedHelpers.run_helper_subprocess(
78
- command: "pyenv exec python #{python_helper_path}",
79
- function: "parse_requirements",
80
- args: [Dir.pwd]
81
- )
82
- end
83
-
84
- def handle_pip_compile_errors(error)
85
- if error.message.include?("Could not find a version")
86
- check_original_requirements_resolvable
87
- # If the original requirements are resolvable but we get an
88
- # incompatibility update after unlocking then it's likely to be
89
- # due to problems with pip-compile's cascading resolution
90
- return nil
91
- end
92
-
93
- if error.message.include?('Command "python setup.py egg_info') &&
94
- error.message.include?(dependency.name)
95
- # The latest version of the dependency we're updating is borked
96
- # (because it has an unevaluatable setup.py). Skip the update.
97
- return nil
98
- end
99
-
100
- if error.message.include?("Could not find a version ") &&
101
- !error.message.include?(dependency.name)
102
- # Sometimes pip-tools gets confused and can't work around
103
- # sub-dependency incompatibilities. Ignore those cases.
104
- return nil
105
- end
106
-
107
- raise
108
- end
109
-
110
- # Needed because pip-compile's resolver isn't perfect.
111
- # Note: We raise errors from this method, rather than returning a
112
- # boolean, so that all deps for this repo will raise identical
113
- # errors when failing to update
114
- def check_original_requirements_resolvable
115
- SharedHelpers.in_a_temporary_directory do
116
- SharedHelpers.with_git_configured(credentials: credentials) do
117
- write_temporary_dependency_files(unlock_requirement: false)
118
-
119
- filenames_to_compile.each do |filename|
120
- cmd = "pyenv exec pip-compile --allow-unsafe #{filename}"
121
- run_command(cmd)
122
- end
123
-
124
- true
125
- rescue SharedHelpers::HelperSubprocessFailed => error
126
- raise unless error.message.include?("Could not find a version")
127
-
128
- msg = clean_error_message(error.message)
129
- raise if msg.empty?
130
-
131
- raise DependencyFileNotResolvable, msg
132
- end
133
- end
134
- end
135
-
136
- def run_command(command)
137
- command = command.dup
138
- raw_response = nil
139
- IO.popen(command, err: %i(child out)) do |process|
140
- raw_response = process.read
141
- end
142
-
143
- # Raise an error with the output from the shell session if
144
- # pip-compile returns a non-zero status
145
- return if $CHILD_STATUS.success?
146
-
147
- raise SharedHelpers::HelperSubprocessFailed.new(
148
- raw_response,
149
- command
150
- )
151
- rescue SharedHelpers::HelperSubprocessFailed => error
152
- original_error ||= error
153
- msg = error.message
154
-
155
- relevant_error =
156
- if error_suggests_bad_python_version?(msg) then original_error
157
- else error
158
- end
159
-
160
- raise relevant_error unless error_suggests_bad_python_version?(msg)
161
- raise relevant_error if File.exist?(".python-version")
162
-
163
- command = "pyenv local 2.7.15 && " + command
164
- retry
165
- ensure
166
- FileUtils.remove_entry(".python-version", true)
167
- end
168
-
169
- def error_suggests_bad_python_version?(message)
170
- return true if message.include?("not find a version that satisfies")
171
-
172
- message.include?('Command "python setup.py egg_info" failed')
173
- end
174
-
175
- def write_temporary_dependency_files(unlock_requirement: true)
176
- dependency_files.each do |file|
177
- next if file.name == ".python-version"
178
-
179
- path = file.name
180
- FileUtils.mkdir_p(Pathname.new(path).dirname)
181
- File.write(
182
- path,
183
- unlock_requirement ? unlock_dependency(file) : file.content
184
- )
185
- end
186
-
187
- setup_files.each do |file|
188
- path = file.name
189
- FileUtils.mkdir_p(Pathname.new(path).dirname)
190
- File.write(path, sanitized_setup_file_content(file))
191
- end
192
-
193
- setup_cfg_files.each do |file|
194
- path = file.name
195
- FileUtils.mkdir_p(Pathname.new(path).dirname)
196
- File.write(path, "[metadata]\nname = sanitized-package\n")
197
- end
198
- end
199
-
200
- def sanitized_setup_file_content(file)
201
- @sanitized_setup_file_content ||= {}
202
- if @sanitized_setup_file_content[file.name]
203
- return @sanitized_setup_file_content[file.name]
204
- end
205
-
206
- @sanitized_setup_file_content[file.name] =
207
- FileUpdaters::Python::Pip::SetupFileSanitizer.
208
- new(setup_file: file, setup_cfg: setup_cfg(file)).
209
- sanitized_content
210
- end
211
-
212
- def setup_cfg(file)
213
- dependency_files.find do |f|
214
- f.name == file.name.sub(/\.py$/, ".cfg")
215
- end
216
- end
217
-
218
- def unlock_dependency(file)
219
- return file.content unless file.name.end_with?(".in")
220
- return file.content unless dependency.version
221
- return file.content unless unlock_requirement?
222
-
223
- req = dependency.requirements.find { |r| r[:file] == file.name }
224
- return file.content unless req&.fetch(:requirement)
225
-
226
- FileUpdaters::Python::Pip::RequirementReplacer.new(
227
- content: file.content,
228
- dependency_name: dependency.name,
229
- old_requirement: req[:requirement],
230
- new_requirement: updated_version_requirement_string
231
- ).updated_content
232
- end
233
-
234
- def updated_version_requirement_string
235
- lower_bound_req = updated_version_req_lower_bound
236
-
237
- # Add the latest_allowable_version as an upper bound. This means
238
- # ignore conditions are considered when checking for the latest
239
- # resolvable version.
240
- #
241
- # NOTE: This isn't perfect. If v2.x is ignored and v3 is out but
242
- # unresolvable then the `latest_allowable_version` will be v3, and
243
- # we won't be ignoring v2.x releases like we should be.
244
- return lower_bound_req if latest_allowable_version.nil?
245
- unless Utils::Python::Version.correct?(latest_allowable_version)
246
- return lower_bound_req
247
- end
248
-
249
- lower_bound_req + ", <= #{latest_allowable_version}"
250
- end
251
-
252
- def updated_version_req_lower_bound
253
- if dependency.version
254
- ">= #{dependency.version}"
255
- else
256
- version_for_requirement =
257
- dependency.requirements.map { |r| r[:requirement] }.compact.
258
- reject { |req_string| req_string.start_with?("<") }.
259
- select { |req_string| req_string.match?(VERSION_REGEX) }.
260
- map { |req_string| req_string.match(VERSION_REGEX) }.
261
- select { |version| Gem::Version.correct?(version) }.
262
- max_by { |version| Gem::Version.new(version) }
263
-
264
- ">= #{version_for_requirement || 0}"
265
- end
266
- end
267
-
268
- def python_helper_path
269
- project_root = File.join(File.dirname(__FILE__), "../../../../..")
270
- File.join(project_root, "helpers/python/run.py")
271
- end
272
-
273
- # See https://www.python.org/dev/peps/pep-0503/#normalized-names
274
- def normalise(name)
275
- name.downcase.gsub(/[-_.]+/, "-")
276
- end
277
-
278
- def clean_error_message(message)
279
- # Redact any URLs, as they may include credentials
280
- message.gsub(/http.*?(?=\s)/, "<redacted>")
281
- end
282
-
283
- def filenames_to_compile
284
- files_from_reqs =
285
- dependency.requirements.
286
- map { |r| r[:file] }.
287
- select { |fn| fn.end_with?(".in") }
288
-
289
- files_from_compiled_files =
290
- pip_compile_files.map(&:name).select do |fn|
291
- compiled_file = dependency_files.
292
- find { |f| f.name == fn.gsub(/\.in$/, ".txt") }
293
- compiled_file_includes_dependency?(compiled_file)
294
- end
295
-
296
- filenames = [*files_from_reqs, *files_from_compiled_files].uniq
297
-
298
- order_filenames_for_compilation(filenames)
299
- end
300
-
301
- def compiled_file_includes_dependency?(compiled_file)
302
- return false unless compiled_file
303
-
304
- regex = PythonRequirementParser::INSTALL_REQ_WITH_REQUIREMENT
305
-
306
- matches = []
307
- compiled_file.content.scan(regex) { matches << Regexp.last_match }
308
- matches.any? { |m| normalise(m[:name]) == dependency.name }
309
- end
310
-
311
- # If the files we need to update require one another then we need to
312
- # update them in the right order
313
- def order_filenames_for_compilation(filenames)
314
- ordered_filenames = []
315
-
316
- while (remaining_filenames = filenames - ordered_filenames).any?
317
- ordered_filenames +=
318
- remaining_filenames.
319
- select do |fn|
320
- unupdated_reqs = requirement_map[fn] - ordered_filenames
321
- (unupdated_reqs & filenames).empty?
322
- end
323
- end
324
-
325
- ordered_filenames
326
- end
327
-
328
- def requirement_map
329
- child_req_regex = FileFetchers::Python::Pip::CHILD_REQUIREMENT_REGEX
330
- @requirement_map ||=
331
- pip_compile_files.each_with_object({}) do |file, req_map|
332
- paths = file.content.scan(child_req_regex).flatten
333
- current_dir = File.dirname(file.name)
334
-
335
- req_map[file.name] =
336
- paths.map do |path|
337
- path = File.join(current_dir, path) if current_dir != "."
338
- path = Pathname.new(path).cleanpath.to_path
339
- path = path.gsub(/\.txt$/, ".in")
340
- next if path == file.name
341
-
342
- path
343
- end.uniq.compact
344
- end
345
- end
346
-
347
- def parse_updated_files
348
- updated_files =
349
- dependency_files.map do |file|
350
- next file if file.name == ".python-version"
351
-
352
- updated_file = file.dup
353
- updated_file.content = File.read(file.name)
354
- updated_file
355
- end
356
-
357
- FileParsers::Python::Pip.new(
358
- dependency_files: updated_files,
359
- source: nil,
360
- credentials: credentials
361
- ).parse.find { |d| d.name == dependency.name }&.version
362
- end
363
-
364
- def setup_files
365
- dependency_files.select { |f| f.name.end_with?("setup.py") }
366
- end
367
-
368
- def pip_compile_files
369
- dependency_files.select { |f| f.name.end_with?(".in") }
370
- end
371
-
372
- def setup_cfg_files
373
- dependency_files.select { |f| f.name.end_with?("setup.cfg") }
374
- end
375
- end
376
- end
377
- end
378
- end
379
- end
380
- # rubocop:enable Metrics/ClassLength