poise-python 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +2 -0
- data/lib/poise_python/python_command_mixin.rb +5 -1
- data/lib/poise_python/python_providers.rb +1 -0
- data/lib/poise_python/python_providers/dummy.rb +10 -1
- data/lib/poise_python/python_providers/portable_pypy.rb +1 -1
- data/lib/poise_python/python_providers/system.rb +3 -3
- data/lib/poise_python/resources/pip_requirements.rb +9 -1
- data/lib/poise_python/resources/python_package.rb +29 -6
- data/lib/poise_python/resources/python_runtime_test.rb +34 -3
- data/lib/poise_python/resources/python_virtualenv.rb +1 -1
- data/lib/poise_python/version.rb +1 -1
- data/test/integration/default/serverspec/default_spec.rb +1 -1
- data/test/spec/python_providers/portable_pypy3_spec.rb +1 -0
- data/test/spec/python_providers/portable_pypy_spec.rb +3 -2
- data/test/spec/python_providers/scl_spec.rb +1 -0
- data/test/spec/python_providers/system_spec.rb +20 -2
- data/test/spec/resources/pip_requirements_spec.rb +26 -4
- data/test/spec/resources/python_package_spec.rb +172 -1
- 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: 6f954d22962ad5f19fbefef8ce992f18bc0f8b73
|
4
|
+
data.tar.gz: 91a35461eaecb05a6e3e5dee93e9b4d551d95403
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b108843aca7b5c9f6c4db0f991c88c6179c8b91f406bcb44ae4df0b90ff02106080aa4e53610454f2ce4108c00238b973f119ce4f46cbea88a9eaef47be17c2a
|
7
|
+
data.tar.gz: 60273ff1bc570326fee7b2875210ff4f748dd0620332aeb3bbaa211a83d64ec514c63453f1c216f5444ef5f8f81817c1d286b8837c2f49e9151d3024facb6952
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Poise-Python Changelog
|
2
2
|
|
3
|
+
## v1.2.0
|
4
|
+
|
5
|
+
* Add support for passing `user` and `group` to `pip_requirements`.
|
6
|
+
* Allow passing a virtualenv resource object to the `virtualenv` property.
|
7
|
+
* Update PyPy release versions.
|
8
|
+
* Make the `python_virtualenv` resource check for `./bin/python` for idempotence
|
9
|
+
instead of the base path.
|
10
|
+
* Support for packages with extras in `python_package`.
|
11
|
+
* Support for point releases (7.1, 8.1, etc) of Debian in the `system` provider.
|
12
|
+
|
3
13
|
## v1.1.2
|
4
14
|
|
5
15
|
* Fix `PythonPackage#response_file_variables` for the Chef 12.6 initializer.
|
data/README.md
CHANGED
@@ -277,9 +277,11 @@ notifications will only be triggered if a package is actually installed.
|
|
277
277
|
|
278
278
|
* `path` – Path to the requirements file, or a folder containing the
|
279
279
|
requirements file. *(name property)*
|
280
|
+
* `group` – System group to install the packages.
|
280
281
|
* `python` – Name of the `python_runtime` resource to use. If not specified, the
|
281
282
|
most recently declared `python_runtime` will be used. Can also be set to the
|
282
283
|
full path to a `python` binary.
|
284
|
+
* `user` – System user to install the packages.
|
283
285
|
* `virtualenv` – Name of the `python_virtualenv` resource to use. This is
|
284
286
|
mutually exclusive with the `python` property.
|
285
287
|
|
@@ -34,7 +34,11 @@ module PoisePython
|
|
34
34
|
# @param name [String] Name of the virtualenv resource.
|
35
35
|
# @return [void]
|
36
36
|
def virtualenv(name)
|
37
|
-
|
37
|
+
if name.is_a?(PoisePython::Resources::PythonVirtualenv::Resource)
|
38
|
+
parent_python(name)
|
39
|
+
else
|
40
|
+
parent_python("python_virtualenv[#{name}]")
|
41
|
+
end
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
@@ -31,6 +31,7 @@ module PoisePython
|
|
31
31
|
autoload :Base, 'poise_python/python_providers/base'
|
32
32
|
|
33
33
|
Chef::Platform::ProviderPriorityMap.instance.priority(:python_runtime, [
|
34
|
+
PoisePython::PythonProviders::Dummy,
|
34
35
|
PoisePython::PythonProviders::PortablePyPy3,
|
35
36
|
PoisePython::PythonProviders::PortablePyPy,
|
36
37
|
PoisePython::PythonProviders::Scl,
|
@@ -27,9 +27,18 @@ module PoisePython
|
|
27
27
|
class Dummy < Base
|
28
28
|
provides(:dummy)
|
29
29
|
|
30
|
+
# Enable by default on ChefSpec.
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
def self.provides_auto?(node, _resource)
|
34
|
+
node.platform?('chefspec')
|
35
|
+
end
|
36
|
+
|
37
|
+
# Manual overrides for dummy data.
|
38
|
+
#
|
39
|
+
# @api private
|
30
40
|
def self.default_inversion_options(node, resource)
|
31
41
|
super.merge({
|
32
|
-
# Manual overrides for dummy data.
|
33
42
|
python_binary: ::File.join('', 'python'),
|
34
43
|
python_environment: nil,
|
35
44
|
})
|
@@ -26,7 +26,7 @@ module PoisePython
|
|
26
26
|
provides(:portable_pypy)
|
27
27
|
include PoiseLanguages::Static(
|
28
28
|
name: 'pypy',
|
29
|
-
versions: %w{2.6 2.5.1 2.5 2.4 2.3.1 2.3 2.2.1 2.2 2.1 2.0.2},
|
29
|
+
versions: %w{4.0.1 2.6.1 2.5.1 2.5 2.4 2.3.1 2.3 2.2.1 2.2 2.1 2.0.2},
|
30
30
|
machines: %w{linux-i686 linux-x86_64},
|
31
31
|
url: 'https://bitbucket.org/squeaky/portable-pypy/downloads/pypy-%{version}-%{kernel}_%{machine}-portable.tar.bz2'
|
32
32
|
)
|
@@ -28,9 +28,9 @@ module PoisePython
|
|
28
28
|
provides(:system)
|
29
29
|
packages('python', {
|
30
30
|
debian: {
|
31
|
-
'8' => %w{python3.4 python2.7},
|
32
|
-
'7' => %w{python3.2 python2.7 python2.6},
|
33
|
-
'6' => %w{python3.1 python2.6 python2.5},
|
31
|
+
'~> 8.0' => %w{python3.4 python2.7},
|
32
|
+
'~> 7.0' => %w{python3.2 python2.7 python2.6},
|
33
|
+
'~> 6.0' => %w{python3.1 python2.6 python2.5},
|
34
34
|
},
|
35
35
|
ubuntu: {
|
36
36
|
'14.04' => %w{python3.4 python2.7},
|
@@ -44,6 +44,14 @@ module PoisePython
|
|
44
44
|
# requirements file.
|
45
45
|
# @return [String]
|
46
46
|
attribute(:path, kind_of: String, name_attribute: true)
|
47
|
+
# @!attribute group
|
48
|
+
# System group to install the package.
|
49
|
+
# @return [String, Integer, nil]
|
50
|
+
attribute(:group, kind_of: [String, Integer, NilClass])
|
51
|
+
# @!attribute user
|
52
|
+
# System user to install the package.
|
53
|
+
# @return [String, Integer, nil]
|
54
|
+
attribute(:user, kind_of: [String, Integer, NilClass])
|
47
55
|
end
|
48
56
|
|
49
57
|
# The default provider for `pip_requirements`.
|
@@ -80,7 +88,7 @@ module PoisePython
|
|
80
88
|
cmd << '--upgrade' if upgrade
|
81
89
|
cmd << '--requirement'
|
82
90
|
cmd << requirements_path
|
83
|
-
output = python_shell_out!(cmd).stdout
|
91
|
+
output = python_shell_out!(cmd, user: new_resource.user, group: new_resource.group).stdout
|
84
92
|
if output.include?('Successfully installed')
|
85
93
|
new_resource.updated_by_last_action(true)
|
86
94
|
end
|
@@ -91,7 +91,6 @@ EOH
|
|
91
91
|
Poise::Helpers::ChefspecMatchers.create_matcher(:python_package, action)
|
92
92
|
end
|
93
93
|
|
94
|
-
|
95
94
|
# @!attribute group
|
96
95
|
# System group to install the package.
|
97
96
|
# @return [String, Integer, nil]
|
@@ -165,7 +164,7 @@ EOH
|
|
165
164
|
version_data[name][:current] = current
|
166
165
|
end
|
167
166
|
# Check for newer candidates.
|
168
|
-
outdated = pip_outdated(pip_requirements(resource.package_name, version)).stdout
|
167
|
+
outdated = pip_outdated(pip_requirements(resource.package_name, version, parse: true)).stdout
|
169
168
|
parse_pip_outdated(outdated).each do |name, candidate|
|
170
169
|
# Merge candidates in to the existing versions.
|
171
170
|
version_data[name][:candidate] = candidate
|
@@ -176,13 +175,13 @@ EOH
|
|
176
175
|
@candidate_version = []
|
177
176
|
versions = []
|
178
177
|
[resource.package_name].flatten.each do |name|
|
179
|
-
ver = version_data[name.downcase]
|
178
|
+
ver = version_data[parse_package_name(name).downcase]
|
180
179
|
versions << ver[:current]
|
181
180
|
@candidate_version << ver[:candidate]
|
182
181
|
end
|
183
182
|
resource.version(versions)
|
184
183
|
else
|
185
|
-
ver = version_data[resource.package_name.downcase]
|
184
|
+
ver = version_data[parse_package_name(resource.package_name).downcase]
|
186
185
|
resource.version(ver[:current])
|
187
186
|
@candidate_version = ver[:candidate]
|
188
187
|
end
|
@@ -223,11 +222,16 @@ EOH
|
|
223
222
|
# @param name [String, Array<String>] Name or names for the packages.
|
224
223
|
# @param version [String, Array<String>] Version or versions for the
|
225
224
|
# packages.
|
225
|
+
# @param parse [Boolean] Use parsed package names.
|
226
226
|
# @return [Array<String>]
|
227
|
-
def pip_requirements(name, version)
|
227
|
+
def pip_requirements(name, version, parse: false)
|
228
228
|
[name].flatten.zip([version].flatten).map do |n, v|
|
229
|
+
n = parse_package_name(n) if parse
|
229
230
|
v = v.to_s.strip
|
230
|
-
if
|
231
|
+
if n =~ /:\/\//
|
232
|
+
# Probably a URI.
|
233
|
+
n
|
234
|
+
elsif v.empty?
|
231
235
|
# No version requirement, send through unmodified.
|
232
236
|
n
|
233
237
|
elsif v =~ /^\d/
|
@@ -322,6 +326,25 @@ EOH
|
|
322
326
|
end
|
323
327
|
end
|
324
328
|
|
329
|
+
# Regexp for package URLs.
|
330
|
+
PACKAGE_NAME_URL = /:\/\/.*?#egg=(.*)$/
|
331
|
+
|
332
|
+
# Regexp for extras.
|
333
|
+
PACKAGE_NAME_EXTRA = /^(.*?)\[.*?\]$/
|
334
|
+
|
335
|
+
# Find the underlying name from a pip input sequence.
|
336
|
+
#
|
337
|
+
# @param raw_name [String] Raw package name.
|
338
|
+
# @return [String]
|
339
|
+
def parse_package_name(raw_name)
|
340
|
+
case raw_name
|
341
|
+
when PACKAGE_NAME_URL, PACKAGE_NAME_EXTRA
|
342
|
+
$1
|
343
|
+
else
|
344
|
+
raw_name
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
325
348
|
end
|
326
349
|
end
|
327
350
|
end
|
@@ -40,7 +40,7 @@ module PoisePython
|
|
40
40
|
attribute(:path, kind_of: String, default: lazy { default_path })
|
41
41
|
|
42
42
|
def default_path
|
43
|
-
::File.join('', '
|
43
|
+
::File.join('', 'opt', "python_test_#{name}")
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -58,7 +58,9 @@ module PoisePython
|
|
58
58
|
def action_run
|
59
59
|
notifying_block do
|
60
60
|
# Top level directory for this test.
|
61
|
-
directory new_resource.path
|
61
|
+
directory new_resource.path do
|
62
|
+
mode '777'
|
63
|
+
end
|
62
64
|
|
63
65
|
# Install and log the version.
|
64
66
|
python_runtime new_resource.name do
|
@@ -128,6 +130,34 @@ EOH
|
|
128
130
|
end
|
129
131
|
test_import('requests')
|
130
132
|
test_import('six')
|
133
|
+
|
134
|
+
# Create a non-root user and test installing with it.
|
135
|
+
test_user = "py#{new_resource.name}"
|
136
|
+
test_home = ::File.join('', 'home', test_user)
|
137
|
+
group test_user do
|
138
|
+
system true
|
139
|
+
end
|
140
|
+
user test_user do
|
141
|
+
comment "Test user for python_runtime_test #{new_resource.name}"
|
142
|
+
gid test_user
|
143
|
+
home test_home
|
144
|
+
shell '/bin/false'
|
145
|
+
system true
|
146
|
+
end
|
147
|
+
directory test_home do
|
148
|
+
mode '700'
|
149
|
+
group test_user
|
150
|
+
user test_user
|
151
|
+
end
|
152
|
+
test_venv = python_virtualenv ::File.join(test_home, 'env') do
|
153
|
+
python new_resource.name
|
154
|
+
user test_user
|
155
|
+
end
|
156
|
+
python_package 'attrs' do
|
157
|
+
user test_user
|
158
|
+
virtualenv test_venv
|
159
|
+
end
|
160
|
+
test_import('attrs', 'attr', python: nil, virtualenv: test_venv, user: test_user)
|
131
161
|
end
|
132
162
|
end
|
133
163
|
|
@@ -157,7 +187,7 @@ EOH
|
|
157
187
|
end
|
158
188
|
end
|
159
189
|
|
160
|
-
def test_import(name, path=name, python: new_resource.name, virtualenv: nil)
|
190
|
+
def test_import(name, path=name, python: new_resource.name, virtualenv: nil, user: nil)
|
161
191
|
# Only queue up this resource once, the ivar is just for tracking.
|
162
192
|
@python_import_test ||= file ::File.join(new_resource.path, 'import_version.py') do
|
163
193
|
user 'root'
|
@@ -175,6 +205,7 @@ EOH
|
|
175
205
|
|
176
206
|
python_execute "#{@python_import_test.path} #{name} #{::File.join(new_resource.path, "import_#{path}")}" do
|
177
207
|
python python if python
|
208
|
+
user user if user
|
178
209
|
virtualenv virtualenv if virtualenv
|
179
210
|
end
|
180
211
|
end
|
data/lib/poise_python/version.rb
CHANGED
@@ -20,7 +20,7 @@ set :backend, :exec
|
|
20
20
|
# Set up the shared example for python_runtime_test.
|
21
21
|
RSpec.shared_examples 'a python_runtime_test' do |python_name, version=nil|
|
22
22
|
let(:python_name) { python_name }
|
23
|
-
let(:python_path) { File.join('', '
|
23
|
+
let(:python_path) { File.join('', 'opt', "python_test_#{python_name}") }
|
24
24
|
# Helper for all the file checks.
|
25
25
|
def self.assert_file(rel_path, should_exist=true, &block)
|
26
26
|
describe rel_path do
|
@@ -24,6 +24,7 @@ describe PoisePython::PythonProviders::PortablePyPy do
|
|
24
24
|
step_into(:python_runtime)
|
25
25
|
recipe do
|
26
26
|
python_runtime 'test' do
|
27
|
+
provider_no_auto 'dummy'
|
27
28
|
version node['poise_python_version']
|
28
29
|
virtualenv_version false
|
29
30
|
end
|
@@ -37,7 +38,7 @@ describe PoisePython::PythonProviders::PortablePyPy do
|
|
37
38
|
|
38
39
|
context 'with version pypy' do
|
39
40
|
let(:python_version) { 'pypy' }
|
40
|
-
it_behaves_like 'portablepypy provider', 'pypy-
|
41
|
+
it_behaves_like 'portablepypy provider', 'pypy-4.0.1'
|
41
42
|
end # /context with version pypy
|
42
43
|
|
43
44
|
context 'with version pypy-2.4' do
|
@@ -53,6 +54,6 @@ describe PoisePython::PythonProviders::PortablePyPy do
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
it { is_expected.to uninstall_poise_languages_static('/opt/pypy-
|
57
|
+
it { is_expected.to uninstall_poise_languages_static('/opt/pypy-4.0.1') }
|
57
58
|
end # /context action :uninstall
|
58
59
|
end
|
@@ -25,14 +25,15 @@ describe PoisePython::PythonProviders::System do
|
|
25
25
|
step_into(:python_runtime)
|
26
26
|
recipe do
|
27
27
|
python_runtime 'test' do
|
28
|
+
provider_no_auto 'dummy'
|
28
29
|
version node['poise_python_version']
|
29
30
|
virtualenv_version false
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
|
-
shared_examples_for 'system provider' do |candidates, pkg|
|
34
|
+
shared_examples_for 'system provider' do |candidates=nil, pkg|
|
34
35
|
it { expect(python_runtime.provider_for_action(:install)).to be_a described_class }
|
35
|
-
it { expect(system_package_candidates).to eq candidates }
|
36
|
+
it { expect(system_package_candidates).to eq candidates } if candidates
|
36
37
|
it { is_expected.to install_poise_languages_system(pkg) }
|
37
38
|
it do
|
38
39
|
expect_any_instance_of(described_class).to receive(:install_system_packages)
|
@@ -64,6 +65,23 @@ describe PoisePython::PythonProviders::System do
|
|
64
65
|
it_behaves_like 'system provider', %w{python2.3 python23 python}, 'python2.3'
|
65
66
|
end # /context with version 2.3
|
66
67
|
|
68
|
+
context 'on Debian 8.1' do
|
69
|
+
before { chefspec_options.update(platform: 'debian', version: '8.1') }
|
70
|
+
it_behaves_like 'system provider', 'python3.4'
|
71
|
+
end # /context on Debian 8.1
|
72
|
+
|
73
|
+
context 'on CentOS 7' do
|
74
|
+
before { chefspec_options.update(platform: 'centos', version: '7.0') }
|
75
|
+
recipe do
|
76
|
+
python_runtime 'test' do
|
77
|
+
provider :system
|
78
|
+
version node['poise_python_version']
|
79
|
+
virtualenv_version false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
it_behaves_like 'system provider', 'python'
|
83
|
+
end # /context on Debian 8.1
|
84
|
+
|
67
85
|
context 'action :uninstall' do
|
68
86
|
recipe do
|
69
87
|
python_runtime 'test' do
|
@@ -17,19 +17,20 @@
|
|
17
17
|
require 'spec_helper'
|
18
18
|
|
19
19
|
describe PoisePython::Resources::PipRequirements do
|
20
|
-
let(:pip_cmd) { }
|
20
|
+
let(:pip_cmd) { %w{-m pip.__main__ install --requirement /test/requirements.txt} }
|
21
21
|
let(:pip_output) { '' }
|
22
|
+
let(:pip_user) { nil }
|
23
|
+
let(:pip_group) { nil }
|
22
24
|
step_into(:pip_requirements)
|
23
25
|
before do
|
24
26
|
allow(File).to receive(:directory?).and_return(false)
|
25
27
|
allow(File).to receive(:directory?).with('/test').and_return(true)
|
26
28
|
end
|
27
29
|
before do
|
28
|
-
expect_any_instance_of(PoisePython::Resources::PipRequirements::Provider).to receive(:python_shell_out!).with(pip_cmd).and_return(double(stdout: pip_output))
|
30
|
+
expect_any_instance_of(PoisePython::Resources::PipRequirements::Provider).to receive(:python_shell_out!).with(pip_cmd, {user: pip_user, group: pip_group}).and_return(double(stdout: pip_output))
|
29
31
|
end
|
30
32
|
|
31
33
|
context 'with a directory' do
|
32
|
-
let(:pip_cmd) { %w{-m pip.__main__ install --requirement /test/requirements.txt} }
|
33
34
|
recipe do
|
34
35
|
pip_requirements '/test'
|
35
36
|
end
|
@@ -46,6 +47,28 @@ describe PoisePython::Resources::PipRequirements do
|
|
46
47
|
it { is_expected.to install_pip_requirements('/test/reqs.txt') }
|
47
48
|
end # /context with a file
|
48
49
|
|
50
|
+
context 'with a user' do
|
51
|
+
let(:pip_user) { 'testuser' }
|
52
|
+
recipe do
|
53
|
+
pip_requirements '/test' do
|
54
|
+
user 'testuser'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it { is_expected.to install_pip_requirements('/test') }
|
59
|
+
end # /context with a user
|
60
|
+
|
61
|
+
context 'with a group' do
|
62
|
+
let(:pip_group) { 'testgroup' }
|
63
|
+
recipe do
|
64
|
+
pip_requirements '/test' do
|
65
|
+
group 'testgroup'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it { is_expected.to install_pip_requirements('/test') }
|
70
|
+
end # /context with a group
|
71
|
+
|
49
72
|
context 'action :upgrade' do
|
50
73
|
let(:pip_cmd) { %w{-m pip.__main__ install --upgrade --requirement /test/requirements.txt} }
|
51
74
|
recipe do
|
@@ -58,7 +81,6 @@ describe PoisePython::Resources::PipRequirements do
|
|
58
81
|
end # /context action :upgrade
|
59
82
|
|
60
83
|
context 'with output' do
|
61
|
-
let(:pip_cmd) { %w{-m pip.__main__ install --requirement /test/requirements.txt} }
|
62
84
|
let(:pip_output) { 'Successfully installed' }
|
63
85
|
recipe do
|
64
86
|
pip_requirements '/test'
|
@@ -21,7 +21,157 @@ describe PoisePython::Resources::PythonPackage do
|
|
21
21
|
end # /describe PoisePython::Resources::PythonPackage::Resource
|
22
22
|
|
23
23
|
describe PoisePython::Resources::PythonPackage::Provider do
|
24
|
-
let(:
|
24
|
+
let(:test_resource) { nil }
|
25
|
+
let(:test_provider) { described_class.new(test_resource, chef_run.run_context) }
|
26
|
+
def stub_cmd(cmd, **options)
|
27
|
+
output_options = {error?: options.delete(:error?) || false, stdout: options.delete(:stdout) || '', stderr: options.delete(:stderr) || ''}
|
28
|
+
expect(test_provider).to receive(:python_shell_out!).with(cmd, options).and_return(double("python #{cmd} return", **output_options))
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#load_current_resource' do
|
32
|
+
let(:package_name) { nil }
|
33
|
+
let(:package_version) { nil }
|
34
|
+
let(:test_resource) { PoisePython::Resources::PythonPackage::Resource.new(package_name, chef_run.run_context).tap {|r| r.version(package_version) if package_version } }
|
35
|
+
let(:candidate_version) { subject; test_provider.candidate_version }
|
36
|
+
subject { test_provider.load_current_resource }
|
37
|
+
|
38
|
+
context 'with package_name foo' do
|
39
|
+
let(:package_name) { 'foo' }
|
40
|
+
before do
|
41
|
+
stub_cmd(%w{-m pip.__main__ list}, stdout: '')
|
42
|
+
stub_cmd(%w{- list --outdated foo}, input: kind_of(String), stdout: "foo (Current: 0 Latest: 1.0.0 [wheel])\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
its(:version) { is_expected.to be nil }
|
46
|
+
it { expect(candidate_version).to eq '1.0.0' }
|
47
|
+
end # /context with package_name foo
|
48
|
+
|
49
|
+
context 'with package_name ["foo", "bar"]' do
|
50
|
+
let(:package_name) { %w{foo bar} }
|
51
|
+
before do
|
52
|
+
stub_cmd(%w{-m pip.__main__ list}, stdout: '')
|
53
|
+
stub_cmd(%w{- list --outdated foo bar}, input: kind_of(String), stdout: "foo (Current: 0 Latest: 1.0.0 [wheel])\nbar (Current: 0 Latest: 2.0.0 [wheel])\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
its(:version) { is_expected.to eq [nil, nil] }
|
57
|
+
it { expect(candidate_version).to eq %w{1.0.0 2.0.0} }
|
58
|
+
end # /context with package_name ["foo", "bar"]
|
59
|
+
|
60
|
+
context 'with a package with extras' do
|
61
|
+
let(:package_name) { 'foo[bar]' }
|
62
|
+
before do
|
63
|
+
stub_cmd(%w{-m pip.__main__ list}, stdout: '')
|
64
|
+
stub_cmd(%w{- list --outdated foo}, input: kind_of(String), stdout: "foo (Current: 0 Latest: 1.0.0 [wheel])\n")
|
65
|
+
end
|
66
|
+
|
67
|
+
its(:version) { is_expected.to be nil }
|
68
|
+
it { expect(candidate_version).to eq '1.0.0' }
|
69
|
+
end # /context with a package with extras
|
70
|
+
end # /describe #load_current_resource
|
71
|
+
|
72
|
+
describe 'actions' do
|
73
|
+
let(:package_name) { nil }
|
74
|
+
let(:current_version) { nil }
|
75
|
+
let(:candidate_version) { nil }
|
76
|
+
let(:test_resource) { PoisePython::Resources::PythonPackage::Resource.new(package_name, chef_run.run_context) }
|
77
|
+
subject { test_provider.run_action }
|
78
|
+
before do
|
79
|
+
current_version = self.current_version
|
80
|
+
candidate_version = self.candidate_version
|
81
|
+
allow(test_provider).to receive(:load_current_resource) do
|
82
|
+
current_resource = double('current_resource', package_name: package_name, version: current_version)
|
83
|
+
test_provider.instance_eval do
|
84
|
+
@current_resource = current_resource
|
85
|
+
@candidate_version = candidate_version
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'action :install' do
|
91
|
+
before { test_provider.action = :install }
|
92
|
+
|
93
|
+
context 'with package_name foo' do
|
94
|
+
let(:package_name) { 'foo' }
|
95
|
+
let(:candidate_version) { '1.0.0' }
|
96
|
+
it do
|
97
|
+
stub_cmd(%w{-m pip.__main__ install foo==1.0.0})
|
98
|
+
subject
|
99
|
+
end
|
100
|
+
end # /context with package_name foo
|
101
|
+
|
102
|
+
context 'with package_name ["foo", "bar"]' do
|
103
|
+
let(:package_name) { %w{foo bar} }
|
104
|
+
let(:candidate_version) { %w{1.0.0 2.0.0} }
|
105
|
+
it do
|
106
|
+
stub_cmd(%w{-m pip.__main__ install foo==1.0.0 bar==2.0.0})
|
107
|
+
subject
|
108
|
+
end
|
109
|
+
end # /context with package_name ["foo", "bar"]
|
110
|
+
|
111
|
+
context 'with options' do
|
112
|
+
let(:package_name) { 'foo' }
|
113
|
+
let(:candidate_version) { '1.0.0' }
|
114
|
+
before { test_resource.options('--editable') }
|
115
|
+
it do
|
116
|
+
stub_cmd('-m pip.__main__ install --editable foo\\=\\=1.0.0')
|
117
|
+
subject
|
118
|
+
end
|
119
|
+
end # /context with options
|
120
|
+
|
121
|
+
context 'with a package with extras' do
|
122
|
+
let(:package_name) { 'foo[bar]' }
|
123
|
+
let(:candidate_version) { '1.0.0' }
|
124
|
+
it do
|
125
|
+
stub_cmd(%w{-m pip.__main__ install foo[bar]==1.0.0})
|
126
|
+
subject
|
127
|
+
end
|
128
|
+
end # /context with a package with extras
|
129
|
+
end # /describe action :install
|
130
|
+
|
131
|
+
describe 'action :upgrade' do
|
132
|
+
before { test_provider.action = :upgrade }
|
133
|
+
|
134
|
+
context 'with package_name foo' do
|
135
|
+
let(:package_name) { 'foo' }
|
136
|
+
let(:candidate_version) { '1.0.0' }
|
137
|
+
it do
|
138
|
+
stub_cmd(%w{-m pip.__main__ install --upgrade foo==1.0.0})
|
139
|
+
subject
|
140
|
+
end
|
141
|
+
end # /context with package_name foo
|
142
|
+
|
143
|
+
context 'with package_name ["foo", "bar"]' do
|
144
|
+
let(:package_name) { %w{foo bar} }
|
145
|
+
let(:candidate_version) { %w{1.0.0 2.0.0} }
|
146
|
+
it do
|
147
|
+
stub_cmd(%w{-m pip.__main__ install --upgrade foo==1.0.0 bar==2.0.0})
|
148
|
+
subject
|
149
|
+
end
|
150
|
+
end # /context with package_name ["foo", "bar"]
|
151
|
+
end # /describe action :upgrade
|
152
|
+
|
153
|
+
describe 'action :remove' do
|
154
|
+
before { test_provider.action = :remove }
|
155
|
+
|
156
|
+
context 'with package_name foo' do
|
157
|
+
let(:package_name) { 'foo' }
|
158
|
+
let(:current_version) { '1.0.0' }
|
159
|
+
it do
|
160
|
+
stub_cmd(%w{-m pip.__main__ uninstall --yes foo})
|
161
|
+
subject
|
162
|
+
end
|
163
|
+
end # /context with package_name foo
|
164
|
+
|
165
|
+
context 'with package_name ["foo", "bar"]' do
|
166
|
+
let(:package_name) { %w{foo bar} }
|
167
|
+
let(:current_version) { %w{1.0.0 2.0.0} }
|
168
|
+
it do
|
169
|
+
stub_cmd(%w{-m pip.__main__ uninstall --yes foo bar})
|
170
|
+
subject
|
171
|
+
end
|
172
|
+
end # /context with package_name ["foo", "bar"]
|
173
|
+
end # /describe action :remove
|
174
|
+
end # /describe actions
|
25
175
|
|
26
176
|
describe '#parse_pip_outdated' do
|
27
177
|
let(:text) { '' }
|
@@ -41,6 +191,17 @@ Fabric (Current: 1.9.1 Latest: 1.10.2 [wheel])
|
|
41
191
|
EOH
|
42
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'}) }
|
43
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
|
44
205
|
end # /describe #parse_pip_outdated
|
45
206
|
|
46
207
|
describe '#parse_pip_list' do
|
@@ -60,6 +221,16 @@ flake8 (2.1.0.dev0)
|
|
60
221
|
EOH
|
61
222
|
it { is_expected.to eq({'eventlet' => '0.12.1', 'fabric' => '1.9.1', 'fabric-rundeck' => '1.2', 'flake8' => '2.1.0.dev0'}) }
|
62
223
|
end # /context with standard content
|
224
|
+
|
225
|
+
context 'with malformed content' do
|
226
|
+
let(:text) { <<-EOH }
|
227
|
+
eventlet (0.12.1)
|
228
|
+
Fabric (1.9.1)
|
229
|
+
fabric-rundeck (1.2, /Users/coderanger/src/bal/fabric-rundeck)
|
230
|
+
flake 8 (2.1.0.dev0)
|
231
|
+
EOH
|
232
|
+
it { is_expected.to eq({'eventlet' => '0.12.1', 'fabric' => '1.9.1', 'fabric-rundeck' => '1.2'}) }
|
233
|
+
end # /context with malformed content
|
63
234
|
end # /describe #parse_pip_list
|
64
235
|
end # /describe PoisePython::Resources::PythonPackage::Provider
|
65
236
|
end
|
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.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Kantrowitz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: halite
|