class Dependabot::Python::FileUpdater::SetupFileSanitizer

setup.py using only the information which will appear in the lockfile.
Take a setup.py, parses it (carefully!) and then create a new, clean

def extras_require_hash

def extras_require_hash
  @extras_require_hash ||=
    begin
      hash = {}
      parsed_setup_file.dependencies.each do |dep|
        first = T.must(dep.requirements.first)
        first[:groups].each do |group|
          next unless group.start_with?("extras_require:")
          hash[group.split(":").last] ||= []
          hash[group.split(":").last] <<
            (dep.name + first[:requirement].to_s)
        end
      end
      hash
    end
end

def include_pbr?

def include_pbr?
  setup_requires_array.any? { |d| d.start_with?("pbr") }
end

def initialize(setup_file:, setup_cfg:)

def initialize(setup_file:, setup_cfg:)
  @setup_file = T.let(setup_file, T.nilable(Dependabot::DependencyFile))
  @setup_cfg = T.let(setup_cfg, T.nilable(Dependabot::DependencyFile))
  @install_requires_array = T.let(nil, T.nilable(T::Array[String]))
  @setup_requires_array = T.let(nil, T.nilable(T::Array[String]))
  @extras_require_hash = T.let(nil, T.nilable(T::Hash[String, T::Array[String]]))
  @parsed_setup_file = T.let(nil, T.nilable(Dependabot::FileParsers::Base::DependencySet))
end

def install_requires_array

def install_requires_array
  @install_requires_array ||=
    parsed_setup_file.dependencies.filter_map do |dep|
      first = T.must(dep.requirements.first)
      next unless first[:groups]
                  .include?("install_requires")
      dep.name + first[:requirement].to_s
    end
end

def package_name

def package_name
  content = T.must(T.must(setup_file).content)
  match = content.match(/name\s*=\s*['"](?<package_name>[^'"]+)['"]/)
  match ? T.must(match[:package_name]) : "default_package_name"
end

def parsed_setup_file

def parsed_setup_file
  @parsed_setup_file ||=
    Python::FileParser::SetupFileParser.new(
      dependency_files: [
        setup_file&.dup&.tap { |f| f.name = "setup.py" },
        setup_cfg&.dup&.tap { |f| f.name = "setup.cfg" }
      ].compact
    ).dependency_set
end

def sanitized_content

def sanitized_content
  # The part of the setup.py that Pipenv cares about appears to be the
  # install_requires. A name and version are required by don't end up
  # in the lockfile.
  content =
    "from setuptools import setup\n\n" \
    "setup(name=\"#{package_name}\",version=\"0.0.1\"," \
    "install_requires=#{install_requires_array.to_json}," \
    "extras_require=#{extras_require_hash.to_json}"
  content += ',setup_requires=["pbr"],pbr=True' if include_pbr?
  content + ")"
end

def setup_requires_array

def setup_requires_array
  @setup_requires_array ||=
    parsed_setup_file.dependencies.filter_map do |dep|
      first = T.must(dep.requirements.first)
      next unless first[:groups]
                  .include?("setup_requires")
      dep.name + first[:requirement].to_s
    end
end