dependabot-python 0.211.0 → 0.212.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.
- 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 +22 -8
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
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.
|
89
|
+
version: 3.12.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.
|
96
|
+
version: 3.12.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +142,28 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 1.
|
145
|
+
version: 1.36.0
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 1.
|
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
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 1.14.2
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: ruby-debug-ide
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|