poise-python 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/poise_python/resources/python_package.rb +39 -60
- data/lib/poise_python/resources/python_runtime_pip.rb +6 -3
- data/lib/poise_python/resources/python_runtime_test.rb +17 -2
- data/lib/poise_python/version.rb +1 -1
- data/test/cookbooks/poise-python_test/recipes/default.rb +31 -6
- data/test/integration/default/serverspec/default_spec.rb +25 -3
- data/test/spec/resources/python_package_spec.rb +3 -34
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bef0f55828842107d9397608ee63c0a08007f6d4
|
4
|
+
data.tar.gz: 05b4a93226b282e4b1708f7ec29d7b9f40d6baad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7084145bf568d242e6c33a1a8560d23ff49de234b2c3e9358e5cee8478dc26ebdd7259db6f86d43db7ab3693efe05d99d5d14cb117e01f892a184b8eed19a93
|
7
|
+
data.tar.gz: 55016a0d57459240bfd38c140628e743011beccfce1130dd6fbb09baa8b8a4221090b8c64e91423bfdf156394d2909104e368552b1f7796f14686205dbfcd21e
|
data/CHANGELOG.md
CHANGED
@@ -29,47 +29,44 @@ module PoisePython
|
|
29
29
|
# (see PythonPackage::Resource)
|
30
30
|
# @since 1.0.0
|
31
31
|
module PythonPackage
|
32
|
-
# A Python snippet to
|
33
|
-
#
|
34
|
-
# @api private
|
32
|
+
# A Python snippet to check which versions of things pip would try to
|
33
|
+
# install. Probably not 100% bulletproof.
|
35
34
|
PIP_HACK_SCRIPT = <<-EOH
|
35
|
+
import json
|
36
36
|
import sys
|
37
37
|
|
38
|
-
import
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
get_installed_distributions.__code__ = replacement.__code__
|
71
|
-
|
72
|
-
sys.exit(pip.main())
|
38
|
+
from pip.commands import InstallCommand
|
39
|
+
from pip.index import PackageFinder
|
40
|
+
from pip.req import InstallRequirement
|
41
|
+
from pip._vendor import pkg_resources
|
42
|
+
|
43
|
+
|
44
|
+
packages = {}
|
45
|
+
cmd = InstallCommand()
|
46
|
+
options, args = cmd.parse_args(sys.argv[1:])
|
47
|
+
with cmd._build_session(options) as session:
|
48
|
+
if options.no_index:
|
49
|
+
index_urls = []
|
50
|
+
else:
|
51
|
+
index_urls = [options.index_url] + options.extra_index_urls
|
52
|
+
finder = PackageFinder(
|
53
|
+
find_links=options.find_links,
|
54
|
+
format_control=options.format_control,
|
55
|
+
index_urls=index_urls,
|
56
|
+
trusted_hosts=options.trusted_hosts,
|
57
|
+
allow_all_prereleases=options.pre,
|
58
|
+
process_dependency_links=options.process_dependency_links,
|
59
|
+
session=session,
|
60
|
+
)
|
61
|
+
find_all = getattr(finder, 'find_all_candidates', getattr(finder, '_find_all_versions', None))
|
62
|
+
for arg in args:
|
63
|
+
req = InstallRequirement.from_line(arg)
|
64
|
+
found = finder.find_requirement(req, True)
|
65
|
+
all_candidates = find_all(req.name)
|
66
|
+
candidate = [c for c in all_candidates if c.location == found]
|
67
|
+
if candidate:
|
68
|
+
packages[candidate[0].project.lower()] = str(candidate[0].version)
|
69
|
+
json.dump(packages, sys.stdout)
|
73
70
|
EOH
|
74
71
|
|
75
72
|
# A `python_package` resource to manage Python installations using pip.
|
@@ -165,7 +162,7 @@ EOH
|
|
165
162
|
end
|
166
163
|
# Check for newer candidates.
|
167
164
|
outdated = pip_outdated(pip_requirements(resource.package_name, version, parse: true)).stdout
|
168
|
-
|
165
|
+
Chef::JSONCompat.parse(outdated).each do |name, candidate|
|
169
166
|
# Merge candidates in to the existing versions.
|
170
167
|
version_data[name][:candidate] = candidate
|
171
168
|
end
|
@@ -245,7 +242,7 @@ EOH
|
|
245
242
|
|
246
243
|
# Run a pip command.
|
247
244
|
#
|
248
|
-
# @param pip_command [String] The pip subcommand to run (eg. install).
|
245
|
+
# @param pip_command [String, nil] The pip subcommand to run (eg. install).
|
249
246
|
# @param pip_options [Array<String>] Options for the pip command.
|
250
247
|
# @param opts [Hash] Mixlib::ShellOut options.
|
251
248
|
# @return [Mixlib::ShellOut]
|
@@ -257,7 +254,7 @@ EOH
|
|
257
254
|
"#{runner.join(' ')} #{pip_command} #{new_resource.options} #{Shellwords.join(pip_options)}"
|
258
255
|
else
|
259
256
|
# No special options, use an array to skip the extra /bin/sh.
|
260
|
-
runner + [pip_command] + pip_options
|
257
|
+
runner + (pip_command ? [pip_command] : []) + pip_options
|
261
258
|
end
|
262
259
|
# Set user and group.
|
263
260
|
opts[:user] = new_resource.user if new_resource.user
|
@@ -287,25 +284,7 @@ EOH
|
|
287
284
|
# @param requirements [Array<String>] Pip-formatted package requirements.
|
288
285
|
# @return [Mixlib::ShellOut]
|
289
286
|
def pip_outdated(requirements)
|
290
|
-
pip_command(
|
291
|
-
end
|
292
|
-
|
293
|
-
# Parse the output from `pip list --outdate`. Returns a hash of package
|
294
|
-
# key to candidate version.
|
295
|
-
#
|
296
|
-
# @param text [String] Output to parse.
|
297
|
-
# @return [Hash<String, String>]
|
298
|
-
def parse_pip_outdated(text)
|
299
|
-
text.split(/\n/).inject({}) do |memo, line|
|
300
|
-
# Example of a line:
|
301
|
-
# boto (Current: 2.25.0 Latest: 2.38.0 [wheel])
|
302
|
-
if md = line.match(/^(\S+)\s+\(.*?latest:\s+([^\s,]+).*\)$/i)
|
303
|
-
memo[md[1].downcase] = md[2]
|
304
|
-
else
|
305
|
-
Chef::Log.debug("[#{new_resource}] Unparsable line in pip outdated: #{line}")
|
306
|
-
end
|
307
|
-
memo
|
308
|
-
end
|
287
|
+
pip_command(nil, requirements, input: PIP_HACK_SCRIPT, pip_runner: %w{-})
|
309
288
|
end
|
310
289
|
|
311
290
|
# Parse the output from `pip list`. Returns a hash of package key to
|
@@ -72,7 +72,8 @@ module PoisePython
|
|
72
72
|
#
|
73
73
|
# @return [void]
|
74
74
|
def action_install
|
75
|
-
|
75
|
+
# If you have older than 7.0.0, we're re-bootstraping because lolno.
|
76
|
+
if current_resource.version && Gem::Version.create(current_resource.version) >= Gem::Version.create('7.0.0')
|
76
77
|
install_pip
|
77
78
|
else
|
78
79
|
bootstrap_pip
|
@@ -86,6 +87,7 @@ module PoisePython
|
|
86
87
|
notifying_block do
|
87
88
|
python_package 'pip' do
|
88
89
|
action :uninstall
|
90
|
+
parent_python new_resource.parent
|
89
91
|
end
|
90
92
|
end
|
91
93
|
end
|
@@ -114,7 +116,7 @@ module PoisePython
|
|
114
116
|
# al. Disable setuptools and wheel as we will install those later.
|
115
117
|
# Use the environment vars instead of CLI arguments so I don't have
|
116
118
|
# to deal with bootstrap versions that don't support --no-wheel.
|
117
|
-
|
119
|
+
poise_shell_out!([new_resource.parent.python_binary, temp.path], environment: new_resource.parent.python_environment.merge('PIP_NO_SETUPTOOLS' => '1', 'PIP_NO_WHEEL' => '1'))
|
118
120
|
end
|
119
121
|
new_pip_version = pip_version
|
120
122
|
if new_resource.version && new_pip_version != new_resource.version
|
@@ -142,6 +144,7 @@ module PoisePython
|
|
142
144
|
# Use pip to upgrade (or downgrade) itself.
|
143
145
|
python_package 'pip' do
|
144
146
|
action :upgrade
|
147
|
+
parent_python new_resource.parent
|
145
148
|
version new_resource.version if new_resource.version
|
146
149
|
end
|
147
150
|
end
|
@@ -152,7 +155,7 @@ module PoisePython
|
|
152
155
|
#
|
153
156
|
# @return [String, nil]
|
154
157
|
def pip_version
|
155
|
-
cmd =
|
158
|
+
cmd = poise_shell_out([new_resource.parent.python_binary, '-m', 'pip.__main__', '--version'], environment: new_resource.parent.python_environment)
|
156
159
|
if cmd.error?
|
157
160
|
# Not installed, probably.
|
158
161
|
nil
|
@@ -119,6 +119,11 @@ module PoisePython
|
|
119
119
|
test_import('pytest', 'pytest_venv', python: nil, virtualenv: ::File.join(new_resource.path, 'venv'))
|
120
120
|
|
121
121
|
# Create and install a requirements file.
|
122
|
+
# Running this in a venv because of pip 8.0 and Ubuntu packaing
|
123
|
+
# both requests and six.
|
124
|
+
python_virtualenv ::File.join(new_resource.path, 'venv2') do
|
125
|
+
python new_resource.name
|
126
|
+
end
|
122
127
|
file ::File.join(new_resource.path, 'requirements.txt') do
|
123
128
|
content <<-EOH
|
124
129
|
requests==2.7.0
|
@@ -126,10 +131,20 @@ six==1.8.0
|
|
126
131
|
EOH
|
127
132
|
end
|
128
133
|
pip_requirements ::File.join(new_resource.path, 'requirements.txt') do
|
134
|
+
virtualenv ::File.join(new_resource.path, 'venv2')
|
135
|
+
end
|
136
|
+
test_import('requests', python: nil, virtualenv: ::File.join(new_resource.path, 'venv2'))
|
137
|
+
test_import('six', python: nil, virtualenv: ::File.join(new_resource.path, 'venv2'))
|
138
|
+
|
139
|
+
# Install a non-latest version of a package.
|
140
|
+
python_virtualenv ::File.join(new_resource.path, 'venv3') do
|
129
141
|
python new_resource.name
|
130
142
|
end
|
131
|
-
|
132
|
-
|
143
|
+
python_package 'requests' do
|
144
|
+
version '2.8.0'
|
145
|
+
virtualenv ::File.join(new_resource.path, 'venv3')
|
146
|
+
end
|
147
|
+
test_import('requests', 'requests_version', python: nil, virtualenv: ::File.join(new_resource.path, 'venv3'))
|
133
148
|
|
134
149
|
# Create a non-root user and test installing with it.
|
135
150
|
test_user = "py#{new_resource.name}"
|
data/lib/poise_python/version.rb
CHANGED
@@ -21,15 +21,21 @@ package 'lsb-release' if platform?('debian') && node['platform_version'].start_w
|
|
21
21
|
|
22
22
|
python_runtime_test '2'
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
if node['platform'] == 'ubuntu' && node['platform_version'] == '12.04'
|
25
|
+
# Can't deal with Python 3.2 today.
|
26
|
+
file '/no_py3'
|
27
|
+
file '/no_system'
|
28
|
+
else
|
29
|
+
python_runtime_test '3'
|
27
30
|
|
28
|
-
python_runtime_test 'system' do
|
29
|
-
|
30
|
-
|
31
|
+
python_runtime_test 'system' do
|
32
|
+
version ''
|
33
|
+
runtime_provider :system
|
34
|
+
end
|
31
35
|
end
|
32
36
|
|
37
|
+
python_runtime_test 'pypy'
|
38
|
+
|
33
39
|
if platform_family?('rhel')
|
34
40
|
python_runtime_test 'scl' do
|
35
41
|
version ''
|
@@ -38,3 +44,22 @@ if platform_family?('rhel')
|
|
38
44
|
else
|
39
45
|
file '/no_scl'
|
40
46
|
end
|
47
|
+
|
48
|
+
# Specific test for pip reversion working correctly.
|
49
|
+
python_runtime 'pip1' do
|
50
|
+
pip_version '7.1.2'
|
51
|
+
provider :portable_pypy
|
52
|
+
options path: '/opt/pip1'
|
53
|
+
version ''
|
54
|
+
end
|
55
|
+
python_runtime 'pip2' do
|
56
|
+
provider :portable_pypy
|
57
|
+
options path: '/opt/pip2'
|
58
|
+
version ''
|
59
|
+
end
|
60
|
+
python_runtime 'pip2b' do
|
61
|
+
pip_version '7.1.2'
|
62
|
+
provider :portable_pypy
|
63
|
+
options path: '/opt/pip2'
|
64
|
+
version ''
|
65
|
+
end
|
@@ -79,17 +79,27 @@ RSpec.shared_examples 'a python_runtime_test' do |python_name, version=nil|
|
|
79
79
|
its(:content) { is_expected.to eq '1.8.0' }
|
80
80
|
end
|
81
81
|
end
|
82
|
+
|
83
|
+
describe 'non default version' do
|
84
|
+
assert_file('import_requests_version') do
|
85
|
+
its(:content) { is_expected.to eq '2.8.0' }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'user install' do
|
90
|
+
# assert_file('import_attrs')
|
91
|
+
end
|
82
92
|
end
|
83
93
|
|
84
|
-
describe 'python 2' do
|
94
|
+
describe 'python 2', unless: File.exist?('/no_py2') do
|
85
95
|
it_should_behave_like 'a python_runtime_test', '2', '2'
|
86
96
|
end
|
87
97
|
|
88
|
-
describe 'python 3' do
|
98
|
+
describe 'python 3', unless: File.exist?('/no_py3') do
|
89
99
|
it_should_behave_like 'a python_runtime_test', '3', '3'
|
90
100
|
end
|
91
101
|
|
92
|
-
describe 'pypy' do
|
102
|
+
describe 'pypy', unless: File.exist?('/no_pypy') do
|
93
103
|
it_should_behave_like 'a python_runtime_test', 'pypy'
|
94
104
|
end
|
95
105
|
|
@@ -100,3 +110,15 @@ end
|
|
100
110
|
describe 'scl provider', unless: File.exist?('/no_scl') do
|
101
111
|
it_should_behave_like 'a python_runtime_test', 'scl'
|
102
112
|
end
|
113
|
+
|
114
|
+
describe 'pip reversion test' do
|
115
|
+
describe command('/opt/pip1/bin/pypy -m pip --version') do
|
116
|
+
its(:exit_status) { is_expected.to eq 0 }
|
117
|
+
its(:stdout) { is_expected.to include '7.1.2' }
|
118
|
+
end
|
119
|
+
|
120
|
+
describe command('/opt/pip2/bin/pypy -m pip --version') do
|
121
|
+
its(:exit_status) { is_expected.to eq 0 }
|
122
|
+
its(:stdout) { is_expected.to include '7.1.2' }
|
123
|
+
end
|
124
|
+
end
|
@@ -39,7 +39,7 @@ describe PoisePython::Resources::PythonPackage do
|
|
39
39
|
let(:package_name) { 'foo' }
|
40
40
|
before do
|
41
41
|
stub_cmd(%w{-m pip.__main__ list}, stdout: '')
|
42
|
-
stub_cmd(%w{-
|
42
|
+
stub_cmd(%w{- foo}, input: kind_of(String), stdout: '{"foo":"1.0.0"}')
|
43
43
|
end
|
44
44
|
|
45
45
|
its(:version) { is_expected.to be nil }
|
@@ -50,7 +50,7 @@ describe PoisePython::Resources::PythonPackage do
|
|
50
50
|
let(:package_name) { %w{foo bar} }
|
51
51
|
before do
|
52
52
|
stub_cmd(%w{-m pip.__main__ list}, stdout: '')
|
53
|
-
stub_cmd(%w{-
|
53
|
+
stub_cmd(%w{- foo bar}, input: kind_of(String), stdout: '{"foo":"1.0.0","bar":"2.0.0"}')
|
54
54
|
end
|
55
55
|
|
56
56
|
its(:version) { is_expected.to eq [nil, nil] }
|
@@ -61,7 +61,7 @@ describe PoisePython::Resources::PythonPackage do
|
|
61
61
|
let(:package_name) { 'foo[bar]' }
|
62
62
|
before do
|
63
63
|
stub_cmd(%w{-m pip.__main__ list}, stdout: '')
|
64
|
-
stub_cmd(%w{-
|
64
|
+
stub_cmd(%w{- foo}, input: kind_of(String), stdout: '{"foo":"1.0.0"}')
|
65
65
|
end
|
66
66
|
|
67
67
|
its(:version) { is_expected.to be nil }
|
@@ -173,37 +173,6 @@ describe PoisePython::Resources::PythonPackage do
|
|
173
173
|
end # /describe action :remove
|
174
174
|
end # /describe actions
|
175
175
|
|
176
|
-
describe '#parse_pip_outdated' do
|
177
|
-
let(:text) { '' }
|
178
|
-
subject { test_provider.send(:parse_pip_outdated, text) }
|
179
|
-
|
180
|
-
context 'with no content' do
|
181
|
-
it { is_expected.to eq({}) }
|
182
|
-
end # /context with no content
|
183
|
-
|
184
|
-
context 'with standard content' do
|
185
|
-
let(:text) { <<-EOH }
|
186
|
-
boto (Current: 2.25.0 Latest: 2.38.0 [wheel])
|
187
|
-
botocore (Current: 0.56.0 Latest: 1.1.1 [wheel])
|
188
|
-
certifi (Current: 14.5.14 Latest: 2015.4.28 [wheel])
|
189
|
-
cffi (Current: 0.8.1 Latest: 1.1.2 [sdist])
|
190
|
-
Fabric (Current: 1.9.1 Latest: 1.10.2 [wheel])
|
191
|
-
EOH
|
192
|
-
it { is_expected.to eq({'boto' => '2.38.0', 'botocore' => '1.1.1', 'certifi' => '2015.4.28', 'cffi' => '1.1.2', 'fabric' => '1.10.2'}) }
|
193
|
-
end # /context with standard content
|
194
|
-
|
195
|
-
context 'with malformed content' do
|
196
|
-
let(:text) { <<-EOH }
|
197
|
-
boto (Current: 2.25.0 Latest: 2.38.0 [wheel])
|
198
|
-
botocore (Current: 0.56.0 Latest: 1.1.1 [wheel])
|
199
|
-
certifi (Current: 14.5.14 Latest: 2015.4.28 [wheel])
|
200
|
-
cffi (Current: 0.8.1 Latest: 1.1.2 [sdist])
|
201
|
-
Fabric (Future: 1.9.1 [wheel])
|
202
|
-
EOH
|
203
|
-
it { is_expected.to eq({'boto' => '2.38.0', 'botocore' => '1.1.1', 'certifi' => '2015.4.28', 'cffi' => '1.1.2'}) }
|
204
|
-
end # /context with malformed content
|
205
|
-
end # /describe #parse_pip_outdated
|
206
|
-
|
207
176
|
describe '#parse_pip_list' do
|
208
177
|
let(:text) { '' }
|
209
178
|
subject { test_provider.send(:parse_pip_list, text) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poise-python
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Kantrowitz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: halite
|