Compare commits

...

4 Commits

Author SHA1 Message Date
Jordan Sissel bfa2e8d1fe Have pip download packages to the build_path
Prior to this change, pip would download Python packages to $PWD which
leaves files hanging around.

The build_path is automatically removed when fpm exits.
2021-11-09 21:26:04 -08:00
Jordan Sissel c983842ba4 Try to find the right python executable. Also don't require easy_install anymore.
As part of making "internal pip" the default (#1820), the test suite
needed two main changes:
1) Don't check for easy_install anymore
2) Try to find the right python executable.

On my Ubuntu 20.04 system, installing Python gives Python v3 which only
makes the "python3" executable available. To compensate, the test suite
now tries to find any of "python", "python2", or "python3" to use with
the test suite. When found, it will set the appropriate `--python-bin`
flag in fpm for each test.

For #1820
2021-11-09 21:17:24 -08:00
Jordan Sissel b708b092dc Cite reason for using 'python -m pip' aka "internal pip"
* https://bugs.python.org/issue22295

At time of writing, the python 3 installation docs mention:

https://docs.python.org/3/installing/index.html

> The following command will install the latest version of a module and its dependencies from the Python Package Index:
>
> python -m pip install SomePackage
2021-11-09 21:17:24 -08:00
Jordan Sissel 7ee316995c By default, use pip for fetching and installing python packages.
This adds a new flag, --python-internal-pip, which is enabled by default.

"internal pip" means using 'python -m pip' to invoke pip. Ideally this will make fpm more correctly use pip.

Tested on python 2.7.17 and 3.6.9 on Ubuntu 18.04

All python tests passing 👍👍

Fixes #1820
2021-11-09 21:17:24 -08:00
3 changed files with 39 additions and 17 deletions

View File

@ -79,7 +79,11 @@ class FPM::Package::Python < FPM::Package
option "--setup-py-arguments", "setup_py_argument",
"Arbitrary argument(s) to be passed to setup.py",
:multivalued => true, :attribute_name => :python_setup_py_arguments,
:default => []
:default => []
option "--internal-pip", :flag,
"Use the pip module within python to install modules - aka 'python -m pip'. This is the recommended usage since Python 3.4 (2014) instead of invoking the 'pip' script",
:attribute_name => :python_internal_pip,
:default => true
private
@ -130,23 +134,24 @@ class FPM::Package::Python < FPM::Package
target = build_path(package)
FileUtils.mkdir(target) unless File.directory?(target)
if attributes[:python_pip].nil?
# no pip, use easy_install
logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall])
safesystem(attributes[:python_easyinstall], "-i",
attributes[:python_pypi], "--editable", "-U",
"--build-directory", target, want_pkg)
else
if attributes[:python_internal_pip?]
# XXX: Should we detect if internal pip is available?
attributes[:python_pip] = [ attributes[:python_bin], "-m", "pip"]
end
# attributes[:python_pip] -- expected to be a path
if attributes[:python_pip]
logger.debug("using pip", :pip => attributes[:python_pip])
# TODO: Support older versions of pip
pip = [attributes[:python_pip]] if pip.is_a?(String)
setup_cmd = [
attributes[:python_pip],
*attributes[:python_pip],
"download",
"--no-clean",
"--no-deps",
"--no-binary",
":all:",
"--no-binary", ":all:",
"-d", build_path,
"-i", attributes[:python_pypi],
]
@ -164,6 +169,12 @@ class FPM::Package::Python < FPM::Package
]
safesystem(*setup_cmd)
else
# no pip, use easy_install
logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall])
safesystem(attributes[:python_easyinstall], "-i",
attributes[:python_pypi], "--editable", "-U",
"--build-directory", target, want_pkg)
end
# easy_install will put stuff in @tmpdir/packagename/, so find that:

View File

@ -10,6 +10,9 @@ setup(name="Example",
package_dir={},
install_requires=[
"Dependency1", "dependency2",
# XXX: I don't know what these python_version-dependent deps mean
# needs investigation
# Reference: PEP-0508
'rtxt-dep3; python_version == "2.0"',
'rtxt-dep4; python_version > "2.0"',
],

View File

@ -3,13 +3,19 @@ require "fpm" # local
require "fpm/package/python" # local
require "find" # stdlib
def find_python
[ "python", "python3", "python2" ].each do |i|
return i if program_exists?(i)
end
return nil
end
def python_usable?
return program_exists?("python") && program_exists?("easy_install")
return find_python
end
if !python_usable?
Cabin::Channel.get("rspec").warn("Skipping Python#input tests because " \
"'python' and/or 'easy_install' isn't in your PATH")
Cabin::Channel.get("rspec").warn("Skipping Python#input tests because 'python' wasn't found in $PATH")
end
is_travis = ENV["TRAVIS_OS_NAME"] && !ENV["TRAVIS_OS_NAME"].empty?
@ -28,7 +34,8 @@ end
describe FPM::Package::Python do
before do
skip("Python and/or easy_install not found") unless python_usable?
skip("Python program not found") unless python_usable?
subject.attributes[:python_bin] = find_python
end
let (:example_dir) do
@ -124,7 +131,8 @@ describe FPM::Package::Python do
it "it should include the dependencies from setup.py" do
subject.input(example_dir)
insist { subject.dependencies.sort } == ["python-dependency1 ","python-dependency2 "]
# XXX: Why is there extra whitespace in these strings?
insist { subject.dependencies.sort } == ["python-dependency1 ","python-dependency2 ", "python-rtxt-dep4 "]
end
context "and :python_disable_dependency is set" do
@ -134,7 +142,7 @@ describe FPM::Package::Python do
it "it should exclude the dependency" do
subject.input(example_dir)
insist { subject.dependencies.sort } == ["python-dependency2 "]
insist { subject.dependencies.sort } == ["python-dependency2 ", "python-rtxt-dep4 "]
end
end
end