poise-python 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|