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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d12f6acdc73f229dcc3154fe50f5c2f2bdd74de5239948eceed2bd6f6f6c936
4
- data.tar.gz: 3085c1241c3cffdbc133fbafe9f79bba159198972b6824c54d94b0e977154680
3
+ metadata.gz: 4862b59513a97a33d51ff8ad57b6d9815842769c87f612426ffbcd8e75a9655c
4
+ data.tar.gz: 9543935b3ab8027344757b41aa8ff265d823beac956a06d20d4917e75962698d
5
5
  SHA512:
6
- metadata.gz: 70c2ff5b635dd88b44d6291d788efc93a702c1c73846cf69acc0a43ded441f57880cddd3c2a61d2e5a7bcf749a557b236c9b67d4f2690f8942c0117a2c8d01af
7
- data.tar.gz: 42d0b64bb8cb513b23a01a5f380add5e53fed90cb9534ec096b0906f04f1cba4754336fd91158fbb8218808d167a7894c60409bd35331edc4f23bc676662486e
6
+ metadata.gz: fd9e547d19f01addfdc2fcc4eeb7095bf8e886eded086772f81b9bfbd6acfb2fc6076c354c970ae5fad0691a25679d99db8eb0884121e986c1bcf39b17c041ba
7
+ data.tar.gz: be587fe031f132dd20d4fc023668e31d81c37608d915a9f586ca159b675302993a208b6e93209cfaedad83d08eaae1ca06f6af7eec8933bcc2c44e8a61293ccf
@@ -4,7 +4,7 @@ flake8==5.0.4
4
4
  hashin==0.17.0
5
5
  pipenv==2022.4.8
6
6
  pipfile==0.0.2
7
- poetry==1.1.14
7
+ poetry>=1.1.15,<=1.2.0
8
8
  wheel==0.37.1
9
9
 
10
10
  # Some dependencies will only install if Cython is present
@@ -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
- "or a Pipfile."
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
- %w(packages dev-packages).each do |dep_type|
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.map do |requirement|
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.compact
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 %w(directory git url).include?(details.dig("source", "type"))
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
- map { |l| l.match(/python_version(?<req>.*?["'].*?['"])/) }.
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.map do |file|
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.compact
105
+ end
106
106
  end
107
107
  end
108
108
 
109
109
  def update_manifest_files
110
- dependency_files.map do |file|
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.compact
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.map { |k| [k.to_sym, args[k]] }.to_h
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
- %w(packages dev-packages).each do |type|
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 %w(directory file url).include?(locked_details&.dig("source", "type"))
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.map do |(new_req, old_req)|
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.compact
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)/, '\1 ')
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.map do |dep|
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.compact
46
+ end
47
47
  end
48
48
 
49
49
  def setup_requires_array
50
50
  @setup_requires_array ||=
51
- parsed_setup_file.dependencies.map do |dep|
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.compact
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? { |f| f == "Pipfile" }
64
- return :poetry if changed_req_files.any? { |f| f == "pyproject.toml" }
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
@@ -12,7 +12,7 @@ module Dependabot
12
12
  end
13
13
 
14
14
  def self.python_helpers_dir
15
- File.join(native_helpers_root, "python/helpers")
15
+ File.join(native_helpers_root, "python")
16
16
  end
17
17
 
18
18
  def self.native_helpers_root
@@ -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.map do |details|
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.compact
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.map do |r|
121
+ reqs = dependency.requirements.filter_map do |r|
122
122
  requirement_class.requirements_array(r.fetch(:requirement))
123
- end.compact
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
- if [401, 403].include?(index_response.status) &&
150
- [401, 403].include?(registry_index_response(index_url).status)
151
- raise PrivateSourceAuthenticationFailure, sanitized_url
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
- "(see https://github.com/pypa/pipenv/issues/1050 for more "\
152
- "details)."
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
- %w(packages dev-packages).each do |type|
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
- /x.freeze
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
- '\['git',
32
- \s+'clone',
33
- \s+'--recurse-submodules',
34
- \s+'(--)?',
35
- \s+'(?<url>.+?)'.*
36
- \s+exit\s+status\s+128
37
- /mx.freeze
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
- name = message.match(GIT_REFERENCE_NOT_FOUND_REGEX).
122
- named_captures.fetch("name")
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? { |f| f == "Pipfile" }
148
- return :poetry if req_files.any? { |f| f == "pyproject.toml" }
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.map { |r| r[:requirement] }.compact.
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.209.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-08-17 00:00:00.000000000 Z
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.209.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.209.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.33.0
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.33.0
166
+ version: 1.14.2
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: ruby-debug-ide
141
169
  requirement: !ruby/object:Gem::Requirement