diff --git a/python/lib/dependabot/python/file_parser/pyproject_files_parser.rb b/python/lib/dependabot/python/file_parser/pyproject_files_parser.rb index 6ce7ef57e8f0..b1841ca856c3 100644 --- a/python/lib/dependabot/python/file_parser/pyproject_files_parser.rb +++ b/python/lib/dependabot/python/file_parser/pyproject_files_parser.rb @@ -137,12 +137,21 @@ def parse_requirements_from(req, type) check_requirements(requirement) - { - requirement: requirement.is_a?(String) ? requirement : requirement["version"], - file: pyproject.name, - source: nil, - groups: [type] - } + if requirement.is_a?(String) + { + requirement: requirement, + file: pyproject.name, + source: nil, + groups: [type] + } + else + { + requirement: requirement["version"], + file: pyproject.name, + source: requirement.fetch("source", nil), + groups: [type] + } + end end end diff --git a/python/lib/dependabot/python/update_checker/index_finder.rb b/python/lib/dependabot/python/update_checker/index_finder.rb index f1b610f1725f..649a861b136f 100644 --- a/python/lib/dependabot/python/update_checker/index_finder.rb +++ b/python/lib/dependabot/python/update_checker/index_finder.rb @@ -12,9 +12,10 @@ class IndexFinder PYPI_BASE_URL = "https://pypi.org/simple/" ENVIRONMENT_VARIABLE_REGEX = /\$\{.+\}/ - def initialize(dependency_files:, credentials:) + def initialize(dependency_files:, credentials:, dependency:) @dependency_files = dependency_files @credentials = credentials + @dependency = dependency end def index_urls @@ -124,7 +125,11 @@ def pyproject_index_urls if source["default"] urls[:main] = source["url"] - else + elsif source["priority"] != "explicit" + # if source is not explicit, add it to extra + urls[:extra] << source["url"] + elsif @dependency.all_sources.include?(source["name"]) + # if source is explicit, and dependency has specified it as a source, add it to extra urls[:extra] << source["url"] end end diff --git a/python/lib/dependabot/python/update_checker/latest_version_finder.rb b/python/lib/dependabot/python/update_checker/latest_version_finder.rb index a6340ac1bcf5..071202e8ab1e 100644 --- a/python/lib/dependabot/python/update_checker/latest_version_finder.rb +++ b/python/lib/dependabot/python/update_checker/latest_version_finder.rb @@ -213,7 +213,8 @@ def index_urls @index_urls ||= IndexFinder.new( dependency_files: dependency_files, - credentials: credentials + credentials: credentials, + dependency: dependency ).index_urls end diff --git a/python/spec/dependabot/python/file_parser/pyproject_files_parser_spec.rb b/python/spec/dependabot/python/file_parser/pyproject_files_parser_spec.rb index f3f85f7d8b6f..df4fb171e8aa 100644 --- a/python/spec/dependabot/python/file_parser/pyproject_files_parser_spec.rb +++ b/python/spec/dependabot/python/file_parser/pyproject_files_parser_spec.rb @@ -251,6 +251,15 @@ expect(dependency_names).to include("sphinx") end end + + context "with package specify source" do + let(:pyproject_fixture_name) { "package_specify_source.toml" } + subject(:dependency) { dependencies.find { |f| f.name == "black" } } + + it "specifies a package source" do + expect(dependency.requirements[0][:source]).to eq("custom") + end + end end describe "parse standard python files" do diff --git a/python/spec/dependabot/python/update_checker/index_finder_spec.rb b/python/spec/dependabot/python/update_checker/index_finder_spec.rb index f2e15ad9df81..80343089a0e1 100644 --- a/python/spec/dependabot/python/update_checker/index_finder_spec.rb +++ b/python/spec/dependabot/python/update_checker/index_finder_spec.rb @@ -9,7 +9,8 @@ let(:finder) do described_class.new( dependency_files: dependency_files, - credentials: credentials + credentials: credentials, + dependency: dependency ) end let(:credentials) do @@ -21,6 +22,19 @@ }] end let(:dependency_files) { [requirements_file] } + let(:dependency) do + Dependabot::Dependency.new( + name: "requests", + version: "2.4.1", + requirements: [{ + requirement: "==2.4.1", + file: "requirements.txt", + groups: ["dependencies"], + source: nil + }], + package_manager: "pip" + ) + end before do stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response) @@ -306,6 +320,43 @@ end end + context "when set in a pyproject.toml file and marked as explicit" do + let(:pyproject_fixture_name) { "extra_source_explicit.toml" } + let(:dependency_files) { [pyproject] } + + it "gets the right index URLs" do + expect(index_urls).to match_array( + [ + "https://pypi.org/simple/" + ] + ) + end + end + + context "when set in a pyproject.toml file and marked as explicit and specify with source" do + let(:pyproject_fixture_name) { "extra_source_explicit_and_package_specify_source.toml" } + let(:dependency_files) { [pyproject] } + let(:dependency) do + Dependabot::Dependency.new( + name: "requests", + version: "2.4.1", + requirements: [{ + requirement: "==2.4.1", + file: "requirements.txt", + groups: ["dependencies"], + source: "custom" + }], + package_manager: "pip" + ) + end + + it "gets the right index URLs" do + expect(index_urls).to match_array( + ["https://pypi.org/simple/", "https://some.internal.registry.com/pypi/"] + ) + end + end + context "set in credentials" do let(:credentials) do [{ diff --git a/python/spec/fixtures/pyproject_files/extra_source_explicit.toml b/python/spec/fixtures/pyproject_files/extra_source_explicit.toml new file mode 100644 index 000000000000..26b3527ae39a --- /dev/null +++ b/python/spec/fixtures/pyproject_files/extra_source_explicit.toml @@ -0,0 +1,17 @@ +[tool.poetry] +name = "PythonProjects" +version = "2.0.0" +homepage = "https://github.com/roghu/py3_projects" +license = "MIT" +readme = "README.md" +authors = ["Dependabot "] +description = "Various small python projects." + +[tool.poetry.dependencies] +python = "^3.7" +requests = "2.18.0" + +[[tool.poetry.source]] +name = "custom" +url = "https://some.internal.registry.com/pypi/" +priority = "explicit" diff --git a/python/spec/fixtures/pyproject_files/extra_source_explicit_and_package_specify_source.toml b/python/spec/fixtures/pyproject_files/extra_source_explicit_and_package_specify_source.toml new file mode 100644 index 000000000000..6a578ede209d --- /dev/null +++ b/python/spec/fixtures/pyproject_files/extra_source_explicit_and_package_specify_source.toml @@ -0,0 +1,17 @@ +[tool.poetry] +name = "PythonProjects" +version = "2.0.0" +homepage = "https://github.com/roghu/py3_projects" +license = "MIT" +readme = "README.md" +authors = ["Dependabot "] +description = "Various small python projects." + +[tool.poetry.dependencies] +python = "^3.7" +requests = { version = "2.18.0", source = "custom" } + +[[tool.poetry.source]] +name = "custom" +url = "https://some.internal.registry.com/pypi/" +priority = "explicit" diff --git a/python/spec/fixtures/pyproject_files/package_specify_source.toml b/python/spec/fixtures/pyproject_files/package_specify_source.toml new file mode 100644 index 000000000000..dbbab5083afe --- /dev/null +++ b/python/spec/fixtures/pyproject_files/package_specify_source.toml @@ -0,0 +1,12 @@ +[tool.poetry] +name = "PoetryGroups" +version = "2.0.0" +homepage = "https://github.com/roghu/py3_projects" +license = "MIT" +readme = "README.md" +authors = ["Dependabot "] +description = "Various small python projects." + +[tool.poetry.dependencies] +python = ">=3.10" +black = {version="^22.12.0", source="custom"}