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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/helpers/npm/lib/updater.js +11 -5
  4. data/helpers/npm/package.json +2 -2
  5. data/helpers/npm/yarn.lock +26 -28
  6. data/helpers/yarn/lib/replace-lockfile-declaration.js +15 -3
  7. data/helpers/yarn/lib/updater.js +17 -5
  8. data/helpers/yarn/package.json +2 -2
  9. data/helpers/yarn/yarn.lock +24 -31
  10. data/lib/dependabot/file_fetchers.rb +0 -2
  11. data/lib/dependabot/file_parsers.rb +0 -2
  12. data/lib/dependabot/file_updaters.rb +0 -2
  13. data/lib/dependabot/metadata_finders.rb +0 -2
  14. data/lib/dependabot/update_checkers.rb +0 -2
  15. data/lib/dependabot/utils.rb +0 -4
  16. data/lib/dependabot/version.rb +1 -1
  17. metadata +3 -34
  18. data/helpers/python/lib/__init__.py +0 -0
  19. data/helpers/python/lib/hasher.py +0 -23
  20. data/helpers/python/lib/parser.py +0 -130
  21. data/helpers/python/requirements.txt +0 -9
  22. data/helpers/python/run.py +0 -18
  23. data/lib/dependabot/file_fetchers/python/pip.rb +0 -305
  24. data/lib/dependabot/file_parsers/python/pip.rb +0 -223
  25. data/lib/dependabot/file_parsers/python/pip/pipfile_files_parser.rb +0 -154
  26. data/lib/dependabot/file_parsers/python/pip/poetry_files_parser.rb +0 -141
  27. data/lib/dependabot/file_parsers/python/pip/setup_file_parser.rb +0 -164
  28. data/lib/dependabot/file_updaters/python/pip.rb +0 -147
  29. data/lib/dependabot/file_updaters/python/pip/pip_compile_file_updater.rb +0 -363
  30. data/lib/dependabot/file_updaters/python/pip/pipfile_file_updater.rb +0 -397
  31. data/lib/dependabot/file_updaters/python/pip/pipfile_preparer.rb +0 -125
  32. data/lib/dependabot/file_updaters/python/pip/poetry_file_updater.rb +0 -289
  33. data/lib/dependabot/file_updaters/python/pip/pyproject_preparer.rb +0 -105
  34. data/lib/dependabot/file_updaters/python/pip/requirement_file_updater.rb +0 -166
  35. data/lib/dependabot/file_updaters/python/pip/requirement_replacer.rb +0 -95
  36. data/lib/dependabot/file_updaters/python/pip/setup_file_sanitizer.rb +0 -91
  37. data/lib/dependabot/file_updaters/ruby/.DS_Store +0 -0
  38. data/lib/dependabot/metadata_finders/python/pip.rb +0 -120
  39. data/lib/dependabot/update_checkers/python/pip.rb +0 -227
  40. data/lib/dependabot/update_checkers/python/pip/latest_version_finder.rb +0 -252
  41. data/lib/dependabot/update_checkers/python/pip/pip_compile_version_resolver.rb +0 -380
  42. data/lib/dependabot/update_checkers/python/pip/pipfile_version_resolver.rb +0 -559
  43. data/lib/dependabot/update_checkers/python/pip/poetry_version_resolver.rb +0 -300
  44. data/lib/dependabot/update_checkers/python/pip/requirements_updater.rb +0 -367
  45. data/lib/dependabot/utils/python/requirement.rb +0 -130
  46. data/lib/dependabot/utils/python/version.rb +0 -88
  47. data/lib/python_requirement_parser.rb +0 -33
  48. data/lib/python_versions.rb +0 -21
