dependabot-core 0.78.0 → 0.79.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|