dependabot-python 0.380.0 → 0.381.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05b66da58a53be405a84e1d0690f1e469dbe7f629a30a969e23eaded26de4f33
4
- data.tar.gz: d42a62ba72dacd9e0368aa66c3b19b9791a9896f231cf5d43da258204dfe19d4
3
+ metadata.gz: f0477e6159f9fcd2dfd744b603b9bd23ba2df5ad50c3bf3a8fc51fbcd00e6306
4
+ data.tar.gz: 1271ebda6e197461e2721a7aa0f69d917dc8c506813465931ba01ae143f3c34a
5
5
  SHA512:
6
- metadata.gz: 7953f17b6c1f70e7675228f17902850a0931b17aa2d25035d46348cfcd91db9cc6247b266cf84fdf927d3f6e9f86629a5ed41b1fd5e85933dfdbd22b09d8f63d
7
- data.tar.gz: 33ecc6ad4b78e6327fa28224f1b5fe7fec57da1ff1a3106cb06b97e69bf30ab7e91040a7c5f1b2622d1b522a6889f5bb9cd81207a50822ddd9fd6ec024c97238
6
+ metadata.gz: ca638414b000ecf033fa4470316f3858a1f57e9ca496db678b9779da39a292aaaaf66908b037e6b6f0c02ad528c9142cd42a687149a75887b053dc5001dd5ff8
7
+ data.tar.gz: 34164a7fcbc0eb80ee3cdfe995cd891560fe9b2feaab98ec3be721699117897855be5a6f76bb76cea581b2cf18b60cc378df2a1128042197582894154abb308f
@@ -1,4 +1,4 @@
1
- # typed: strict
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
@@ -37,6 +37,7 @@ module Dependabot
37
37
  files << setup_file if setup_file
38
38
  files << setup_cfg_file if setup_cfg_file
39
39
  files << pip_conf if pip_conf
40
+ files << pip_tools_config if pip_tools_config
40
41
  files
41
42
  end
42
43
 
@@ -121,6 +122,14 @@ module Dependabot
121
122
  )
122
123
  end
123
124
 
125
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
126
+ def pip_tools_config
127
+ @pip_tools_config ||= T.let(
128
+ fetch_support_file(".pip-tools.toml"),
129
+ T.nilable(Dependabot::DependencyFile)
130
+ )
131
+ end
132
+
124
133
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
125
134
  def pipfile
126
135
  @pipfile ||= T.let(
@@ -94,9 +94,10 @@ module Dependabot
94
94
  return dependencies unless pipfile_lock
95
95
 
96
96
  DEPENDENCY_GROUP_KEYS.map { |h| h.fetch(:lockfile) }.each do |key|
97
- next unless parsed_pipfile_lock[key]
97
+ section_data = parsed_pipfile_lock_section(key)
98
+ next unless section_data
98
99
 
99
- parsed_pipfile_lock[key].each do |dep_name, details|
100
+ section_data.each do |dep_name, details|
100
101
  version = case details
101
102
  when String then details
102
103
  when Hash then details["version"]
@@ -129,8 +130,7 @@ module Dependabot
129
130
  req = version_from_hash_or_string(requirement)
130
131
 
131
132
  if pipfile_lock
132
- details = parsed_pipfile_lock
133
- .dig(group, normalised_name(dep_name))
133
+ details = parsed_pipfile_lock_section(group)&.[](normalised_name(dep_name))
134
134
 
135
135
  version = version_from_hash_or_string(details)
136
136
  version&.gsub(/^===?/, "")
@@ -185,6 +185,14 @@ module Dependabot
185
185
  raise Dependabot::DependencyFileNotParseable, T.must(pipfile_lock).path
186
186
  end
187
187
 
188
+ sig { params(section: String).returns(T.nilable(T::Hash[String, T.untyped])) }
189
+ def parsed_pipfile_lock_section(section)
190
+ section_data = parsed_pipfile_lock[section]
191
+ return section_data if section_data.is_a?(Hash)
192
+
193
+ nil
194
+ end
195
+
188
196
  sig { returns(T.nilable(Dependabot::DependencyFile)) }
189
197
  def pipfile
190
198
  @pipfile ||= T.let(dependency_files.find { |f| f.name == "Pipfile" }, T.nilable(Dependabot::DependencyFile))
@@ -55,7 +55,7 @@ module Dependabot
55
55
 
56
56
  sig { returns(Dependabot::FileParsers::Base::DependencySet) }
57
57
  def poetry_dependencies
58
- @poetry_dependencies ||= T.let(parse_poetry_dependencies, T.untyped)
58
+ @poetry_dependencies ||= T.let(parse_poetry_dependencies, T.nilable(Dependabot::FileParsers::Base::DependencySet))
59
59
  end
60
60
 
61
61
  sig { returns(Dependabot::FileParsers::Base::DependencySet) }
@@ -372,16 +372,19 @@ module Dependabot
372
372
  }
