Merge pull request #16817 from cho-m/virtualenv-basic-resource-order-args
language/python: order args for `virtualenv_install_with_resources`
This commit is contained in:
commit
c44bf6f432
@ -224,10 +224,13 @@ module Language
|
||||
system_site_packages: T::Boolean,
|
||||
without_pip: T::Boolean,
|
||||
link_manpages: T::Boolean,
|
||||
without: T.nilable(T.any(String, T::Array[String])),
|
||||
start_with: T.nilable(T.any(String, T::Array[String])),
|
||||
end_with: T.nilable(T.any(String, T::Array[String])),
|
||||
).returns(Virtualenv)
|
||||
}
|
||||
def virtualenv_install_with_resources(using: nil, system_site_packages: true, without_pip: true,
|
||||
link_manpages: false)
|
||||
link_manpages: false, without: nil, start_with: nil, end_with: nil)
|
||||
python = using
|
||||
if python.nil?
|
||||
wanted = python_names.select { |py| needs_python?(py) }
|
||||
@ -237,9 +240,22 @@ module Language
|
||||
python = T.must(wanted.first)
|
||||
python = "python3" if python == "python"
|
||||
end
|
||||
|
||||
venv_resources = if without.nil? && start_with.nil? && end_with.nil?
|
||||
resources
|
||||
else
|
||||
remaining_resources = resources.to_h { |resource| [resource.name, resource] }
|
||||
|
||||
slice_resources!(remaining_resources, Array(without))
|
||||
start_with_resources = slice_resources!(remaining_resources, Array(start_with))
|
||||
end_with_resources = slice_resources!(remaining_resources, Array(end_with))
|
||||
|
||||
start_with_resources + remaining_resources.values + end_with_resources
|
||||
end
|
||||
|
||||
venv = virtualenv_create(libexec, python.delete("@"), system_site_packages:,
|
||||
without_pip:)
|
||||
venv.pip_install resources
|
||||
venv.pip_install venv_resources
|
||||
venv.pip_install_and_link(T.must(buildpath), link_manpages:)
|
||||
venv
|
||||
end
|
||||
@ -249,6 +265,22 @@ module Language
|
||||
%w[python python3 pypy pypy3] + Formula.names.select { |name| name.start_with? "python@" }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig {
|
||||
params(
|
||||
resources_hash: T::Hash[String, Resource],
|
||||
resource_names: T::Array[String],
|
||||
).returns(T::Array[Resource])
|
||||
}
|
||||
def slice_resources!(resources_hash, resource_names)
|
||||
resource_names.map do |resource_name|
|
||||
resources_hash.delete(resource_name) do
|
||||
raise ArgumentError, "Resource \"#{resource_name}\" is not defined in formula or is already used"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Convenience wrapper for creating and installing packages into Python
|
||||
# virtualenvs.
|
||||
class Virtualenv
|
||||
|
@ -3,7 +3,153 @@
|
||||
require "language/python"
|
||||
require "resource"
|
||||
|
||||
RSpec.describe Language::Python::Virtualenv::Virtualenv, :needs_python do
|
||||
RSpec.describe Language::Python::Virtualenv, :needs_python do
|
||||
describe "#virtualenv_install_with_resources" do
|
||||
let(:venv) { instance_double(Language::Python::Virtualenv::Virtualenv) }
|
||||
let(:f) do
|
||||
formula "foo" do
|
||||
# Couldn't find a way to get described_class to work inside formula do
|
||||
# rubocop:disable RSpec/DescribedClass
|
||||
include Language::Python::Virtualenv
|
||||
# rubocop:enable RSpec/DescribedClass
|
||||
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
|
||||
resource "resource-a" do
|
||||
url "https://brew.sh/resource1.tar.gz"
|
||||
sha256 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
end
|
||||
|
||||
resource "resource-b" do
|
||||
url "https://brew.sh/resource2.tar.gz"
|
||||
sha256 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
end
|
||||
|
||||
resource "resource-c" do
|
||||
url "https://brew.sh/resource3.tar.gz"
|
||||
sha256 "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
end
|
||||
|
||||
resource "resource-d" do
|
||||
url "https://brew.sh/resource4.tar.gz"
|
||||
sha256 "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
|
||||
end
|
||||
end
|
||||
end
|
||||
let(:r_a) { f.resource("resource-a") }
|
||||
let(:r_b) { f.resource("resource-b") }
|
||||
let(:r_c) { f.resource("resource-c") }
|
||||
let(:r_d) { f.resource("resource-d") }
|
||||
let(:buildpath) { Pathname(TEST_TMPDIR) }
|
||||
|
||||
before { f.instance_variable_set(:@buildpath, buildpath) }
|
||||
|
||||
it "works with `using: \"python\"` and installs resources in order" do
|
||||
expect(f).to receive(:virtualenv_create).with(
|
||||
f.libexec, "python", { system_site_packages: true, without_pip: true }
|
||||
).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_a, r_b, r_c, r_d])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python")
|
||||
end
|
||||
|
||||
it "works with `using: \"python@3.12\"` and installs resources in order" do
|
||||
expect(f).to receive(:virtualenv_create).with(
|
||||
f.libexec, "python3.12", { system_site_packages: true, without_pip: true }
|
||||
).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_a, r_b, r_c, r_d])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python@3.12")
|
||||
end
|
||||
|
||||
it "skips a `without` resource string and installs remaining resources in order" do
|
||||
expect(f).to receive(:virtualenv_create).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_a, r_b, r_d])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python", without: r_c.name)
|
||||
end
|
||||
|
||||
it "skips all resources in `without` array and installs remaining resources in order" do
|
||||
expect(f).to receive(:virtualenv_create).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_b, r_c])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python", without: [r_d.name, r_a.name])
|
||||
end
|
||||
|
||||
it "errors if `without` resource string does not exist in formula" do
|
||||
expect do
|
||||
f.virtualenv_install_with_resources(using: "python", without: "unknown")
|
||||
end.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "errors if `without` resource array refers to a resource that does not exist in formula" do
|
||||
expect do
|
||||
f.virtualenv_install_with_resources(using: "python", without: [r_a.name, "unknown"])
|
||||
end.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "installs a `start_with` resource string and then remaining resources in order" do
|
||||
expect(f).to receive(:virtualenv_create).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_c, r_a, r_b, r_d])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python", start_with: r_c.name)
|
||||
end
|
||||
|
||||
it "installs all resources in `start_with` array and then remaining resources in order" do
|
||||
expect(f).to receive(:virtualenv_create).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_d, r_b, r_a, r_c])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python", start_with: [r_d.name, r_b.name])
|
||||
end
|
||||
|
||||
it "errors if `start_with` resource string does not exist in formula" do
|
||||
expect do
|
||||
f.virtualenv_install_with_resources(using: "python", start_with: "unknown")
|
||||
end.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "errors if `start_with` resource array refers to a resource that does not exist in formula" do
|
||||
expect do
|
||||
f.virtualenv_install_with_resources(using: "python", start_with: [r_a.name, "unknown"])
|
||||
end.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "installs an `end_with` resource string as last resource" do
|
||||
expect(f).to receive(:virtualenv_create).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_a, r_c, r_d, r_b])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python", end_with: r_b.name)
|
||||
end
|
||||
|
||||
it "installs all resources in `end_with` array after other resources are installed" do
|
||||
expect(f).to receive(:virtualenv_create).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_a, r_d, r_c, r_b])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python", end_with: [r_c.name, r_b.name])
|
||||
end
|
||||
|
||||
it "errors if `end_with` resource string does not exist in formula" do
|
||||
expect do
|
||||
f.virtualenv_install_with_resources(using: "python", end_with: "unknown")
|
||||
end.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "errors if `end_with` resource array refers to a resource that does not exist in formula" do
|
||||
expect do
|
||||
f.virtualenv_install_with_resources(using: "python", end_with: [r_a.name, "unknown"])
|
||||
end.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "installs resources in correct order when combining `without`, `start_with`, and `end_with" do
|
||||
expect(f).to receive(:virtualenv_create).and_return(venv)
|
||||
expect(venv).to receive(:pip_install).with([r_d, r_c, r_b])
|
||||
expect(venv).to receive(:pip_install_and_link).with(buildpath, { link_manpages: false })
|
||||
f.virtualenv_install_with_resources(using: "python", without: r_a.name,
|
||||
start_with: r_d.name, end_with: r_b.name)
|
||||
end
|
||||
end
|
||||
|
||||
describe Language::Python::Virtualenv::Virtualenv do
|
||||
subject(:virtualenv) { described_class.new(formula, dir, "python") }
|
||||
|
||||
let(:dir) { mktmpdir }
|
||||
@ -15,7 +161,8 @@ RSpec.describe Language::Python::Virtualenv::Virtualenv, :needs_python do
|
||||
|
||||
describe "#create" do
|
||||
it "creates a venv" do
|
||||
expect(formula).to receive(:system).with("python", "-m", "venv", "--system-site-packages", "--without-pip", dir)
|
||||
expect(formula).to receive(:system)
|
||||
.with("python", "-m", "venv", "--system-site-packages", "--without-pip", dir)
|
||||
virtualenv.create
|
||||
end
|
||||
|
||||
@ -150,4 +297,5 @@ RSpec.describe Language::Python::Virtualenv::Virtualenv, :needs_python do
|
||||
expect(dest_man/"man3").not_to exist
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user