dependabot-python 0.108.19 → 0.108.21

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: 5e0f7ee1df3e5d469f00a05bd8b7806c2204279f97e1394f6d3be2442c26c6f0
4
- data.tar.gz: b34a290ea0a8748858fdb22292961d72ad0b3eb97868c4ead1054a5aaf7ea79d
3
+ metadata.gz: 854e1401da6d4347a3ee43320ad1c92c6f74c54794f456722b2914453947c1ff
4
+ data.tar.gz: adba97d1c4efb823a34c46bea97569f09aa34bb3a3b1ec7aa9db76df93923a81
5
5
  SHA512:
6
- metadata.gz: a91f8ce18580038e1e6de4d0889fa848287a1accd8c457b23568f8f0ca65be411872284af5bace3be7fcb23f4531a922d9b373fd803061442391ae4e6cc25d16
7
- data.tar.gz: b83afaac5e110ebc65b60454a58bc0256100899e39571b5c165ad0fa6fe774dc0452851ee5aa86b6641d5223bdaa83a41de687d0a245c3dbac5e70e8a6c42a03
6
+ metadata.gz: 2afd4503cc8f06a7a445a8dc48cb67510adceda5711588c4d44434094427921665cdf76408b443b3451c2f824323cb50391b8f0fa7443026f7a74211d42878fb
7
+ data.tar.gz: 5720f061637253c91d2fae8408c03607b9b47e16a88365dc6f98537a120a582b08f950d0d77b509b7bbb4b6a08e696902081d59f6181157d9341bfff82fe1c34
@@ -11,11 +11,12 @@ module Dependabot
11
11
  module Python
12
12
  class FileParser
13
13
  class SetupFileParser