373
373
  end
374
374
 
375
- sig { returns(T.untyped) }
375
+ sig { returns(T::Hash[String, T.untyped]) }
376
376
  def parsed_pyproject
377
- @parsed_pyproject ||= T.let(TomlRB.parse(T.must(pyproject).content), T.untyped)
377
+ @parsed_pyproject ||= T.let(TomlRB.parse(T.must(pyproject).content), T.nilable(T::Hash[String, T.untyped]))
378
378
  rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
379
379
  raise Dependabot::DependencyFileNotParseable, T.must(pyproject).path
380
380
  end
381
381
 
382
- sig { returns(T.untyped) }
382
+ sig { returns(T::Hash[String, T.untyped]) }
383
383
  def parsed_poetry_lock
384
- @parsed_poetry_lock ||= T.let(TomlRB.parse(T.must(poetry_lock).content), T.untyped)
384
+ @parsed_poetry_lock ||= T.let(
385
+ TomlRB.parse(T.must(poetry_lock).content),
386
+ T.nilable(T::Hash[String, T.untyped])
387
+ )
385
388
  rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
386
389
  raise Dependabot::DependencyFileNotParseable, T.must(poetry_lock).path
387
390
  end
@@ -21,7 +21,7 @@ module Dependabot
21
21
  TESTS_REQUIRE_REGEX = /tests_require\s*=\s*\[/m
22
22
  EXTRAS_REQUIRE_REGEX = /extras_require\s*=\s*\{/m
23
23
 
24
- CLOSING_BRACKET = T.let({ "[" => "]", "{" => "}" }.freeze, T.any(T.untyped, T.untyped))
24
+ CLOSING_BRACKET = T.let({ "[" => "]", "{" => "}" }.freeze, T::Hash[String, String])
25
25
 
26
26
  sig { params(dependency_files: T::Array[Dependabot::DependencyFile]).void }
27
27
  def initialize(dependency_files:)
@@ -539,7 +539,7 @@ module Dependabot
539
539
 
540
540
  sig { returns(T::Array[Dependabot::DependencyFile]) }
541
541
  def pip_compile_files
542
- @pip_compile_files ||= T.let(dependency_files.select { |f| f.name.end_with?(".in") }, T.untyped)
542
+ @pip_compile_files ||= T.let(dependency_files.select { |f| f.name.end_with?(".in") }, T.nilable(T::Array[Dependabot::DependencyFile]))
543
543
  end
544
544
 
545
545
  sig { returns(Dependabot::Python::PipCompileFileMatcher) }
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "open3"
5
+ require "toml-rb"
5
6
  require "dependabot/dependency"
6
7
  require "dependabot/python/requirement_parser"
7
8
  require "dependabot/python/file_fetcher"
@@ -36,6 +37,7 @@ module Dependabot
36
37
  WARNINGS = T.let(/\s*# WARNING:.*\Z/m, Regexp)
37
38
  UNSAFE_NOTE = T.let(/\s*# The following packages are considered to be unsafe.*\Z/m, Regexp)
38
39
  RESOLVER_REGEX = T.let(/(?<=--resolver=)(\w+)/, Regexp)
40
+ UNSAFE_PACKAGE_OPTION_REGEX = T.let(/--unsafe-package(?:=|\s+)(?<name>[^\s\\]+)/, Regexp)
39
41
  NATIVE_COMPILATION_ERROR = T.let(
40
42
  "pip._internal.exceptions.InstallationSubprocessError: Getting requirements to build wheel exited with 1",
41
43
  String
@@ -206,13 +208,20 @@ module Dependabot
206
208
  files = dependency_files
207
209
  .reject { |file| updated_filenames.include?(file.name) }
208
210
 
209
- args = dependency.to_h
210
- args = args.keys.to_h { |k| [k.to_sym, args[k]] }
211
- args[:requirements] = new_reqs
212
- args[:previous_requirements] = old_reqs
211
+ dep = T.must(dependency)
213
212
 
214
213
  RequirementFileUpdater.new(
215
- dependencies: [Dependency.new(**T.unsafe(args))],
214
+ dependencies: [Dependency.new(
215
+ name: dep.name,
216
+ version: dep.version,
217
+ requirements: new_reqs,
218
+ package_manager: dep.package_manager,
219
+ previous_version: dep.previous_version,
220
+ previous_requirements: old_reqs,
221
+ directory: dep.directory,
222
+ subdependency_metadata: dep.subdependency_metadata,
223
+ removed: dep.removed?
224
+ )],
216
225
  dependency_files: files,
217
226
  credentials: credentials
218
227
  ).updated_dependency_files
@@ -533,37 +542,38 @@ module Dependabot
533
542
  # Use the explicit output file if provided, otherwise fall back to finding one
534
543
  requirements_file = output_file || compiled_file_for_filename(filename)
535
544
  options += pip_compile_options_from_compiled_file(requirements_file) if requirements_file
545
+ options = merge_pip_tools_config_options(options)
536
546
 
537
547
  options.join(" ")
538
548
  end
539
549
 
540
- # rubocop:disable Metrics/AbcSize
541
550
  sig { params(requirements_file: T.nilable(Dependabot::DependencyFile)).returns(T::Array[String]) }
542
551
  def pip_compile_options_from_compiled_file(requirements_file)
552
+ content = T.must(T.must(requirements_file).content)
543
553
  options = ["--output-file=#{T.must(requirements_file).name}"]
544
554
 
545
- options << "--no-emit-index-url" unless T.must(T.must(requirements_file).content).include?("index-url http")
555
+ options << "--no-emit-index-url" unless content.include?("index-url http")
546
556
 
547
- options << "--generate-hashes" if T.must(T.must(requirements_file).content).include?("--hash=sha")
557
+ options << "--generate-hashes" if content.include?("--hash=sha")
548
558
 
549
- options << "--allow-unsafe" if includes_unsafe_packages?(T.must(T.must(requirements_file).content))
559
+ options << "--allow-unsafe" if includes_unsafe_packages?(content)
560
+ options.concat(unsafe_package_options_from_compiled_file(content))
550
561
 
551
- options << "--no-annotate" unless T.must(T.must(requirements_file).content).include?("# via ")
562
+ options << "--no-annotate" unless content.include?("# via ")
552
563
 
553
- options << "--no-header" unless T.must(T.must(requirements_file).content).include?("autogenerated by pip-c")
564
+ options << "--no-header" unless content.include?("autogenerated by pip-c")
554
565
 
555
- options << "--pre" if T.must(T.must(requirements_file).content).include?("--pre")
566
+ options << "--pre" if content.include?("--pre")
556
567
 
557
- options << "--strip-extras" if T.must(T.must(requirements_file).content).include?("--strip-extras")
568
+ options << "--strip-extras" if content.include?("--strip-extras")
558
569
 
559
- if (resolver = RESOLVER_REGEX.match(T.must(requirements_file).content))
570
+ if (resolver = RESOLVER_REGEX.match(content))
560
571
  options << "--resolver=#{resolver}"
561
572
  end
562
573
 
563
574
  options
564
575
  end
565
576
 
566
- # rubocop:enable Metrics/AbcSize
567
577
  sig { returns(T::Array[String]) }
568
578
  def pip_compile_index_options
569
579
  credentials
@@ -584,6 +594,87 @@ module Dependabot
584
594
  UNSAFE_PACKAGES.any? { |n| content.match?(/^#{Regexp.quote(n)}==/) }
585
595
  end
586
596
 
597
+ sig { params(content: String).returns(T::Array[String]) }
598
+ def unsafe_package_options_from_compiled_file(content)
599
+ header = content.lines.take_while { |line| line.start_with?("#") }.join(" ")
600
+ header
601
+ .scan(UNSAFE_PACKAGE_OPTION_REGEX)
602
+ .flatten
603
+ .uniq
604
+ .map { |name| "--unsafe-package=#{name}" }
605
+ end
606
+
607
+ sig { params(options: T::Array[String]).returns(T::Array[String]) }
608
+ def merge_pip_tools_config_options(options)
609
+ merged_options = options.dup
610
+ pip_tools_config_options.each do |option|
611
+ next if option_already_present?(merged_options, option)
612
+
613
+ merged_options << option
614
+ end
615
+
616
+ merged_options
617
+ end
618
+
619
+ sig { returns(T::Array[String]) }
620
+ def pip_tools_config_options
621
+ return [] unless pip_tools_config_file&.content
622
+
623
+ config = parse_pip_tools_config
624
+ return [] unless config
625
+
626
+ options = []
627
+ options << "--allow-unsafe" if config["allow-unsafe"] == true
628
+ options << "--strip-extras" if config["strip-extras"] == true
629
+
630
+ options.concat(resolver_option_from_config(config))
631
+ options.concat(unsafe_package_options_from_config(config))
632
+
633
+ options
634
+ end
635
+
636
+ sig { params(existing_options: T::Array[String], option: String).returns(T::Boolean) }
637
+ def option_already_present?(existing_options, option)
638
+ return existing_options.include?("--allow-unsafe") if option == "--allow-unsafe"
639
+ return existing_options.include?("--strip-extras") if option == "--strip-extras"
640
+ return existing_options.any? { |opt| opt.start_with?("--resolver=") } if option.start_with?("--resolver=")
641
+ return existing_options.include?(option) if option.start_with?("--unsafe-package=")
642
+
643
+ false
644
+ end
645
+
646
+ sig { params(config: T::Hash[String, T.untyped]).returns(T::Array[String]) }
647
+ def resolver_option_from_config(config)
648
+ resolver = config["resolver"]
649
+ return [] unless resolver.is_a?(String)
650
+ return [] if resolver.empty?
651
+
652
+ ["--resolver=#{resolver}"]
653
+ end
654
+
655
+ sig { params(config: T::Hash[String, T.untyped]).returns(T::Array[String]) }
656
+ def unsafe_package_options_from_config(config)
657
+ Array(config["unsafe-package"])
658
+ .select { |package_name| package_name.is_a?(String) && !package_name.empty? }
659
+ .map { |package_name| "--unsafe-package=#{package_name}" }
660
+ end
661
+
662
+ sig { returns(T.nilable(T::Hash[String, T.untyped])) }
663
+ def parse_pip_tools_config
664
+ parsed = T.let(TomlRB.parse(T.must(pip_tools_config_file).content), T::Hash[String, T.untyped])
665
+ pip_tools_config = parsed["pip-tools"]
666
+ return unless pip_tools_config.is_a?(Hash)
667
+
668
+ pip_tools_config
669
+ rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
670
+ nil
671
+ end
672
+
673
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
674
+ def pip_tools_config_file
675
+ dependency_files.find { |file| file.name.end_with?(".pip-tools.toml") }
676
+ end
677
+
587
678
  sig { returns(T::Array[String]) }
588
679
  def filenames_to_compile
589
680
  files_from_reqs =
@@ -14,6 +14,7 @@ require "dependabot/python/file_updater"
14
14
  require "dependabot/python/native_helpers"
15
15
  require "dependabot/python/name_normaliser"
16
16
  require "dependabot/python/poetry_plugin_installer"
17
+ require "dependabot/package/release_cooldown_options"
17
18
 
18
19
  module Dependabot
19
20
  module Python
@@ -36,13 +37,15 @@ module Dependabot
36
37
  params(
37
38
  dependencies: T::Array[Dependabot::Dependency],
38
39
  dependency_files: T::Array[Dependabot::DependencyFile],
39
- credentials: T::Array[Dependabot::Credential]
40
+ credentials: T::Array[Dependabot::Credential],
41
+ cooldown: T.nilable(Dependabot::Package::ReleaseCooldownOptions)
40
42
  ).void
41
43
  end
42
- def initialize(dependencies:, dependency_files:, credentials:)
44
+ def initialize(dependencies:, dependency_files:, credentials:, cooldown: nil)
43
45
  @dependencies = dependencies
44
46
  @dependency_files = dependency_files
45
47
  @credentials = credentials
48
+ @cooldown = T.let(cooldown, T.nilable(Dependabot::Package::ReleaseCooldownOptions))
46
49
  @updated_dependency_files = T.let(nil, T.nilable(T::Array[Dependabot::DependencyFile]))
47
50
  @prepared_pyproject = T.let(nil, T.nilable(String))
48
51
  @pyproject = T.let(nil, T.nilable(Dependabot::DependencyFile))
@@ -252,29 +255,49 @@ module Dependabot
252
255
  .update_python_requirement(language_version_manager.python_version)
253
256
  end
254
257
 
255
- sig { params(poetry_object: T::Hash[String, T.untyped], dep: Dependabot::Dependency).returns(T::Array[String]) }
258
+ sig { params(poetry_object: T::Hash[String, T.untyped], dep: Dependabot::Dependency).void }
256
259
  def lock_declaration_to_new_version!(poetry_object, dep)
257
- Dependabot::Python::FileParser::PyprojectFilesParser::POETRY_DEPENDENCY_TYPES.each do |type|
258
- names = poetry_object[type]&.keys || []
259
- pkg_name = names.find { |nm| normalise(nm) == dep.name }
260
- next unless pkg_name
260
+ pinned_version = exact_poetry_requirement(dep.version)
261
+ return unless pinned_version
261
262
 
262
- if poetry_object[type][pkg_name].is_a?(Hash)
263
- next unless poetry_object[type][pkg_name].key?("version") # skip enrichment-only entries
263
+ poetry_dependency_tables(poetry_object).each do |deps_hash|
264
+ pkg_name = deps_hash.keys.find { |nm| normalise(nm) == dep.name }
265
+ next unless pkg_name
264
266
 
265
- poetry_object[type][pkg_name]["version"] = dep.version
267
+ entry = deps_hash[pkg_name]
268
+ if entry.is_a?(Hash)
269
+ entry["version"] = pinned_version if entry.key?("version") # skip enrichment-only entries
266
270
  else
267
- poetry_object[type][pkg_name] = dep.version
271
+ deps_hash[pkg_name] = pinned_version
268
272
  end
269
273
  end
270
274
  end
271
275
 
272
276
  sig { params(poetry_object: T::Hash[String, T.untyped], dep: Dependabot::Dependency).void }
273
277
  def create_declaration_at_new_version!(poetry_object, dep)
274
- subdep_type = dep.production? ? "dependencies" : "dev-dependencies"
278
+ pinned_version = exact_poetry_requirement(dep.version)
279
+ return unless pinned_version
275
280
 
281
+ subdep_type = dep.production? ? "dependencies" : "dev-dependencies"
276
282
  poetry_object[subdep_type] ||= {}
277
- poetry_object[subdep_type][dep.name] = dep.version
283
+ poetry_object[subdep_type][dep.name] = pinned_version
284
+ end
285
+
286
+ sig { params(version: T.nilable(String)).returns(T.nilable(String)) }
287
+ def exact_poetry_requirement(version)
288
+ return nil unless version
289
+
290
+ # Pin with ==version only when cooldown is set so Poetry can't pick a newer excluded release.
291
+ @cooldown ? "==#{version}" : version
292
+ end
293
+
294
+ sig { params(poetry_object: T::Hash[String, T.untyped]).returns(T::Array[T::Hash[String, T.untyped]]) }
295
+ def poetry_dependency_tables(poetry_object)
296
+ types = Dependabot::Python::FileParser::PyprojectFilesParser::POETRY_DEPENDENCY_TYPES
297
+ groups = poetry_object["group"].is_a?(Hash) ? poetry_object["group"].values : []
298
+ candidates = types.map { |type| poetry_object[type] } +
299
+ groups.map { |group_spec| group_spec["dependencies"] if group_spec.is_a?(Hash) }
300
+ candidates.grep(Hash)
278
301
  end
279
302
 
280
303
  sig { params(dep: Dependabot::Dependency).returns(T::Boolean) }
@@ -93,7 +93,8 @@ module Dependabot
93
93
  PoetryFileUpdater.new(
94
94
  dependencies: dependencies,
95
95
  dependency_files: dependency_files,
96
- credentials: credentials
96
+ credentials: credentials,
97
+ cooldown: options[:update_cooldown]
97
98
  ).updated_dependency_files
98
99
  end
99
100
 
@@ -34,9 +34,12 @@ module Dependabot
34
34
  T.must(version)
35
35
  end
36
36
 
37
- sig { returns(T.untyped) }
37
+ sig { returns(String) }
38
38
  def python_major_minor
39
- @python_major_minor ||= T.let(T.must(Python::Version.new(python_version).segments[0..1]).join("."), T.untyped)
39
+ @python_major_minor ||= T.let(
40
+ T.must(Python::Version.new(python_version).segments[0..1]).join("."),
41
+ T.nilable(String)
42
+ )
40
43
  end
41
44
 
42
45
  sig { returns(String) }
@@ -117,9 +117,10 @@ module Dependabot
117
117
  return nil unless lockfile_content
118
118
 
119
119
  parsed_lockfile = JSON.parse(lockfile_content)
120
- section = lockfile_section
121
- dependency_data = parsed_lockfile.dig(section, dependency_name)
120
+ section_data = parsed_lockfile_section(parsed_lockfile, lockfile_section)
121
+ return nil unless section_data
122
122
 
123
+ dependency_data = section_data[dependency_name]
123
124
  return nil unless dependency_data
124
125
 
125
126
  dependency_data["extras"]
@@ -127,10 +128,11 @@ module Dependabot
127
128
 
128
129
  sig { params(updated_lockfile: T::Hash[String, T.untyped]).returns(T.nilable(String)) }
129
130
  def fetch_version_from_parsed_lockfile(updated_lockfile)
130
- deps = updated_lockfile[lockfile_section] || {}
131
+ section_data = parsed_lockfile_section(updated_lockfile, lockfile_section)
132
+ return nil unless section_data
131
133
 
132
- deps.dig(dependency_name, "version")
133
- &.gsub(/^==/, "")
134
+ section_data.dig(dependency_name, "version")
135
+ &.gsub(/^==/, "")
134
136
  end
135
137
 
136
138
  sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
@@ -138,18 +140,39 @@ module Dependabot
138
140
  SharedHelpers.run_shell_command(command, env: pipenv_env_variables, fingerprint: fingerprint)
139
141
  end
140
142
 
141
- sig { returns(String) }
143
+ sig { returns(T.nilable(String)) }
142
144
  def lockfile_section
143
145
  if current_dependency.requirements.any?
144
146
  T.must(current_dependency.requirements.first)[:groups].first
145
147
  else
148
+ parsed_lockfile = JSON.parse(T.must(T.must(lockfile).content))
146
149
  Python::FileParser::DEPENDENCY_GROUP_KEYS.each do |keys|
147
150
  section = keys.fetch(:lockfile)
148
- return section if JSON.parse(T.must(T.must(lockfile).content))[section].keys.any?(dependency_name)
151
+ section_data = parsed_lockfile_section(parsed_lockfile, section)
152
+ next unless section_data
153
+
154
+ return section if section_data.key?(dependency_name)
149
155
  end
156
+
157
+ nil
150
158
  end
151
159
  end
152
160
 
161
+ sig do
162
+ params(
163
+ parsed_lockfile: T::Hash[String, T.untyped],
164
+ section: T.nilable(String)
165
+ ).returns(T.nilable(T::Hash[String, T.untyped]))
166
+ end
167
+ def parsed_lockfile_section(parsed_lockfile, section)
168
+ return nil unless section
169
+
170
+ section_data = parsed_lockfile[section]
171
+ return section_data if section_data.is_a?(Hash)
172
+
173
+ nil
174
+ end
175
+
153
176
  sig { returns(String) }
154
177
  def dependency_name
155
178
  current_dependency.metadata[:original_name] || current_dependency.name
@@ -48,7 +48,7 @@ module Dependabot
48
48
  languages: {
49
49
  python: {
50
50
  "raw" => language_version_manager.user_specified_python_version || "unknown",
51
- "max" => language_version_manager.python_major_minor || "unknown"
51
+ "max" => language_version_manager.python_major_minor
52
52
  }
53
53
  }
54
54
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-python
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.380.0
4
+ version: 0.381.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.380.0
18
+ version: 0.381.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.380.0
25
+ version: 0.381.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -323,7 +323,7 @@ licenses:
323
323
  - MIT
324
324
  metadata:
325
325
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
326
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.380.0
326
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.381.0
327
327
  rdoc_options: []
328
328
  require_paths:
329
329
  - lib