@@ -1,223 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "toml-rb"
4
-
5
- require "dependabot/dependency"
6
- require "dependabot/file_parsers/base"
7
- require "dependabot/file_parsers/base/dependency_set"
8
- require "dependabot/shared_helpers"
9
- require "dependabot/utils/python/requirement"
10
- require "dependabot/errors"
11
-
12
- module Dependabot
13
- module FileParsers
14
- module Python
15
- class Pip < Dependabot::FileParsers::Base
16
- require_relative "pip/pipfile_files_parser"
17
- require_relative "pip/poetry_files_parser"
18
- require_relative "pip/setup_file_parser"
19
-
20
- POETRY_DEPENDENCY_TYPES =
21
- %w(tool.poetry.dependencies tool.poetry.dev-dependencies).freeze
22
- DEPENDENCY_GROUP_KEYS = [
23
- {
24
- pipfile: "packages",
25
- lockfile: "default"
26
- },
27
- {
28
- pipfile: "dev-packages",
29
- lockfile: "develop"
30
- }
31
- ].freeze
32
- REQUIREMENT_FILE_EVALUATION_ERRORS = %w(
33
- InstallationError RequirementsFileParseError InvalidMarker
34
- InvalidRequirement
35
- ).freeze
36
-
37
- def parse
38
- dependency_set = DependencySet.new
39
-
40
- dependency_set += pipenv_dependencies if pipfile
41
- dependency_set += poetry_dependencies if using_poetry?
42
- dependency_set += requirement_dependencies if requirement_files.any?
43
- dependency_set += setup_file_dependencies if setup_file
44
-
45
- dependency_set.dependencies
46
- end
47
-
48
- private
49
-
50
- def requirement_files
51
- dependency_files.select { |f| f.name.end_with?(".txt", ".in") }
52
- end
53
-
54
- def pipenv_dependencies
55
- @pipenv_dependencies ||=
56
- PipfileFilesParser.
57
- new(dependency_files: dependency_files).
58
- dependency_set
59
- end
60
-
61
- def poetry_dependencies
62
- @poetry_dependencies ||=
63
- PoetryFilesParser.
64
- new(dependency_files: dependency_files).
65
- dependency_set
66
- end
67
-
68
- def requirement_dependencies
69
- dependencies = DependencySet.new
70
- parsed_requirement_files.each do |dep|
71
- # This isn't ideal, but currently the FileUpdater won't update
72
- # deps that appear in a requirements.txt and Pipfile / Pipfile.lock
73
- # and *aren't* a straight lockfile for the Pipfile
74
- next if included_in_pipenv_deps?(normalised_name(dep["name"]))
75
-
76
- # If a requirement has a `<` or `<=` marker then updating it is
77
- # probably blocked. Ignore it.
78
- next if dep["markers"].include?("<")
79
-
80
- requirements =
81
- if lockfile_for_pip_compile_file?(dep["file"]) then []
82
- else
83
- [{
84
- requirement: dep["requirement"],
85
- file: Pathname.new(dep["file"]).cleanpath.to_path,
86
- source: nil,
87
- groups: []
88
- }]
89
- end
90
-
91
- dependencies <<
92
- Dependency.new(
93
- name: normalised_name(dep["name"]),
94
- version: dep["version"]&.include?("*") ? nil : dep["version"],
95
- requirements: requirements,
96
- package_manager: "pip"
97
- )
98
- end
99
- dependencies
100
- end
101
-
102
- def included_in_pipenv_deps?(dep_name)
103
- return false unless pipfile
104
-
105
- pipenv_dependencies.dependencies.map(&:name).include?(dep_name)
106
- end
107
-
108
- def setup_file_dependencies
109
- @setup_file_dependencies ||=
110
- SetupFileParser.
111
- new(dependency_files: dependency_files).
112
- dependency_set
113
- end
114
-
115
- def lockfile_for_pip_compile_file?(filename)
116
- return false unless pip_compile_files.any?
117
- return false unless filename.end_with?(".txt")
118
-
119
- basename = filename.gsub(/\.txt$/, "")
120
- pip_compile_files.any? { |f| f.name == basename + ".in" }
121
- end
122
-
123
- def parsed_requirement_files
124
- SharedHelpers.in_a_temporary_directory do
125
- write_temporary_dependency_files
126
-
127
- requirements = SharedHelpers.run_helper_subprocess(
128
- command: "pyenv exec python #{python_helper_path}",
129
- function: "parse_requirements",
130
- args: [Dir.pwd]
131
- )
132
-
133
- check_requirements(requirements)
134
- requirements
135
- end
136
- rescue SharedHelpers::HelperSubprocessFailed => error
137
- evaluation_errors = REQUIREMENT_FILE_EVALUATION_ERRORS
138
- raise unless error.message.start_with?(*evaluation_errors)
139
-
140
- raise Dependabot::DependencyFileNotEvaluatable, error.message
141
- end
142
-
143
- def check_requirements(requirements)
144
- requirements.each do |dep|
145
- next unless dep["requirement"]
146
-
147
- Utils::Python::Requirement.new(dep["requirement"].split(","))
148
- rescue Gem::Requirement::BadRequirementError => error
149
- raise Dependabot::DependencyFileNotEvaluatable, error.message
150
- end
151
- end
152
-
153
- def write_temporary_dependency_files
154
- dependency_files.
155
- reject { |f| f.name == ".python-version" }.
156
- each do |file|
157
- path = file.name
158
- FileUtils.mkdir_p(Pathname.new(path).dirname)
159
- File.write(path, file.content)
160
- end
161
- end
162
-
163
- def python_helper_path
164
- project_root = File.join(File.dirname(__FILE__), "../../../..")
165
- File.join(project_root, "helpers/python/run.py")
166
- end
167
-
168
- # See https://www.python.org/dev/peps/pep-0503/#normalized-names
169
- def normalised_name(name)
170
- name.downcase.gsub(/[-_.]+/, "-")
171
- end
172
-
173
- def check_required_files
174
- filenames = dependency_files.map(&:name)
175
- return if filenames.any? { |name| name.end_with?(".txt", ".in") }
176
- return if pipfile
177
- return if pyproject
178
- return if setup_file
179
-
180
- raise "No requirements.txt or setup.py!"
181
- end
182
-
183
- def pipfile
184
- @pipfile ||= get_original_file("Pipfile")
185
- end
186
-
187
- def pipfile_lock
188
- @pipfile_lock ||= get_original_file("Pipfile.lock")
189
- end
190
-
191
- def using_poetry?
192
- return false unless pyproject
193
- return true if poetry_lock || pyproject_lock
194
-
195
- !TomlRB.parse(pyproject.content).dig("tool", "poetry").nil?
196
- rescue TomlRB::ParseError
197
- raise Dependabot::DependencyFileNotParseable, pyproject.path
198
- end
199
-
200
- def pyproject
201
- @pyproject ||= get_original_file("pyproject.toml")
202
- end
203
-
204
- def pyproject_lock
205
- @pyproject_lock ||= get_original_file("pyproject.lock")
206
- end
207
-
208
- def poetry_lock
209
- @poetry_lock ||= get_original_file("poetry.lock")
210
- end
211
-
212
- def setup_file
213
- @setup_file ||= get_original_file("setup.py")
214
- end
215
-
216
- def pip_compile_files
217
- @pip_compile_files ||=
218
- dependency_files.select { |f| f.name.end_with?(".in") }
219
- end
220
- end
221
- end
222
- end
223
- end
@@ -1,154 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "toml-rb"
4
-
5
- require "dependabot/dependency"
6
- require "dependabot/file_parsers/base/dependency_set"
7
- require "dependabot/file_parsers/python/pip"
8
- require "dependabot/errors"
9
-
10
- module Dependabot
11
- module FileParsers
12
- module Python
13
- class Pip
14
- class PipfileFilesParser
15
- DEPENDENCY_GROUP_KEYS = [
16
- {
17
- pipfile: "packages",
18
- lockfile: "default"
19
- },
20
- {
21
- pipfile: "dev-packages",
22
- lockfile: "develop"
23
- }
24
- ].freeze
25
-
26
- def initialize(dependency_files:)
27
- @dependency_files = dependency_files
28
- end
29
-
30
- def dependency_set
31
- dependency_set = Dependabot::FileParsers::Base::DependencySet.new
32
-
33
- dependency_set += pipfile_dependencies
34
- dependency_set += pipfile_lock_dependencies
35
-
36
- dependency_set
37
- end
38
-
39
- private
40
-
41
- attr_reader :dependency_files
42
-
43
- def pipfile_dependencies
44
- dependencies = Dependabot::FileParsers::Base::DependencySet.new
45
-
46
- DEPENDENCY_GROUP_KEYS.each do |keys|
47
- next unless parsed_pipfile[keys[:pipfile]]
48
-
49
- parsed_pipfile[keys[:pipfile]].map do |dep_name, req|
50
- group = keys[:lockfile]
51
- next unless req.is_a?(String) || req["version"]
52
- if pipfile_lock && !dependency_version(dep_name, req, group)
53
- next
54
- end
55
-
56
- dependencies <<
57
- Dependency.new(
58
- name: normalised_name(dep_name),
59
- version: dependency_version(dep_name, req, group),
60
- requirements: [{
61
- requirement: req.is_a?(String) ? req : req["version"],
62
- file: pipfile.name,
63
- source: nil,
64
- groups: [group]
65
- }],
66
- package_manager: "pip"
67
- )
68
- end
69
- end
70
-
71
- dependencies
72
- end
73
-
74
- # Create a DependencySet where each element has no requirement. Any
75
- # requirements will be added when combining the DependencySet with
76
- # other DependencySets.
77
- def pipfile_lock_dependencies
78
- dependencies = Dependabot::FileParsers::Base::DependencySet.new
79
- return dependencies unless pipfile_lock
80
-
81
- DEPENDENCY_GROUP_KEYS.map { |h| h.fetch(:lockfile) }.each do |key|
82
- next unless parsed_pipfile_lock[key]
83
-
84
- parsed_pipfile_lock[key].each do |dep_name, details|
85
- version = case details
86
- when String then details
87
- when Hash then details["version"]
88
- end
89
- next unless version
90
-
91
- dependencies <<
92
- Dependency.new(
93
- name: dep_name,
94
- version: version&.gsub(/^===?/, ""),
95
- requirements: [],
96
- package_manager: "pip"
97
- )
98
- end
99
- end
100
-
101
- dependencies
102
- end
103
-
104
- def dependency_version(dep_name, requirement, group)
105
- req = version_from_hash_or_string(requirement)
106
-
107
- if pipfile_lock
108
- details = parsed_pipfile_lock.
109
- dig(group, normalised_name(dep_name))
110
-
111
- version = version_from_hash_or_string(details)
112
- version&.gsub(/^===?/, "")
113
- elsif req.start_with?("==") && !req.include?("*")
114
- req.strip.gsub(/^===?/, "")
115
- end
116
- end
117
-
118
- def version_from_hash_or_string(obj)
119
- case obj
120
- when String then obj.strip
121
- when Hash then obj["version"]
122
- end
123
- end
124
-
125
- # See https://www.python.org/dev/peps/pep-0503/#normalized-names
126
- def normalised_name(name)
127
- name.downcase.gsub(/[-_.]+/, "-")
128
- end
129
-
130
- def parsed_pipfile
131
- @parsed_pipfile ||= TomlRB.parse(pipfile.content)
132
- rescue TomlRB::ParseError
133
- raise Dependabot::DependencyFileNotParseable, pipfile.path
134
- end
135
-
136
- def parsed_pipfile_lock
137
- @parsed_pipfile_lock ||= JSON.parse(pipfile_lock.content)
138
- rescue JSON::ParserError
139
- raise Dependabot::DependencyFileNotParseable, pipfile_lock.path
140
- end
141
-
142
- def pipfile
143
- @pipfile ||= dependency_files.find { |f| f.name == "Pipfile" }
144
- end
145
-
146
- def pipfile_lock
147
- @pipfile_lock ||=
148
- dependency_files.find { |f| f.name == "Pipfile.lock" }
149
- end
150
- end
151
- end
152
- end
153
- end
154
- end
@@ -1,141 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "toml-rb"
4
-
5
- require "dependabot/dependency"
6
- require "dependabot/file_parsers/base/dependency_set"
7
- require "dependabot/file_parsers/python/pip"
8
- require "dependabot/errors"
9
-
10
- module Dependabot
11
- module FileParsers
12
- module Python
13
- class Pip
14
- class PoetryFilesParser
15
- POETRY_DEPENDENCY_TYPES = %w(dependencies dev-dependencies).freeze
16
-
17
- def initialize(dependency_files:)
18
- @dependency_files = dependency_files
19
- end
20
-
21
- def dependency_set
22
- dependency_set = Dependabot::FileParsers::Base::DependencySet.new
23
-
24
- dependency_set += pyproject_dependencies
25
- dependency_set += lockfile_dependencies if lockfile
26
-
27
- dependency_set
28
- end
29
-
30
- private
31
-
32
- attr_reader :dependency_files
33
-
34
- def pyproject_dependencies
35
- dependencies = Dependabot::FileParsers::Base::DependencySet.new
36
-
37
- POETRY_DEPENDENCY_TYPES.each do |type|
38
- deps_hash = parsed_pyproject.dig("tool", "poetry", type) || {}
39
-
40
- deps_hash.each do |name, req|
41
- next if normalised_name(name) == "python"
42
- next if req.is_a?(Hash) && req.key?("git")
43
-
44
- dependencies <<
45
- Dependency.new(
46
- name: normalised_name(name),
47
- version: version_from_lockfile(name),
48
- requirements: [{
49
- requirement: req.is_a?(String) ? req : req["version"],
50
- file: pyproject.name,
51
- source: nil,
52
- groups: [type]
53
- }],
54
- package_manager: "pip"
55
- )
56
- end
57
- end
58
-
59
- dependencies
60
- end
61
-
62
- # Create a DependencySet where each element has no requirement. Any
63
- # requirements will be added when combining the DependencySet with
64
- # other DependencySets.
65
- def lockfile_dependencies
66
- dependencies = Dependabot::FileParsers::Base::DependencySet.new
67
-
68
- parsed_lockfile.fetch("package", []).each do |details|
69
- next if details.dig("source", "type") == "git"
70
-
71
- dependencies <<
72
- Dependency.new(
73
- name: details.fetch("name"),
74
- version: details.fetch("version"),
75
- requirements: [],
76
- package_manager: "pip"
77
- )
78
- end
79
-
80
- dependencies
81
- end
82
-
83
- def version_from_lockfile(dep_name)
84
- return unless parsed_lockfile
85
-
86
- parsed_lockfile.fetch("package", []).
87
- find { |p| p.fetch("name") == normalised_name(dep_name) }&.
88
- fetch("verison", nil)
89
- end
90
-
91
- # See https://www.python.org/dev/peps/pep-0503/#normalized-names
92
- def normalised_name(name)
93
- name.downcase.gsub(/[-_.]+/, "-")
94
- end
95
-
96
- def parsed_pyproject
97
- @parsed_pyproject ||= TomlRB.parse(pyproject.content)
98
- rescue TomlRB::ParseError
99
- raise Dependabot::DependencyFileNotParseable, pyproject.path
100
- end
101
-
102
- def parsed_pyproject_lock
103
- @parsed_pyproject_lock ||= TomlRB.parse(pyproject_lock.content)
104
- rescue TomlRB::ParseError
105
- raise Dependabot::DependencyFileNotParseable, pyproject_lock.path
106
- end
107
-
108
- def parsed_poetry_lock
109
- @parsed_poetry_lock ||= TomlRB.parse(poetry_lock.content)
110
- rescue TomlRB::ParseError
111
- raise Dependabot::DependencyFileNotParseable, poetry_lock.path
112
- end
113
-
114
- def pyproject
115
- @pyproject ||=
116
- dependency_files.find { |f| f.name == "pyproject.toml" }
117
- end
118
-
119
- def lockfile
120
- poetry_lock || pyproject_lock
121
- end
122
-
123
- def parsed_lockfile
124
- return parsed_poetry_lock if poetry_lock
125
- return parsed_pyproject_lock if pyproject_lock
126
- end
127
-
128
- def pyproject_lock
129
- @pyproject_lock ||=
130
- dependency_files.find { |f| f.name == "pyproject.lock" }
131
- end
132
-
133
- def poetry_lock
134
- @poetry_lock ||=
135
- dependency_files.find { |f| f.name == "poetry.lock" }
136
- end
137
- end
138
- end
139
- end
140
- end
141
- end