14
- INSTALL_REQUIRES_REGEX =
15
- /install_requires\s*=\s*(\[.*?\])[,)\s]/m.freeze
16
- SETUP_REQUIRES_REGEX = /setup_requires\s*=\s*(\[.*?\])[,)\s]/m.freeze
17
- TESTS_REQUIRE_REGEX = /tests_require\s*=\s*(\[.*?\])[,)\s]/m.freeze
18
- EXTRAS_REQUIRE_REGEX = /extras_require\s*=\s*(\{.*?\})[,)\s]/m.freeze
14
+ INSTALL_REQUIRES_REGEX = /install_requires\s*=\s*\[/m.freeze
15
+ SETUP_REQUIRES_REGEX = /setup_requires\s*=\s*\[/m.freeze
16
+ TESTS_REQUIRE_REGEX = /tests_require\s*=\s*\[/m.freeze
17
+ EXTRAS_REQUIRE_REGEX = /extras_require\s*=\s*\{/m.freeze
18
+
19
+ CLOSING_BRACKET = { "[" => "]", "{" => "}" }.freeze
19
20
 
20
21
  def initialize(dependency_files:)
21
22
  @dependency_files = dependency_files
@@ -121,16 +122,10 @@ module Dependabot
121
122
  # entries are dynamic), but it is an alternative approach to the one
122
123
  # used in parser.py which sometimes succeeds when that has failed.
123
124
  def write_sanitized_setup_file
124
- original_content = setup_file.content
125
-
126
- install_requires =
127
- original_content.match(INSTALL_REQUIRES_REGEX)&.captures&.first
128
- setup_requires =
129
- original_content.match(SETUP_REQUIRES_REGEX)&.captures&.first
130
- tests_require =
131
- original_content.match(TESTS_REQUIRE_REGEX)&.captures&.first
132
- extras_require =
133
- original_content.match(EXTRAS_REQUIRE_REGEX)&.captures&.first
125
+ install_requires = get_regexed_req_array(INSTALL_REQUIRES_REGEX)
126
+ setup_requires = get_regexed_req_array(SETUP_REQUIRES_REGEX)
127
+ tests_require = get_regexed_req_array(TESTS_REQUIRE_REGEX)
128
+ extras_require = get_regexed_req_dict(EXTRAS_REQUIRE_REGEX)
134
129
 
135
130
  tmp = "from setuptools import setup\n\n"\
136
131
  "setup(name=\"sanitized-package\",version=\"0.0.1\","
@@ -144,6 +139,30 @@ module Dependabot
144
139
  File.write("setup.py", tmp)
145
140
  end
146
141
 
142
+ def get_regexed_req_array(regex)
143
+ return unless (mch = setup_file.content.match(regex))
144
+
145
+ "[#{mch.post_match[0..closing_bracket_index(mch.post_match, '[')]}"
146
+ end
147
+
148
+ def get_regexed_req_dict(regex)
149
+ return unless (mch = setup_file.content.match(regex))
150
+
151
+ "{#{mch.post_match[0..closing_bracket_index(mch.post_match, '{')]}"
152
+ end
153
+
154
+ def closing_bracket_index(string, bracket)
155
+ closes_required = 1
156
+
157
+ string.chars.each_with_index do |char, index|
158
+ closes_required += 1 if char == bracket
159
+ closes_required -= 1 if char == CLOSING_BRACKET.fetch(bracket)
160
+ return index if closes_required.zero?
161
+ end
162
+
163
+ 0
164
+ end
165
+
147
166
  # See https://www.python.org/dev/peps/pep-0503/#normalized-names
148
167
  def normalised_name(name)
149
168
  name.downcase.gsub(/[-_.]+/, "-")
@@ -446,6 +446,7 @@ module Dependabot
446
446
  options << "--no-header"
447
447
  end
448
448
 
449
+ options << "--pre" if requirements_file.content.include?("--pre")
449
450
  options.join(" ")
450
451
  end
451
452
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
3
4
  require "excon"
4
5
 
5
6
  require "dependabot/python/update_checker"
@@ -12,6 +13,9 @@ module Dependabot
12
13
  class LatestVersionFinder
13
14
  require_relative "index_finder"
14
15
 
16
+ PYTHON_REQUIREMENT_REGEX =
17
+ /data-requires-python\s*=\s*["'](?<requirement>[^"']+)["']/m.freeze
18
+
15
19
  def initialize(dependency:, dependency_files:, credentials:,
16
20
  ignored_versions:, security_advisories:)
17
21
  @dependency = dependency
@@ -21,17 +25,19 @@ module Dependabot
21
25
  @security_advisories = security_advisories
22
26
  end
23
27
 
24
- def latest_version
25
- @latest_version ||= fetch_latest_version
28
+ def latest_version(python_version: nil)
29
+ @latest_version ||=
30
+ fetch_latest_version(python_version: python_version)
26
31
  end
27
32
 
28
- def latest_version_with_no_unlock
33
+ def latest_version_with_no_unlock(python_version: nil)
29
34
  @latest_version_with_no_unlock ||=
30
- fetch_latest_version_with_no_unlock
35
+ fetch_latest_version_with_no_unlock(python_version: python_version)
31
36
  end
32
37
 
33
- def lowest_security_fix_version
34
- @lowest_security_fix_version ||= fetch_lowest_security_fix_version
38
+ def lowest_security_fix_version(python_version: nil)
39
+ @lowest_security_fix_version ||=
40
+ fetch_lowest_security_fix_version(python_version: python_version)
35
41
  end
36
42
 
37
43
  private
@@ -39,23 +45,26 @@ module Dependabot
39
45
  attr_reader :dependency, :dependency_files, :credentials,
40
46
  :ignored_versions, :security_advisories
41
47
 
42
- def fetch_latest_version
48
+ def fetch_latest_version(python_version:)
43
49
  versions = available_versions
50
+ versions = filter_unsupported_versions(versions, python_version)
44
51
  versions = filter_prerelease_versions(versions)
45
52
  versions = filter_ignored_versions(versions)
46
53
  versions.max
47
54
  end
48
55
 
49
- def fetch_latest_version_with_no_unlock
56
+ def fetch_latest_version_with_no_unlock(python_version:)
50
57
  versions = available_versions
58
+ versions = filter_unsupported_versions(versions, python_version)
51
59
  versions = filter_prerelease_versions(versions)
52
60
  versions = filter_ignored_versions(versions)
53
61
  versions = filter_out_of_range_versions(versions)
54
62
  versions.max
55
63
  end
56
64
 
57
- def fetch_lowest_security_fix_version
65
+ def fetch_lowest_security_fix_version(python_version:)
58
66
  versions = available_versions
67
+ versions = filter_unsupported_versions(versions, python_version)
59
68
  versions = filter_prerelease_versions(versions)
60
69
  versions = filter_ignored_versions(versions)
61
70
  versions = filter_vulnerable_versions(versions)
@@ -63,6 +72,17 @@ module Dependabot
63
72
  versions.min
64
73
  end
65
74
 
75
+ def filter_unsupported_versions(versions_array, python_version)
76
+ versions_array.map do |details|
77
+ python_requirement = details.fetch(:python_requirement)
78
+ next details.fetch(:version) unless python_version
79
+ next details.fetch(:version) unless python_requirement
80
+ next unless python_requirement.satisfied_by?(python_version)
81
+
82
+ details.fetch(:version)
83
+ end.compact
84
+ end
85
+
66
86
  def filter_prerelease_versions(versions_array)
67
87
  return versions_array if wants_prerelease?
68
88
 
@@ -118,19 +138,13 @@ module Dependabot
118
138
  raise PrivateSourceAuthenticationFailure, sanitized_url
119
139
  end
120
140
 
121
- index_response.body.
122
- scan(%r{<a\s.*?>(.*?)</a>}m).flatten.
123
- select { |n| n.match?(name_regex) }.
124
- map do |filename|
125
- version =
126
- filename.
127
- gsub(/#{name_regex}-/i, "").
128
- split(/-|\.tar\.|\.zip|\.whl/).
129
- first
130
- next unless version_class.correct?(version)
131
-
132
- version_class.new(version)
133
- end.compact
141
+ version_links = []
142
+ index_response.body.scan(%r{<a\s.*?>.*?</a>}m) do
143
+ details = version_details_from_link(Regexp.last_match.to_s)
144
+ version_links << details if details
145
+ end
146
+
147
+ version_links.compact
134
148
  rescue Excon::Error::Timeout, Excon::Error::Socket
135
149
  raise if MAIN_PYPI_INDEXES.include?(index_url)
136
150
 
@@ -138,6 +152,38 @@ module Dependabot
138
152
  end
139
153
  end
140
154
 
155
+ def version_details_from_link(link)
156
+ filename = link.match(%r{<a\s.*?>(.*?)</a>}).captures.first
157
+ return unless filename.match?(name_regex)
158
+
159
+ version = get_version_from_filename(filename)
160
+ return unless version_class.correct?(version)
161
+
162
+ {
163
+ version: version_class.new(version),
164
+ python_requirement: build_python_requirement_from_link(link)
165
+ }
166
+ end
167
+
168
+ def get_version_from_filename(filename)
169
+ filename.
170
+ gsub(/#{name_regex}-/i, "").
171
+ split(/-|\.tar\.|\.zip|\.whl/).
172
+ first
173
+ end
174
+
175
+ def build_python_requirement_from_link(link)
176
+ req_string = link.
177
+ match(PYTHON_REQUIREMENT_REGEX)&.
178
+ named_captures&.
179
+ fetch("requirement")
180
+ return unless req_string
181
+
182
+ requirement_class.new(CGI.unescapeHTML(req_string))
183
+ rescue Gem::Requirement::BadRequirementError
184
+ nil
185
+ end
186
+
141
187
  def index_urls
142
188
  @index_urls ||=
143
189
  IndexFinder.new(
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.108.19
4
+ version: 0.108.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-18 00:00:00.000000000 Z
11
+ date: 2019-06-22 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.108.19
19
+ version: 0.108.21
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.108.19
26
+ version: 0.108.21
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement