dependabot-core 0.78.0 → 0.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/helpers/npm/lib/updater.js +11 -5
- data/helpers/npm/package.json +2 -2
- data/helpers/npm/yarn.lock +26 -28
- data/helpers/yarn/lib/replace-lockfile-declaration.js +15 -3
- data/helpers/yarn/lib/updater.js +17 -5
- data/helpers/yarn/package.json +2 -2
- data/helpers/yarn/yarn.lock +24 -31
- data/lib/dependabot/file_fetchers.rb +0 -2
- data/lib/dependabot/file_parsers.rb +0 -2
- data/lib/dependabot/file_updaters.rb +0 -2
- data/lib/dependabot/metadata_finders.rb +0 -2
- data/lib/dependabot/update_checkers.rb +0 -2
- data/lib/dependabot/utils.rb +0 -4
- data/lib/dependabot/version.rb +1 -1
- metadata +3 -34
- data/helpers/python/lib/__init__.py +0 -0
- data/helpers/python/lib/hasher.py +0 -23
- data/helpers/python/lib/parser.py +0 -130
- data/helpers/python/requirements.txt +0 -9
- data/helpers/python/run.py +0 -18
- data/lib/dependabot/file_fetchers/python/pip.rb +0 -305
- data/lib/dependabot/file_parsers/python/pip.rb +0 -223
- data/lib/dependabot/file_parsers/python/pip/pipfile_files_parser.rb +0 -154
- data/lib/dependabot/file_parsers/python/pip/poetry_files_parser.rb +0 -141
- data/lib/dependabot/file_parsers/python/pip/setup_file_parser.rb +0 -164
- data/lib/dependabot/file_updaters/python/pip.rb +0 -147
- data/lib/dependabot/file_updaters/python/pip/pip_compile_file_updater.rb +0 -363
- data/lib/dependabot/file_updaters/python/pip/pipfile_file_updater.rb +0 -397
- data/lib/dependabot/file_updaters/python/pip/pipfile_preparer.rb +0 -125
- data/lib/dependabot/file_updaters/python/pip/poetry_file_updater.rb +0 -289
- data/lib/dependabot/file_updaters/python/pip/pyproject_preparer.rb +0 -105
- data/lib/dependabot/file_updaters/python/pip/requirement_file_updater.rb +0 -166
- data/lib/dependabot/file_updaters/python/pip/requirement_replacer.rb +0 -95
- data/lib/dependabot/file_updaters/python/pip/setup_file_sanitizer.rb +0 -91
- data/lib/dependabot/file_updaters/ruby/.DS_Store +0 -0
- data/lib/dependabot/metadata_finders/python/pip.rb +0 -120
- data/lib/dependabot/update_checkers/python/pip.rb +0 -227
- data/lib/dependabot/update_checkers/python/pip/latest_version_finder.rb +0 -252
- data/lib/dependabot/update_checkers/python/pip/pip_compile_version_resolver.rb +0 -380
- data/lib/dependabot/update_checkers/python/pip/pipfile_version_resolver.rb +0 -559
- data/lib/dependabot/update_checkers/python/pip/poetry_version_resolver.rb +0 -300
- data/lib/dependabot/update_checkers/python/pip/requirements_updater.rb +0 -367
- data/lib/dependabot/utils/python/requirement.rb +0 -130
- data/lib/dependabot/utils/python/version.rb +0 -88
- data/lib/python_requirement_parser.rb +0 -33
- data/lib/python_versions.rb +0 -21
@@ -1,95 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "python_requirement_parser"
|
4
|
-
require "dependabot/file_updaters/python/pip"
|
5
|
-
require "dependabot/shared_helpers"
|
6
|
-
|
7
|
-
module Dependabot
|
8
|
-
module FileUpdaters
|
9
|
-
module Python
|
10
|
-
class Pip
|
11
|
-
class RequirementReplacer
|
12
|
-
attr_reader :content, :dependency_name, :old_requirement,
|
13
|
-
:new_requirement
|
14
|
-
|
15
|
-
def initialize(content:, dependency_name:, old_requirement:,
|
16
|
-
new_requirement:)
|
17
|
-
@content = content
|
18
|
-
@dependency_name = dependency_name
|
19
|
-
@old_requirement = old_requirement
|
20
|
-
@new_requirement = new_requirement
|
21
|
-
end
|
22
|
-
|
23
|
-
def updated_content
|
24
|
-
updated_content =
|
25
|
-
content.gsub(original_declaration_replacement_regex) do |mtch|
|
26
|
-
# If the "declaration" is setting an option (e.g., no-binary)
|
27
|
-
# ignore it, since it isn't actually a declaration
|
28
|
-
next mtch if Regexp.last_match.pre_match.match?(/--.*\z/)
|
29
|
-
|
30
|
-
updated_dependency_declaration_string(
|
31
|
-
old_requirement,
|
32
|
-
new_requirement
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
raise "Expected content to change!" if content == updated_content
|
37
|
-
|
38
|
-
updated_content
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def original_dependency_declaration_string(old_req)
|
44
|
-
matches = []
|
45
|
-
|
46
|
-
dec =
|
47
|
-
if old_req.nil?
|
48
|
-
regex = PythonRequirementParser::INSTALL_REQ_WITHOUT_REQUIREMENT
|
49
|
-
content.scan(regex) { matches << Regexp.last_match }
|
50
|
-
matches.find { |m| normalise(m[:name]) == dependency_name }
|
51
|
-
else
|
52
|
-
regex = PythonRequirementParser::INSTALL_REQ_WITH_REQUIREMENT
|
53
|
-
content.scan(regex) { matches << Regexp.last_match }
|
54
|
-
matches.
|
55
|
-
select { |m| normalise(m[:name]) == dependency_name }.
|
56
|
-
find { |m| requirements_match(m[:requirements], old_req) }
|
57
|
-
end
|
58
|
-
|
59
|
-
raise "Declaration not found for #{dependency_name}!" unless dec
|
60
|
-
|
61
|
-
dec.to_s.strip
|
62
|
-
end
|
63
|
-
|
64
|
-
def updated_dependency_declaration_string(old_req, new_req)
|
65
|
-
if old_req
|
66
|
-
original_dependency_declaration_string(old_req).
|
67
|
-
sub(PythonRequirementParser::REQUIREMENTS, new_req)
|
68
|
-
else
|
69
|
-
original_dependency_declaration_string(old_req).
|
70
|
-
sub(PythonRequirementParser::NAME_WITH_EXTRAS) do |nm|
|
71
|
-
nm + new_req
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def original_declaration_replacement_regex
|
77
|
-
original_string =
|
78
|
-
original_dependency_declaration_string(old_requirement)
|
79
|
-
/(?<![\-\w\.])#{Regexp.escape(original_string)}(?![\-\w\.])/
|
80
|
-
end
|
81
|
-
|
82
|
-
# See https://www.python.org/dev/peps/pep-0503/#normalized-names
|
83
|
-
def normalise(name)
|
84
|
-
name.downcase.gsub(/[-_.]+/, "-")
|
85
|
-
end
|
86
|
-
|
87
|
-
def requirements_match(req1, req2)
|
88
|
-
req1&.split(",")&.map { |r| r.gsub(/\s/, "") }&.sort ==
|
89
|
-
req2&.split(",")&.map { |r| r.gsub(/\s/, "") }&.sort
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "dependabot/file_updaters/python/pip"
|
4
|
-
require "dependabot/file_parsers/python/pip/setup_file_parser"
|
5
|
-
|
6
|
-
module Dependabot
|
7
|
-
module FileUpdaters
|
8
|
-
module Python
|
9
|
-
class Pip
|
10
|
-
# Take a setup.py, parses it (carefully!) and then create a new, clean
|
11
|
-
# setup.py using only the information which will appear in the lockfile.
|
12
|
-
class SetupFileSanitizer
|
13
|
-
def initialize(setup_file:, setup_cfg:)
|
14
|
-
@setup_file = setup_file
|
15
|
-
@setup_cfg = setup_cfg
|
16
|
-
end
|
17
|
-
|
18
|
-
def sanitized_content
|
19
|
-
# The part of the setup.py that Pipenv cares about appears to be the
|
20
|
-
# install_requires. A name and version are required by don't end up
|
21
|
-
# in the lockfile.
|
22
|
-
content =
|
23
|
-
"from setuptools import setup\n\n"\
|
24
|
-
"setup(name=\"sanitized-package\",version=\"0.0.1\","\
|
25
|
-
"install_requires=#{install_requires_array.to_json},"\
|
26
|
-
"extras_require=#{extras_require_hash.to_json}"
|
27
|
-
|
28
|
-
content += ',setup_requires=["pbr"],pbr=True' if include_pbr?
|
29
|
-
content + ")"
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
attr_reader :setup_file, :setup_cfg
|
35
|
-
|
36
|
-
def include_pbr?
|
37
|
-
setup_requires_array.any? { |d| d.start_with?("pbr") }
|
38
|
-
end
|
39
|
-
|
40
|
-
def install_requires_array
|
41
|
-
@install_requires_array ||=
|
42
|
-
parsed_setup_file.dependencies.map do |dep|
|
43
|
-
next unless dep.requirements.first[:groups].
|
44
|
-
include?("install_requires")
|
45
|
-
|
46
|
-
dep.name + dep.requirements.first[:requirement].to_s
|
47
|
-
end.compact
|
48
|
-
end
|
49
|
-
|
50
|
-
def setup_requires_array
|
51
|
-
@setup_requires_array ||=
|
52
|
-
parsed_setup_file.dependencies.map do |dep|
|
53
|
-
next unless dep.requirements.first[:groups].
|
54
|
-
include?("setup_requires")
|
55
|
-
|
56
|
-
dep.name + dep.requirements.first[:requirement].to_s
|
57
|
-
end.compact
|
58
|
-
end
|
59
|
-
|
60
|
-
def extras_require_hash
|
61
|
-
@extras_require_hash ||=
|
62
|
-
begin
|
63
|
-
hash = {}
|
64
|
-
parsed_setup_file.dependencies.each do |dep|
|
65
|
-
dep.requirements.first[:groups].each do |group|
|
66
|
-
next unless group.start_with?("extras_require:")
|
67
|
-
|
68
|
-
hash[group.split(":").last] ||= []
|
69
|
-
hash[group.split(":").last] <<
|
70
|
-
dep.name + dep.requirements.first[:requirement].to_s
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
hash
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def parsed_setup_file
|
79
|
-
@parsed_setup_file ||=
|
80
|
-
FileParsers::Python::Pip::SetupFileParser.new(
|
81
|
-
dependency_files: [
|
82
|
-
setup_file&.dup&.tap { |f| f.name = "setup.py" },
|
83
|
-
setup_cfg&.dup&.tap { |f| f.name = "setup.cfg" }
|
84
|
-
].compact
|
85
|
-
).dependency_set
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
Binary file
|
@@ -1,120 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "excon"
|
4
|
-
require "dependabot/metadata_finders/base"
|
5
|
-
require "dependabot/shared_helpers"
|
6
|
-
|
7
|
-
module Dependabot
|
8
|
-
module MetadataFinders
|
9
|
-
module Python
|
10
|
-
class Pip < Dependabot::MetadataFinders::Base
|
11
|
-
MAIN_PYPI_URL = "https://pypi.org/pypi"
|
12
|
-
|
13
|
-
def homepage_url
|
14
|
-
pypi_listing.dig("info", "home_page") || super
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def look_up_source
|
20
|
-
potential_source_urls = [
|
21
|
-
pypi_listing.dig("info", "home_page"),
|
22
|
-
pypi_listing.dig("info", "bugtrack_url"),
|
23
|
-
pypi_listing.dig("info", "download_url"),
|
24
|
-
pypi_listing.dig("info", "docs_url")
|
25
|
-
].compact
|
26
|
-
|
27
|
-
source_url = potential_source_urls.find { |url| Source.from_url(url) }
|
28
|
-
source_url ||= source_from_description
|
29
|
-
source_url ||= source_from_homepage
|
30
|
-
|
31
|
-
Source.from_url(source_url)
|
32
|
-
end
|
33
|
-
|
34
|
-
def source_from_description
|
35
|
-
github_urls = []
|
36
|
-
desc = pypi_listing.dig("info", "description")
|
37
|
-
return unless desc
|
38
|
-
|
39
|
-
desc.scan(Source::SOURCE_REGEX) do
|
40
|
-
github_urls << Regexp.last_match.to_s
|
41
|
-
end
|
42
|
-
|
43
|
-
github_urls.find do |url|
|
44
|
-
repo = Source.from_url(url).repo
|
45
|
-
repo.downcase.end_with?(dependency.name)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def source_from_homepage
|
50
|
-
return unless homepage_body
|
51
|
-
|
52
|
-
github_urls = []
|
53
|
-
homepage_body.scan(Source::SOURCE_REGEX) do
|
54
|
-
github_urls << Regexp.last_match.to_s
|
55
|
-
end
|
56
|
-
|
57
|
-
github_urls.find do |url|
|
58
|
-
repo = Source.from_url(url).repo
|
59
|
-
repo.downcase.end_with?(dependency.name)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def homepage_body
|
64
|
-
homepage_url = pypi_listing.dig("info", "home_page")
|
65
|
-
|
66
|
-
return unless homepage_url
|
67
|
-
return if homepage_url.include?("pypi.python.org")
|
68
|
-
return if homepage_url.include?("pypi.org")
|
69
|
-
|
70
|
-
@homepage_response ||=
|
71
|
-
begin
|
72
|
-
Excon.get(
|
73
|
-
homepage_url,
|
74
|
-
idempotent: true,
|
75
|
-
**SharedHelpers.excon_defaults
|
76
|
-
)
|
77
|
-
rescue Excon::Error::Timeout, Excon::Error::Socket, ArgumentError
|
78
|
-
nil
|
79
|
-
end
|
80
|
-
|
81
|
-
return unless @homepage_response&.status == 200
|
82
|
-
|
83
|
-
@homepage_response.body
|
84
|
-
end
|
85
|
-
|
86
|
-
def pypi_listing
|
87
|
-
return @pypi_listing unless @pypi_listing.nil?
|
88
|
-
return @pypi_listing = {} if dependency.version.include?("+")
|
89
|
-
|
90
|
-
possible_listing_urls.each do |url|
|
91
|
-
response = Excon.get(
|
92
|
-
url,
|
93
|
-
idempotent: true,
|
94
|
-
**SharedHelpers.excon_defaults
|
95
|
-
)
|
96
|
-
next unless response.status == 200
|
97
|
-
|
98
|
-
@pypi_listing = JSON.parse(response.body)
|
99
|
-
return @pypi_listing
|
100
|
-
rescue JSON::ParserError
|
101
|
-
next
|
102
|
-
end
|
103
|
-
|
104
|
-
@pypi_listing = {} # No listing found
|
105
|
-
end
|
106
|
-
|
107
|
-
def possible_listing_urls
|
108
|
-
credential_urls =
|
109
|
-
credentials.
|
110
|
-
select { |cred| cred["type"] == "python_index" }.
|
111
|
-
map { |cred| cred["index-url"].gsub(%r{/$}, "") }
|
112
|
-
|
113
|
-
(credential_urls + [MAIN_PYPI_URL]).map do |base_url|
|
114
|
-
base_url + "/#{dependency.name}/json"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
@@ -1,227 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "excon"
|
4
|
-
require "toml-rb"
|
5
|
-
|
6
|
-
require "python_requirement_parser"
|
7
|
-
require "dependabot/update_checkers/base"
|
8
|
-
require "dependabot/shared_helpers"
|
9
|
-
require "dependabot/utils/python/requirement"
|
10
|
-
|
11
|
-
module Dependabot
|
12
|
-
module UpdateCheckers
|
13
|
-
module Python
|
14
|
-
class Pip < Dependabot::UpdateCheckers::Base
|
15
|
-
require_relative "pip/poetry_version_resolver"
|
16
|
-
require_relative "pip/pipfile_version_resolver"
|
17
|
-
require_relative "pip/pip_compile_version_resolver"
|
18
|
-
require_relative "pip/requirements_updater"
|
19
|
-
require_relative "pip/latest_version_finder"
|
20
|
-
|
21
|
-
MAIN_PYPI_INDEXES = %w(
|
22
|
-
https://pypi.python.org/simple/
|
23
|
-
https://pypi.org/simple/
|
24
|
-
).freeze
|
25
|
-
|
26
|
-
def latest_version
|
27
|
-
@latest_version ||= fetch_latest_version
|
28
|
-
end
|
29
|
-
|
30
|
-
def latest_resolvable_version
|
31
|
-
@latest_resolvable_version ||=
|
32
|
-
case resolver_type
|
33
|
-
when :pipfile
|
34
|
-
PipfileVersionResolver.new(
|
35
|
-
resolver_args.merge(unlock_requirement: true)
|
36
|
-
).latest_resolvable_version
|
37
|
-
when :poetry
|
38
|
-
PoetryVersionResolver.new(
|
39
|
-
resolver_args.merge(unlock_requirement: true)
|
40
|
-
).latest_resolvable_version
|
41
|
-
when :pip_compile
|
42
|
-
PipCompileVersionResolver.new(
|
43
|
-
resolver_args.merge(unlock_requirement: true)
|
44
|
-
).latest_resolvable_version
|
45
|
-
when :requirements
|
46
|
-
# pip doesn't (yet) do any dependency resolution, so if we don't
|
47
|
-
# have a Pipfile or a pip-compile file, we just return the latest
|
48
|
-
# version.
|
49
|
-
latest_version
|
50
|
-
else raise "Unexpected resolver type #{resolver_type}"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def latest_resolvable_version_with_no_unlock
|
55
|
-
@latest_resolvable_version_with_no_unlock ||=
|
56
|
-
case resolver_type
|
57
|
-
when :pipfile
|
58
|
-
PipfileVersionResolver.new(
|
59
|
-
resolver_args.merge(unlock_requirement: false)
|
60
|
-
).latest_resolvable_version
|
61
|
-
when :poetry
|
62
|
-
PoetryVersionResolver.new(
|
63
|
-
resolver_args.merge(unlock_requirement: false)
|
64
|
-
).latest_resolvable_version
|
65
|
-
when :pip_compile
|
66
|
-
PipCompileVersionResolver.new(
|
67
|
-
resolver_args.merge(unlock_requirement: false)
|
68
|
-
).latest_resolvable_version
|
69
|
-
when :requirements
|
70
|
-
latest_pip_version_with_no_unlock
|
71
|
-
else raise "Unexpected resolver type #{resolver_type}"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def updated_requirements
|
76
|
-
RequirementsUpdater.new(
|
77
|
-
requirements: dependency.requirements,
|
78
|
-
latest_version: latest_version&.to_s,
|
79
|
-
latest_resolvable_version: latest_resolvable_version&.to_s,
|
80
|
-
update_strategy: requirements_update_strategy,
|
81
|
-
has_lockfile: !(pipfile_lock || poetry_lock || pyproject_lock).nil?
|
82
|
-
).updated_requirements
|
83
|
-
end
|
84
|
-
|
85
|
-
def requirements_update_strategy
|
86
|
-
# If passed in as an option (in the base class) honour that option
|
87
|
-
if @requirements_update_strategy
|
88
|
-
return @requirements_update_strategy.to_sym
|
89
|
-
end
|
90
|
-
|
91
|
-
# Otherwise, check if this is a poetry library or not
|
92
|
-
poetry_library? ? :widen_ranges : :bump_versions
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def latest_version_resolvable_with_full_unlock?
|
98
|
-
# Full unlock checks aren't implemented for pip because they're not
|
99
|
-
# relevant (pip doesn't have a resolver). This method always returns
|
100
|
-
# false to ensure `updated_dependencies_after_full_unlock` is never
|
101
|
-
# called.
|
102
|
-
false
|
103
|
-
end
|
104
|
-
|
105
|
-
def updated_dependencies_after_full_unlock
|
106
|
-
raise NotImplementedError
|
107
|
-
end
|
108
|
-
|
109
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
110
|
-
def resolver_type
|
111
|
-
reqs = dependency.requirements
|
112
|
-
req_files = reqs.map { |r| r.fetch(:file) }
|
113
|
-
|
114
|
-
# If there are no requirements then this is a sub-dependency. It
|
115
|
-
# must come from one of Pipenv, Poetry or pip-tools, and can't come
|
116
|
-
# from the first two unless they have a lockfile.
|
117
|
-
return subdependency_resolver if reqs.none?
|
118
|
-
|
119
|
-
# Otherwise, this is a top-level dependency, and we can figure out
|
120
|
-
# which resolver to use based on the filename of its requirements
|
121
|
-
return :pipfile if req_files.any? { |f| f == "Pipfile" }
|
122
|
-
return :poetry if req_files.any? { |f| f == "pyproject.toml" }
|
123
|
-
return :pip_compile if req_files.any? { |f| f.end_with?(".in") }
|
124
|
-
|
125
|
-
if dependency.version && !exact_requirement?(reqs)
|
126
|
-
subdependency_resolver
|
127
|
-
else
|
128
|
-
:requirements
|
129
|
-
end
|
130
|
-
end
|
131
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
132
|
-
|
133
|
-
def subdependency_resolver
|
134
|
-
return :pipfile if pipfile_lock
|
135
|
-
return :poetry if poetry_lock || pyproject_lock
|
136
|
-
return :pip_compile if pip_compile_files.any?
|
137
|
-
|
138
|
-
raise "Claimed to be a sub-dependency, but no lockfile exists!"
|
139
|
-
end
|
140
|
-
|
141
|
-
def exact_requirement?(reqs)
|
142
|
-
reqs = reqs.map { |r| r.fetch(:requirement) }
|
143
|
-
reqs = reqs.compact
|
144
|
-
reqs = reqs.flat_map { |r| r.split(",").map(&:strip) }
|
145
|
-
reqs.any? { |r| Utils::Python::Requirement.new(r).exact? }
|
146
|
-
end
|
147
|
-
|
148
|
-
def resolver_args
|
149
|
-
{
|
150
|
-
dependency: dependency,
|
151
|
-
dependency_files: dependency_files,
|
152
|
-
credentials: credentials,
|
153
|
-
latest_allowable_version: latest_version
|
154
|
-
}
|
155
|
-
end
|
156
|
-
|
157
|
-
def fetch_latest_version
|
158
|
-
latest_version_finder.latest_version
|
159
|
-
end
|
160
|
-
|
161
|
-
def latest_pip_version_with_no_unlock
|
162
|
-
latest_version_finder.latest_version_with_no_unlock
|
163
|
-
end
|
164
|
-
|
165
|
-
def latest_version_finder
|
166
|
-
@latest_version_finder ||= LatestVersionFinder.new(
|
167
|
-
dependency: dependency,
|
168
|
-
dependency_files: dependency_files,
|
169
|
-
credentials: credentials,
|
170
|
-
ignored_versions: ignored_versions
|
171
|
-
)
|
172
|
-
end
|
173
|
-
|
174
|
-
def poetry_library?
|
175
|
-
return false unless pyproject
|
176
|
-
|
177
|
-
# Hit PyPi and check whether there are details for a library with a
|
178
|
-
# matching name and description
|
179
|
-
details = TomlRB.parse(pyproject.content).dig("tool", "poetry")
|
180
|
-
return false unless details
|
181
|
-
|
182
|
-
index_response = Excon.get(
|
183
|
-
"https://pypi.org/pypi/#{normalised_name(details['name'])}/json",
|
184
|
-
idempotent: true,
|
185
|
-
**SharedHelpers.excon_defaults
|
186
|
-
)
|
187
|
-
|
188
|
-
return false unless index_response.status == 200
|
189
|
-
|
190
|
-
pypi_info = JSON.parse(index_response.body)["info"] || {}
|
191
|
-
pypi_info["summary"] == details["description"]
|
192
|
-
rescue URI::InvalidURIError
|
193
|
-
false
|
194
|
-
end
|
195
|
-
|
196
|
-
# See https://www.python.org/dev/peps/pep-0503/#normalized-names
|
197
|
-
def normalised_name(name)
|
198
|
-
name.downcase.gsub(/[-_.]+/, "-")
|
199
|
-
end
|
200
|
-
|
201
|
-
def pipfile
|
202
|
-
dependency_files.find { |f| f.name == "Pipfile" }
|
203
|
-
end
|
204
|
-
|
205
|
-
def pipfile_lock
|
206
|
-
dependency_files.find { |f| f.name == "Pipfile.lock" }
|
207
|
-
end
|
208
|
-
|
209
|
-
def pyproject
|
210
|
-
dependency_files.find { |f| f.name == "pyproject.toml" }
|
211
|
-
end
|
212
|
-
|
213
|
-
def pyproject_lock
|
214
|
-
dependency_files.find { |f| f.name == "pyproject.lock" }
|
215
|
-
end
|
216
|
-
|
217
|
-
def poetry_lock
|
218
|
-
dependency_files.find { |f| f.name == "poetry.lock" }
|
219
|
-
end
|
220
|
-
|
221
|
-
def pip_compile_files
|
222
|
-
dependency_files.select { |f| f.name.end_with?(".in") }
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|