class Dependabot::Uv::FileParser::SetupFileParser

def check_requirements(requirements)

def check_requirements(requirements)
  requirements&.each do |dep|
    next unless dep["requirement"]
    Uv::Requirement.new(dep["requirement"].split(","))
  rescue Gem::Requirement::BadRequirementError => e
    raise Dependabot::DependencyFileNotEvaluatable, e.message
  end
end

def closing_bracket_index(string, bracket)

def closing_bracket_index(string, bracket)
  closes_required = 1
  string.chars.each_with_index do |char, index|
    closes_required += 1 if char == bracket
    closes_required -= 1 if char == CLOSING_BRACKET.fetch(bracket)
    return index if closes_required.zero?
  end
  0
end

def dependency_set

def dependency_set
  dependencies = Dependabot::FileParsers::Base::DependencySet.new
  parsed_setup_file.each do |dep|
    # If a requirement has a `<` or `<=` marker then updating it is
    # probably blocked. Ignore it.
    next if dep["markers"].include?("<")
    # If the requirement is our inserted version, ignore it
    # (we wouldn't be able to update it)
    next if dep["version"] == "0.0.1+dependabot"
    dependencies <<
      Dependency.new(
        name: normalised_name(dep["name"], dep["extras"]),
        version: dep["version"]&.include?("*") ? nil : dep["version"],
        requirements: [{
          requirement: dep["requirement"],
          file: Pathname.new(dep["file"]).cleanpath.to_path,
          source: nil,
          groups: [dep["requirement_type"]]
        }],
        package_manager: "uv"
      )
  end
  dependencies
end

def get_regexed_req_array(regex)

def get_regexed_req_array(regex)
  return unless (mch = setup_file.content.match(regex))
  "[#{mch.post_match[0..closing_bracket_index(mch.post_match, '[')]}"
end

def get_regexed_req_dict(regex)

def get_regexed_req_dict(regex)
  return unless (mch = setup_file.content.match(regex))
  "{#{mch.post_match[0..closing_bracket_index(mch.post_match, '{')]}"
end

def initialize(dependency_files:)

def initialize(dependency_files:)
  @dependency_files = dependency_files
end

def normalised_name(name, extras)

def normalised_name(name, extras)
  NameNormaliser.normalise_including_extras(name, extras)
end

def parsed_sanitized_setup_file

def parsed_sanitized_setup_file
  SharedHelpers.in_a_temporary_directory do
    write_sanitized_setup_file
    requirements = SharedHelpers.run_helper_subprocess(
      command: "pyenv exec python3 #{NativeHelpers.python_helper_path}",
      function: "parse_setup",
      args: [Dir.pwd]
    )
    check_requirements(requirements)
    requirements
  end
rescue SharedHelpers::HelperSubprocessFailed
  # Assume there are no dependencies in setup.py files that fail to
  # parse. This isn't ideal, and we should continue to improve
  # parsing, but there are a *lot* of things that can go wrong at
  # the moment!
  []
end

def parsed_setup_file

def parsed_setup_file
  SharedHelpers.in_a_temporary_directory do
    write_temporary_dependency_files
    requirements = SharedHelpers.run_helper_subprocess(
      command: "pyenv exec python3 #{NativeHelpers.python_helper_path}",
      function: "parse_setup",
      args: [Dir.pwd]
    )
    check_requirements(requirements)
    requirements
  end
rescue SharedHelpers::HelperSubprocessFailed => e
  raise Dependabot::DependencyFileNotEvaluatable, e.message if e.message.start_with?("InstallationError")
  return [] unless setup_file
  parsed_sanitized_setup_file
end

def setup_file

def setup_file
  dependency_files.find { |f| f.name == "setup.py" }
end

def write_sanitized_setup_file

def write_sanitized_setup_file
  install_requires = get_regexed_req_array(INSTALL_REQUIRES_REGEX)
  setup_requires = get_regexed_req_array(SETUP_REQUIRES_REGEX)
  tests_require = get_regexed_req_array(TESTS_REQUIRE_REGEX)
  extras_require = get_regexed_req_dict(EXTRAS_REQUIRE_REGEX)
  tmp = "from setuptools import setup\n\n" \
        "setup(name=\"sanitized-package\",version=\"0.0.1\","
  tmp += "install_requires=#{install_requires}," if install_requires
  tmp += "setup_requires=#{setup_requires}," if setup_requires
  tmp += "tests_require=#{tests_require}," if tests_require
  tmp += "extras_require=#{extras_require}," if extras_require
  tmp += ")"
  File.write("setup.py", tmp)
end

def write_temporary_dependency_files

def write_temporary_dependency_files
  dependency_files
    .reject { |f| f.name == ".python-version" }
    .each do |file|
      path = file.name
      FileUtils.mkdir_p(Pathname.new(path).dirname)
      File.write(path, file.content)
    end
end