dependabot-python 0.209.0 → 0.212.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/helpers/requirements.txt +1 -1
- data/lib/dependabot/python/file_fetcher.rb +4 -3
- data/lib/dependabot/python/file_parser/poetry_files_parser.rb +4 -3
- data/lib/dependabot/python/file_parser/python_requirement_parser.rb +1 -2
- data/lib/dependabot/python/file_parser/setup_file_parser.rb +1 -1
- data/lib/dependabot/python/file_updater/pip_compile_file_updater.rb +11 -11
- data/lib/dependabot/python/file_updater/pipfile_file_updater.rb +6 -4
- data/lib/dependabot/python/file_updater/poetry_file_updater.rb +1 -1
- data/lib/dependabot/python/file_updater/pyproject_preparer.rb +2 -1
- data/lib/dependabot/python/file_updater/requirement_file_updater.rb +2 -2
- data/lib/dependabot/python/file_updater/requirement_replacer.rb +2 -2
- data/lib/dependabot/python/file_updater/setup_file_sanitizer.rb +8 -8
- data/lib/dependabot/python/file_updater.rb +2 -2
- data/lib/dependabot/python/native_helpers.rb +1 -1
- data/lib/dependabot/python/update_checker/index_finder.rb +1 -1
- data/lib/dependabot/python/update_checker/latest_version_finder.rb +10 -7
- data/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb +1 -1
- data/lib/dependabot/python/update_checker/pipenv_version_resolver.rb +23 -19
- data/lib/dependabot/python/update_checker/poetry_version_resolver.rb +35 -18
- data/lib/dependabot/python/update_checker/requirements_updater.rb +1 -1
- data/lib/dependabot/python/update_checker.rb +3 -5
- metadata +34 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4862b59513a97a33d51ff8ad57b6d9815842769c87f612426ffbcd8e75a9655c
|
4
|
+
data.tar.gz: 9543935b3ab8027344757b41aa8ff265d823beac956a06d20d4917e75962698d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd9e547d19f01addfdc2fcc4eeb7095bf8e886eded086772f81b9bfbd6acfb2fc6076c354c970ae5fad0691a25679d99db8eb0884121e986c1bcf39b17c041ba
|
7
|
+
data.tar.gz: be587fe031f132dd20d4fc023668e31d81c37608d915a9f586ca159b675302993a208b6e93209cfaedad83d08eaae1ca06f6af7eec8933bcc2c44e8a61293ccf
|
data/helpers/requirements.txt
CHANGED
@@ -13,6 +13,7 @@ module Dependabot
|
|
13
13
|
class FileFetcher < Dependabot::FileFetchers::Base
|
14
14
|
CHILD_REQUIREMENT_REGEX = /^-r\s?(?<path>.*\.(?:txt|in))/.freeze
|
15
15
|
CONSTRAINT_REGEX = /^-c\s?(?<path>.*\.(?:txt|in))/.freeze
|
16
|
+
DEPENDENCY_TYPES = %w(packages dev-packages).freeze
|
16
17
|
|
17
18
|
def self.required_files_in?(filenames)
|
18
19
|
return true if filenames.any? { |name| name.end_with?(".txt", ".in") }
|
@@ -32,8 +33,8 @@ module Dependabot
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def self.required_files_message
|
35
|
-
"Repo must contain a requirements.txt, setup.py, setup.cfg, pyproject.toml, "\
|
36
|
-
|
36
|
+
"Repo must contain a requirements.txt, setup.py, setup.cfg, pyproject.toml, " \
|
37
|
+
"or a Pipfile."
|
37
38
|
end
|
38
39
|
|
39
40
|
private
|
@@ -372,7 +373,7 @@ module Dependabot
|
|
372
373
|
return [] unless pipfile
|
373
374
|
|
374
375
|
paths = []
|
375
|
-
|
376
|
+
DEPENDENCY_TYPES.each do |dep_type|
|
376
377
|
next unless parsed_pipfile[dep_type]
|
377
378
|
|
378
379
|
parsed_pipfile[dep_type].each do |_, req|
|
@@ -61,7 +61,7 @@ module Dependabot
|
|
61
61
|
|
62
62
|
# @param req can be an Array, Hash or String that represents the constraints for a dependency
|
63
63
|
def parse_requirements_from(req, type)
|
64
|
-
[req].flatten.compact.
|
64
|
+
[req].flatten.compact.filter_map do |requirement|
|
65
65
|
next if requirement.is_a?(Hash) && (UNSUPPORTED_DEPENDENCY_TYPES & requirement.keys).any?
|
66
66
|
|
67
67
|
check_requirements(requirement)
|
@@ -72,7 +72,7 @@ module Dependabot
|
|
72
72
|
source: nil,
|
73
73
|
groups: [type]
|
74
74
|
}
|
75
|
-
end
|
75
|
+
end
|
76
76
|
end
|
77
77
|
|
78
78
|
# Create a DependencySet where each element has no requirement. Any
|
@@ -81,8 +81,9 @@ module Dependabot
|
|
81
81
|
def lockfile_dependencies
|
82
82
|
dependencies = Dependabot::FileParsers::Base::DependencySet.new
|
83
83
|
|
84
|
+
source_types = %w(directory git url)
|
84
85
|
parsed_lockfile.fetch("package", []).each do |details|
|
85
|
-
next if
|
86
|
+
next if source_types.include?(details.dig("source", "type"))
|
86
87
|
|
87
88
|
dependencies <<
|
88
89
|
Dependency.new(
|
@@ -33,8 +33,7 @@ module Dependabot
|
|
33
33
|
requirement_files.flat_map do |file|
|
34
34
|
file.content.lines.
|
35
35
|
select { |l| l.include?(";") && l.include?("python") }.
|
36
|
-
|
37
|
-
compact.
|
36
|
+
filter_map { |l| l.match(/python_version(?<req>.*?["'].*?['"])/) }.
|
38
37
|
map { |re| re.named_captures.fetch("req").gsub(/['"]/, "") }.
|
39
38
|
select { |r| valid_requirement?(r) }
|
40
39
|
end
|
@@ -128,7 +128,7 @@ module Dependabot
|
|
128
128
|
tests_require = get_regexed_req_array(TESTS_REQUIRE_REGEX)
|
129
129
|
extras_require = get_regexed_req_dict(EXTRAS_REQUIRE_REGEX)
|
130
130
|
|
131
|
-
tmp = "from setuptools import setup\n\n"\
|
131
|
+
tmp = "from setuptools import setup\n\n" \
|
132
132
|
"setup(name=\"sanitized-package\",version=\"0.0.1\","
|
133
133
|
|
134
134
|
tmp += "install_requires=#{install_requires}," if install_requires
|
@@ -71,20 +71,20 @@ module Dependabot
|
|
71
71
|
filenames_to_compile.each do |filename|
|
72
72
|
# Shell out to pip-compile, generate a new set of requirements.
|
73
73
|
# This is slow, as pip-compile needs to do installs.
|
74
|
-
name_part = "pyenv exec pip-compile "\
|
75
|
-
"#{pip_compile_options(filename)} -P "\
|
74
|
+
name_part = "pyenv exec pip-compile " \
|
75
|
+
"#{pip_compile_options(filename)} -P " \
|
76
76
|
"#{dependency.name}"
|
77
77
|
version_part = "#{dependency.version} #{filename}"
|
78
78
|
# Don't escape pyenv `dep-name==version` syntax
|
79
79
|
run_pip_compile_command(
|
80
|
-
"#{SharedHelpers.escape_command(name_part)}=="\
|
80
|
+
"#{SharedHelpers.escape_command(name_part)}==" \
|
81
81
|
"#{SharedHelpers.escape_command(version_part)}",
|
82
82
|
allow_unsafe_shell_command: true
|
83
83
|
)
|
84
84
|
# Run pip-compile a second time, without an update argument, to
|
85
85
|
# ensure it resets the right comments.
|
86
86
|
run_pip_compile_command(
|
87
|
-
"pyenv exec pip-compile #{pip_compile_options(filename)} "\
|
87
|
+
"pyenv exec pip-compile #{pip_compile_options(filename)} " \
|
88
88
|
"#{filename}"
|
89
89
|
)
|
90
90
|
end
|
@@ -92,7 +92,7 @@ module Dependabot
|
|
92
92
|
# Remove any .python-version file before parsing the reqs
|
93
93
|
FileUtils.remove_entry(".python-version", true)
|
94
94
|
|
95
|
-
dependency_files.
|
95
|
+
dependency_files.filter_map do |file|
|
96
96
|
next unless file.name.end_with?(".txt")
|
97
97
|
|
98
98
|
updated_content = File.read(file.name)
|
@@ -102,12 +102,12 @@ module Dependabot
|
|
102
102
|
next if updated_content == file.content
|
103
103
|
|
104
104
|
file.dup.tap { |f| f.content = updated_content }
|
105
|
-
end
|
105
|
+
end
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
def update_manifest_files
|
110
|
-
dependency_files.
|
110
|
+
dependency_files.filter_map do |file|
|
111
111
|
next unless file.name.end_with?(".in")
|
112
112
|
|
113
113
|
file = file.dup
|
@@ -116,7 +116,7 @@ module Dependabot
|
|
116
116
|
|
117
117
|
file.content = updated_content
|
118
118
|
file
|
119
|
-
end
|
119
|
+
end
|
120
120
|
end
|
121
121
|
|
122
122
|
def update_uncompiled_files(updated_files)
|
@@ -132,7 +132,7 @@ module Dependabot
|
|
132
132
|
reject { |file| updated_filenames.include?(file.name) }
|
133
133
|
|
134
134
|
args = dependency.to_h
|
135
|
-
args = args.keys.
|
135
|
+
args = args.keys.to_h { |k| [k.to_sym, args[k]] }
|
136
136
|
args[:requirements] = new_reqs
|
137
137
|
args[:previous_requirements] = old_reqs
|
138
138
|
|
@@ -224,7 +224,7 @@ module Dependabot
|
|
224
224
|
|
225
225
|
run_command("pyenv install -s #{python_version}")
|
226
226
|
run_command("pyenv exec pip install --upgrade pip")
|
227
|
-
run_command("pyenv exec pip install -r "\
|
227
|
+
run_command("pyenv exec pip install -r " \
|
228
228
|
"#{NativeHelpers.python_requirements_path}")
|
229
229
|
end
|
230
230
|
|
@@ -352,7 +352,7 @@ module Dependabot
|
|
352
352
|
end
|
353
353
|
|
354
354
|
def deps_to_augment_hashes_for(updated_content, original_content)
|
355
|
-
regex = /^#{RequirementParser::INSTALL_REQ_WITH_REQUIREMENT}/
|
355
|
+
regex = /^#{RequirementParser::INSTALL_REQ_WITH_REQUIREMENT}/o
|
356
356
|
|
357
357
|
new_matches = []
|
358
358
|
updated_content.scan(regex) { new_matches << Regexp.last_match }
|
@@ -18,6 +18,8 @@ module Dependabot
|
|
18
18
|
require_relative "pipfile_manifest_updater"
|
19
19
|
require_relative "setup_file_sanitizer"
|
20
20
|
|
21
|
+
DEPENDENCY_TYPES = %w(packages dev-packages).freeze
|
22
|
+
|
21
23
|
attr_reader :dependencies, :dependency_files, :credentials
|
22
24
|
|
23
25
|
def initialize(dependencies:, dependency_files:, credentials:)
|
@@ -145,7 +147,7 @@ module Dependabot
|
|
145
147
|
pipfile_object = TomlRB.parse(pipfile_content)
|
146
148
|
|
147
149
|
dependencies.each do |dep|
|
148
|
-
|
150
|
+
DEPENDENCY_TYPES.each do |type|
|
149
151
|
names = pipfile_object[type]&.keys || []
|
150
152
|
pkg_name = names.find { |nm| normalise(nm) == dep.name }
|
151
153
|
next unless pkg_name || subdep_type?(type)
|
@@ -350,9 +352,9 @@ module Dependabot
|
|
350
352
|
|
351
353
|
# Otherwise we have to raise, giving details of the Python versions
|
352
354
|
# that Dependabot supports
|
353
|
-
msg = "Dependabot detected the following Python requirement "\
|
354
|
-
"for your project: '#{requirement_string}'.\n\nCurrently, the "\
|
355
|
-
"following Python versions are supported in Dependabot: "\
|
355
|
+
msg = "Dependabot detected the following Python requirement " \
|
356
|
+
"for your project: '#{requirement_string}'.\n\nCurrently, the " \
|
357
|
+
"following Python versions are supported in Dependabot: " \
|
356
358
|
"#{PythonVersions::SUPPORTED_VERSIONS.join(', ')}."
|
357
359
|
raise DependencyFileNotResolvable, msg
|
358
360
|
end
|
@@ -173,7 +173,7 @@ module Dependabot
|
|
173
173
|
if python_version && !pre_installed_python?(python_version)
|
174
174
|
run_poetry_command("pyenv install -s #{python_version}")
|
175
175
|
run_poetry_command("pyenv exec pip install --upgrade pip")
|
176
|
-
run_poetry_command("pyenv exec pip install -r"\
|
176
|
+
run_poetry_command("pyenv exec pip install -r" \
|
177
177
|
"#{NativeHelpers.python_requirements_path}")
|
178
178
|
end
|
179
179
|
|
@@ -55,6 +55,7 @@ module Dependabot
|
|
55
55
|
Dependabot::Python::FileParser::PoetryFilesParser::POETRY_DEPENDENCY_TYPES.each do |key|
|
56
56
|
next unless poetry_object[key]
|
57
57
|
|
58
|
+
source_types = %w(directory file url)
|
58
59
|
poetry_object.fetch(key).each do |dep_name, _|
|
59
60
|
next if excluded_names.include?(normalise(dep_name))
|
60
61
|
|
@@ -62,7 +63,7 @@ module Dependabot
|
|
62
63
|
|
63
64
|
next unless (locked_version = locked_details&.fetch("version"))
|
64
65
|
|
65
|
-
next if
|
66
|
+
next if source_types.include?(locked_details&.dig("source", "type"))
|
66
67
|
|
67
68
|
if locked_details&.dig("source", "type") == "git"
|
68
69
|
poetry_object[key][dep_name] = {
|
@@ -36,7 +36,7 @@ module Dependabot
|
|
36
36
|
def fetch_updated_dependency_files
|
37
37
|
reqs = dependency.requirements.zip(dependency.previous_requirements)
|
38
38
|
|
39
|
-
reqs.
|
39
|
+
reqs.filter_map do |(new_req, old_req)|
|
40
40
|
next if new_req == old_req
|
41
41
|
|
42
42
|
file = get_original_file(new_req.fetch(:file)).dup
|
@@ -46,7 +46,7 @@ module Dependabot
|
|
46
46
|
|
47
47
|
file.content = updated_content
|
48
48
|
file
|
49
|
-
end
|
49
|
+
end
|
50
50
|
end
|
51
51
|
|
52
52
|
def updated_requirement_or_setup_file_content(new_req, old_req)
|
@@ -52,7 +52,7 @@ module Dependabot
|
|
52
52
|
if add_space_after_operators?
|
53
53
|
new_req_string =
|
54
54
|
new_req_string.
|
55
|
-
gsub(/(#{RequirementParser::COMPARISON})\s*(?=\d)
|
55
|
+
gsub(/(#{RequirementParser::COMPARISON})\s*(?=\d)/o, '\1 ')
|
56
56
|
end
|
57
57
|
|
58
58
|
new_req_string
|
@@ -92,7 +92,7 @@ module Dependabot
|
|
92
92
|
def add_space_after_operators?
|
93
93
|
original_dependency_declaration_string(old_requirement).
|
94
94
|
match(RequirementParser::REQUIREMENTS).
|
95
|
-
to_s.match?(/#{RequirementParser::COMPARISON}\s+\d/)
|
95
|
+
to_s.match?(/#{RequirementParser::COMPARISON}\s+\d/o)
|
96
96
|
end
|
97
97
|
|
98
98
|
def original_declaration_replacement_regex
|
@@ -19,9 +19,9 @@ module Dependabot
|
|
19
19
|
# install_requires. A name and version are required by don't end up
|
20
20
|
# in the lockfile.
|
21
21
|
content =
|
22
|
-
"from setuptools import setup\n\n"\
|
23
|
-
"setup(name=\"sanitized-package\",version=\"0.0.1\","\
|
24
|
-
"install_requires=#{install_requires_array.to_json},"\
|
22
|
+
"from setuptools import setup\n\n" \
|
23
|
+
"setup(name=\"sanitized-package\",version=\"0.0.1\"," \
|
24
|
+
"install_requires=#{install_requires_array.to_json}," \
|
25
25
|
"extras_require=#{extras_require_hash.to_json}"
|
26
26
|
|
27
27
|
content += ',setup_requires=["pbr"],pbr=True' if include_pbr?
|
@@ -38,22 +38,22 @@ module Dependabot
|
|
38
38
|
|
39
39
|
def install_requires_array
|
40
40
|
@install_requires_array ||=
|
41
|
-
parsed_setup_file.dependencies.
|
41
|
+
parsed_setup_file.dependencies.filter_map do |dep|
|
42
42
|
next unless dep.requirements.first[:groups].
|
43
43
|
include?("install_requires")
|
44
44
|
|
45
45
|
dep.name + dep.requirements.first[:requirement].to_s
|
46
|
-
end
|
46
|
+
end
|
47
47
|
end
|
48
48
|
|
49
49
|
def setup_requires_array
|
50
50
|
@setup_requires_array ||=
|
51
|
-
parsed_setup_file.dependencies.
|
51
|
+
parsed_setup_file.dependencies.filter_map do |dep|
|
52
52
|
next unless dep.requirements.first[:groups].
|
53
53
|
include?("setup_requires")
|
54
54
|
|
55
55
|
dep.name + dep.requirements.first[:requirement].to_s
|
56
|
-
end
|
56
|
+
end
|
57
57
|
end
|
58
58
|
|
59
59
|
def extras_require_hash
|
@@ -66,7 +66,7 @@ module Dependabot
|
|
66
66
|
|
67
67
|
hash[group.split(":").last] ||= []
|
68
68
|
hash[group.split(":").last] <<
|
69
|
-
dep.name + dep.requirements.first[:requirement].to_s
|
69
|
+
(dep.name + dep.requirements.first[:requirement].to_s)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -60,8 +60,8 @@ module Dependabot
|
|
60
60
|
|
61
61
|
# Otherwise, this is a top-level dependency, and we can figure out
|
62
62
|
# which resolver to use based on the filename of its requirements
|
63
|
-
return :pipfile if changed_req_files.any?
|
64
|
-
return :poetry if changed_req_files.any?
|
63
|
+
return :pipfile if changed_req_files.any?("Pipfile")
|
64
|
+
return :poetry if changed_req_files.any?("pyproject.toml")
|
65
65
|
return :pip_compile if changed_req_files.any? { |f| f.end_with?(".in") }
|
66
66
|
|
67
67
|
:requirements
|
@@ -171,7 +171,7 @@ module Dependabot
|
|
171
171
|
authed_url = config_variable_urls.find { |u| u.match?(regexp) }
|
172
172
|
return authed_url if authed_url
|
173
173
|
|
174
|
-
cleaned_url = url.gsub(%r{#{ENVIRONMENT_VARIABLE_REGEX}/?}, "")
|
174
|
+
cleaned_url = url.gsub(%r{#{ENVIRONMENT_VARIABLE_REGEX}/?}o, "")
|
175
175
|
authed_url = authed_base_url(cleaned_url)
|
176
176
|
return authed_url if credential_for(cleaned_url)
|
177
177
|
|
@@ -85,14 +85,14 @@ module Dependabot
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def filter_unsupported_versions(versions_array, python_version)
|
88
|
-
versions_array.
|
88
|
+
versions_array.filter_map do |details|
|
89
89
|
python_requirement = details.fetch(:python_requirement)
|
90
90
|
next details.fetch(:version) unless python_version
|
91
91
|
next details.fetch(:version) unless python_requirement
|
92
92
|
next unless python_requirement.satisfied_by?(python_version)
|
93
93
|
|
94
94
|
details.fetch(:version)
|
95
|
-
end
|
95
|
+
end
|
96
96
|
end
|
97
97
|
|
98
98
|
def filter_prerelease_versions(versions_array)
|
@@ -118,9 +118,9 @@ module Dependabot
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def filter_out_of_range_versions(versions_array)
|
121
|
-
reqs = dependency.requirements.
|
121
|
+
reqs = dependency.requirements.filter_map do |r|
|
122
122
|
requirement_class.requirements_array(r.fetch(:requirement))
|
123
|
-
end
|
123
|
+
end
|
124
124
|
|
125
125
|
versions_array.
|
126
126
|
select { |v| reqs.all? { |r| r.any? { |o| o.satisfied_by?(v) } } }
|
@@ -144,11 +144,14 @@ module Dependabot
|
|
144
144
|
@available_versions ||=
|
145
145
|
index_urls.flat_map do |index_url|
|
146
146
|
sanitized_url = index_url.gsub(%r{(?<=//).*(?=@)}, "redacted")
|
147
|
+
|
147
148
|
index_response = registry_response_for_dependency(index_url)
|
149
|
+
if index_response.status == 401 || index_response.status == 403
|
150
|
+
registry_index_response = registry_index_response(index_url)
|
148
151
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
+
if registry_index_response.status == 401 || registry_index_response.status == 403
|
153
|
+
raise PrivateSourceAuthenticationFailure, sanitized_url
|
154
|
+
end
|
152
155
|
end
|
153
156
|
|
154
157
|
version_links = []
|
@@ -318,7 +318,7 @@ module Dependabot
|
|
318
318
|
|
319
319
|
run_command("pyenv install -s #{python_version}")
|
320
320
|
run_command("pyenv exec pip install --upgrade pip")
|
321
|
-
run_command("pyenv exec pip install -r"\
|
321
|
+
run_command("pyenv exec pip install -r" \
|
322
322
|
"#{NativeHelpers.python_requirements_path}")
|
323
323
|
end
|
324
324
|
|
@@ -29,12 +29,13 @@ module Dependabot
|
|
29
29
|
# just raise if the latest version can't be resolved. Knowing that is
|
30
30
|
# still better than nothing, though.
|
31
31
|
class PipenvVersionResolver
|
32
|
+
# rubocop:disable Layout/LineLength
|
32
33
|
GIT_DEPENDENCY_UNREACHABLE_REGEX =
|
33
34
|
/git clone -q (?<url>[^\s]+).* /.freeze
|
34
35
|
GIT_REFERENCE_NOT_FOUND_REGEX =
|
35
36
|
%r{git checkout -q (?<tag>[^\n"]+)\n?[^\n]*/(?<name>.*?)(\\n'\]|$)}m.
|
36
37
|
freeze
|
37
|
-
PIPENV_INSTALLATION_ERROR = "pipenv.patched.notpip._internal.exceptions.InstallationError: Command errored out"\
|
38
|
+
PIPENV_INSTALLATION_ERROR = "pipenv.patched.notpip._internal.exceptions.InstallationError: Command errored out" \
|
38
39
|
" with exit status 1: python setup.py egg_info"
|
39
40
|
TRACEBACK = "Traceback (most recent call last):"
|
40
41
|
PIPENV_INSTALLATION_ERROR_REGEX =
|
@@ -44,6 +45,9 @@ module Dependabot
|
|
44
45
|
UNSUPPORTED_DEP_REGEX =
|
45
46
|
/Could not find a version that satisfies the requirement.*(?:#{UNSUPPORTED_DEPS.join("|")})/.freeze
|
46
47
|
PIPENV_RANGE_WARNING = /Warning:\sPython\s[<>].* was not found/.freeze
|
48
|
+
# rubocop:enable Layout/LineLength
|
49
|
+
|
50
|
+
DEPENDENCY_TYPES = %w(packages dev-packages).freeze
|
47
51
|
|
48
52
|
attr_reader :dependency, :dependency_files, :credentials
|
49
53
|
|
@@ -136,20 +140,20 @@ module Dependabot
|
|
136
140
|
end
|
137
141
|
|
138
142
|
if error.message.match?(UNSUPPORTED_DEP_REGEX)
|
139
|
-
msg = "Dependabot detected a dependency that can't be built on "\
|
140
|
-
"linux. Currently, all Dependabot builds happen on linux "\
|
141
|
-
"boxes, so there is no way for Dependabot to resolve your "\
|
142
|
-
"dependency files.\n\n"\
|
143
|
-
"Unless you think Dependabot has made a mistake (please "\
|
144
|
-
"tag us if so) you may wish to disable Dependabot on this "\
|
143
|
+
msg = "Dependabot detected a dependency that can't be built on " \
|
144
|
+
"linux. Currently, all Dependabot builds happen on linux " \
|
145
|
+
"boxes, so there is no way for Dependabot to resolve your " \
|
146
|
+
"dependency files.\n\n" \
|
147
|
+
"Unless you think Dependabot has made a mistake (please " \
|
148
|
+
"tag us if so) you may wish to disable Dependabot on this " \
|
145
149
|
"repo."
|
146
150
|
raise DependencyFileNotResolvable, msg
|
147
151
|
end
|
148
152
|
|
149
153
|
if error.message.match?(PIPENV_RANGE_WARNING)
|
150
|
-
msg = "Pipenv does not support specifying Python ranges "\
|
151
|
-
|
152
|
-
|
154
|
+
msg = "Pipenv does not support specifying Python ranges " \
|
155
|
+
"(see https://github.com/pypa/pipenv/issues/1050 for more " \
|
156
|
+
"details)."
|
153
157
|
raise DependencyFileNotResolvable, msg
|
154
158
|
end
|
155
159
|
|
@@ -159,7 +163,7 @@ module Dependabot
|
|
159
163
|
|
160
164
|
if error.message.include?("SyntaxError: invalid syntax")
|
161
165
|
raise DependencyFileNotResolvable,
|
162
|
-
"SyntaxError while installing dependencies. Is one of the dependencies not Python 3 compatible? "\
|
166
|
+
"SyntaxError while installing dependencies. Is one of the dependencies not Python 3 compatible? " \
|
163
167
|
"Pip v21 no longer supports Python 2."
|
164
168
|
end
|
165
169
|
|
@@ -272,9 +276,9 @@ module Dependabot
|
|
272
276
|
dependency_name = error_message.match(PIPENV_INSTALLATION_ERROR_REGEX).named_captures["name"]
|
273
277
|
raise unless dependency_name
|
274
278
|
|
275
|
-
msg = "Pipenv failed to install \"#{dependency_name}\". This could be caused by missing system "\
|
276
|
-
"dependencies that can't be installed by Dependabot or required installation flags.\n\n"\
|
277
|
-
"Error output from running \"pipenv lock\":\n"\
|
279
|
+
msg = "Pipenv failed to install \"#{dependency_name}\". This could be caused by missing system " \
|
280
|
+
"dependencies that can't be installed by Dependabot or required installation flags.\n\n" \
|
281
|
+
"Error output from running \"pipenv lock\":\n" \
|
278
282
|
"#{clean_error_message(error_message)}"
|
279
283
|
|
280
284
|
raise DependencyFileNotResolvable, msg
|
@@ -324,7 +328,7 @@ module Dependabot
|
|
324
328
|
requirements_path = NativeHelpers.python_requirements_path
|
325
329
|
run_command("pyenv install -s #{python_version}")
|
326
330
|
run_command("pyenv exec pip install --upgrade pip")
|
327
|
-
run_command("pyenv exec pip install -r "\
|
331
|
+
run_command("pyenv exec pip install -r " \
|
328
332
|
"#{requirements_path}")
|
329
333
|
end
|
330
334
|
|
@@ -361,7 +365,7 @@ module Dependabot
|
|
361
365
|
|
362
366
|
pipfile_object = TomlRB.parse(pipfile_content)
|
363
367
|
|
364
|
-
|
368
|
+
DEPENDENCY_TYPES.each do |type|
|
365
369
|
names = pipfile_object[type]&.keys || []
|
366
370
|
pkg_name = names.find { |nm| normalise(nm) == dependency.name }
|
367
371
|
next unless pkg_name || subdep_type?(type)
|
@@ -429,9 +433,9 @@ module Dependabot
|
|
429
433
|
|
430
434
|
# Otherwise we have to raise, giving details of the Python versions
|
431
435
|
# that Dependabot supports
|
432
|
-
msg = "Dependabot detected the following Python requirement "\
|
433
|
-
"for your project: '#{requirement_string}'.\n\nCurrently, the "\
|
434
|
-
"following Python versions are supported in Dependabot: "\
|
436
|
+
msg = "Dependabot detected the following Python requirement " \
|
437
|
+
"for your project: '#{requirement_string}'.\n\nCurrently, the " \
|
438
|
+
"following Python versions are supported in Dependabot: " \
|
435
439
|
"#{PythonVersions::SUPPORTED_VERSIONS.join(', ')}."
|
436
440
|
raise DependencyFileNotResolvable, msg
|
437
441
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "excon"
|
4
4
|
require "toml-rb"
|
5
5
|
require "open3"
|
6
|
+
require "uri"
|
6
7
|
require "dependabot/dependency"
|
7
8
|
require "dependabot/errors"
|
8
9
|
require "dependabot/shared_helpers"
|
@@ -23,18 +24,26 @@ module Dependabot
|
|
23
24
|
# This class does version resolution for pyproject.toml files.
|
24
25
|
class PoetryVersionResolver
|
25
26
|
GIT_REFERENCE_NOT_FOUND_REGEX = /
|
26
|
-
'git'.*pypoetry-git-(?<name>.+?).{8}',
|
27
|
+
(?:'git'.*pypoetry-git-(?<name>.+?).{8}',
|
27
28
|
'checkout',
|
28
29
|
'(?<tag>.+?)'
|
29
|
-
|
30
|
+
|
|
31
|
+
...Failedtoclone
|
32
|
+
(?<url>.+?).gitat'(?<tag>.+?)',
|
33
|
+
verifyrefexistsonremote)
|
34
|
+
/x.freeze # TODO: remove the first clause and | when py3.6 support is EoL
|
30
35
|
GIT_DEPENDENCY_UNREACHABLE_REGEX = /
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
(?:'\['git',
|
37
|
+
\s+'clone',
|
38
|
+
\s+'--recurse-submodules',
|
39
|
+
\s+'(--)?',
|
40
|
+
\s+'(?<url>.+?)'.*
|
41
|
+
\s+exit\s+status\s+128
|
42
|
+
|
|
43
|
+
\s+Failed\sto\sclone
|
44
|
+
\s+(?<url>.+?),
|
45
|
+
\s+check\syour\sgit\sconfiguration)
|
46
|
+
/mx.freeze # TODO: remove the first clause and | when py3.6 support is EoL
|
38
47
|
|
39
48
|
attr_reader :dependency, :dependency_files, :credentials
|
40
49
|
|
@@ -61,7 +70,8 @@ module Dependabot
|
|
61
70
|
false
|
62
71
|
end
|
63
72
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
64
|
-
raise unless e.message.include?("SolverProblemError")
|
73
|
+
raise unless e.message.include?("SolverProblemError") || # TODO: Remove once py3.6 is EoL
|
74
|
+
e.message.include?("version solving failed.")
|
65
75
|
|
66
76
|
@resolvable[version] = false
|
67
77
|
end
|
@@ -82,7 +92,7 @@ module Dependabot
|
|
82
92
|
run_poetry_command("pyenv install -s #{python_version}")
|
83
93
|
run_poetry_command("pyenv exec pip install --upgrade pip")
|
84
94
|
run_poetry_command(
|
85
|
-
"pyenv exec pip install -r "\
|
95
|
+
"pyenv exec pip install -r " \
|
86
96
|
"#{NativeHelpers.python_requirements_path}"
|
87
97
|
)
|
88
98
|
end
|
@@ -118,8 +128,13 @@ module Dependabot
|
|
118
128
|
def handle_poetry_errors(error)
|
119
129
|
if error.message.gsub(/\s/, "").match?(GIT_REFERENCE_NOT_FOUND_REGEX)
|
120
130
|
message = error.message.gsub(/\s/, "")
|
121
|
-
|
122
|
-
|
131
|
+
match = message.match(GIT_REFERENCE_NOT_FOUND_REGEX)
|
132
|
+
name = if (url = match.named_captures.fetch("url"))
|
133
|
+
File.basename(URI.parse(url).path)
|
134
|
+
else
|
135
|
+
message.match(GIT_REFERENCE_NOT_FOUND_REGEX).
|
136
|
+
named_captures.fetch("name")
|
137
|
+
end
|
123
138
|
raise GitDependencyReferenceNotFound, name
|
124
139
|
end
|
125
140
|
|
@@ -130,7 +145,8 @@ module Dependabot
|
|
130
145
|
end
|
131
146
|
|
132
147
|
raise unless error.message.include?("SolverProblemError") ||
|
133
|
-
error.message.include?("PackageNotFound")
|
148
|
+
error.message.include?("PackageNotFound") ||
|
149
|
+
error.message.include?("version solving failed.")
|
134
150
|
|
135
151
|
check_original_requirements_resolvable
|
136
152
|
|
@@ -161,7 +177,8 @@ module Dependabot
|
|
161
177
|
@original_reqs_resolvable = true
|
162
178
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
163
179
|
raise unless e.message.include?("SolverProblemError") ||
|
164
|
-
e.message.include?("PackageNotFound")
|
180
|
+
e.message.include?("PackageNotFound") ||
|
181
|
+
e.message.include?("version solving failed.")
|
165
182
|
|
166
183
|
msg = clean_error_message(e.message)
|
167
184
|
raise DependencyFileNotResolvable, msg
|
@@ -214,9 +231,9 @@ module Dependabot
|
|
214
231
|
end
|
215
232
|
return version if version
|
216
233
|
|
217
|
-
msg = "Dependabot detected the following Python requirements "\
|
218
|
-
"for your project: '#{requirements}'.\n\nCurrently, the "\
|
219
|
-
"following Python versions are supported in Dependabot: "\
|
234
|
+
msg = "Dependabot detected the following Python requirements " \
|
235
|
+
"for your project: '#{requirements}'.\n\nCurrently, the " \
|
236
|
+
"following Python versions are supported in Dependabot: " \
|
220
237
|
"#{PythonVersions::SUPPORTED_VERSIONS.join(', ')}."
|
221
238
|
raise DependencyFileNotResolvable, msg
|
222
239
|
end
|
@@ -260,7 +260,7 @@ module Dependabot
|
|
260
260
|
# Updates the version in a constraint to be the given version
|
261
261
|
def bump_version(req_string, version_to_be_permitted)
|
262
262
|
old_version = req_string.
|
263
|
-
match(/(#{RequirementParser::VERSION})/).
|
263
|
+
match(/(#{RequirementParser::VERSION})/o).
|
264
264
|
captures.first
|
265
265
|
|
266
266
|
req_string.sub(
|
@@ -132,7 +132,6 @@ module Dependabot
|
|
132
132
|
resolver.resolvable?(version: fix_version) ? fix_version : nil
|
133
133
|
end
|
134
134
|
|
135
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
136
135
|
def resolver_type
|
137
136
|
reqs = dependency.requirements
|
138
137
|
req_files = reqs.map { |r| r.fetch(:file) }
|
@@ -144,8 +143,8 @@ module Dependabot
|
|
144
143
|
|
145
144
|
# Otherwise, this is a top-level dependency, and we can figure out
|
146
145
|
# which resolver to use based on the filename of its requirements
|
147
|
-
return :pipenv if req_files.any?
|
148
|
-
return :poetry if req_files.any?
|
146
|
+
return :pipenv if req_files.any?("Pipfile")
|
147
|
+
return :poetry if req_files.any?("pyproject.toml")
|
149
148
|
return :pip_compile if req_files.any? { |f| f.end_with?(".in") }
|
150
149
|
|
151
150
|
if dependency.version && !exact_requirement?(reqs)
|
@@ -154,7 +153,6 @@ module Dependabot
|
|
154
153
|
:requirements
|
155
154
|
end
|
156
155
|
end
|
157
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
158
156
|
|
159
157
|
def subdependency_resolver
|
160
158
|
return :pipenv if pipfile_lock
|
@@ -238,7 +236,7 @@ module Dependabot
|
|
238
236
|
return ">= #{dependency.version}" if dependency.version
|
239
237
|
|
240
238
|
version_for_requirement =
|
241
|
-
dependency.requirements.
|
239
|
+
dependency.requirements.filter_map { |r| r[:requirement] }.
|
242
240
|
reject { |req_string| req_string.start_with?("<") }.
|
243
241
|
select { |req_string| req_string.match?(VERSION_REGEX) }.
|
244
242
|
map { |req_string| req_string.match(VERSION_REGEX) }.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-python
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.212.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dependabot-common
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.212.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.212.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: debase
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '2.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: parallel_tests
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 3.12.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 3.12.0
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: rake
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +142,28 @@ dependencies:
|
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: 1.
|
145
|
+
version: 1.36.0
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 1.36.0
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rubocop-performance
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 1.14.2
|
132
160
|
type: :development
|
133
161
|
prerelease: false
|
134
162
|
version_requirements: !ruby/object:Gem::Requirement
|
135
163
|
requirements:
|
136
164
|
- - "~>"
|
137
165
|
- !ruby/object:Gem::Version
|
138
|
-
version: 1.
|
166
|
+
version: 1.14.2
|
139
167
|
- !ruby/object:Gem::Dependency
|
140
168
|
name: ruby-debug-ide
|
141
169
|
requirement: !ruby/object:Gem::Requirement
|