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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6f954d22962ad5f19fbefef8ce992f18bc0f8b73
4
- data.tar.gz: 91a35461eaecb05a6e3e5dee93e9b4d551d95403
3
+ metadata.gz: bef0f55828842107d9397608ee63c0a08007f6d4
4
+ data.tar.gz: 05b4a93226b282e4b1708f7ec29d7b9f40d6baad
5
5
  SHA512:
6
- metadata.gz: b108843aca7b5c9f6c4db0f991c88c6179c8b91f406bcb44ae4df0b90ff02106080aa4e53610454f2ce4108c00238b973f119ce4f46cbea88a9eaef47be17c2a
7
- data.tar.gz: 60273ff1bc570326fee7b2875210ff4f748dd0620332aeb3bbaa211a83d64ec514c63453f1c216f5444ef5f8f81817c1d286b8837c2f49e9151d3024facb6952
6
+ metadata.gz: d7084145bf568d242e6c33a1a8560d23ff49de234b2c3e9358e5cee8478dc26ebdd7259db6f86d43db7ab3693efe05d99d5d14cb117e01f892a184b8eed19a93
7
+ data.tar.gz: 55016a0d57459240bfd38c140628e743011beccfce1130dd6fbb09baa8b8a4221090b8c64e91423bfdf156394d2909104e368552b1f7796f14686205dbfcd21e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Poise-Python Changelog
2
2
 
3
+ ## v1.2.1
4
+
5
+ * Compatibility with Pip 8.0.
6
+
3
7
  ## v1.2.0
4
8
 
5
9
  * Add support for passing `user` and `group` to `pip_requirements`.
@@ -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 hack pip a bit so `pip list --outdated` will show
33
- # only the things we want and will understand version requirements.
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 pip
39
- try:
40
- # >= 6.0
41
- from pip.utils import get_installed_distributions
42
- except ImportError:
43
- # <= 1.5.6
44
- from pip.util import get_installed_distributions
45
-
46
- def replacement(*args, **kwargs):
47
- import copy, sys
48
- from pip._vendor import pkg_resources
49
- dists = []
50
- for raw_req in sys.argv[3:]:
51
- if raw_req.startswith('-'):
52
- continue
53
- req = pkg_resources.Requirement.parse(raw_req)
54
- dist = pkg_resources.working_set.by_key.get(req.key)
55
- if dist:
56
- # Don't mutate stuff from the global working set.
57
- dist = copy.copy(dist)
58
- else:
59
- # Make a fake one.
60
- dist = pkg_resources.Distribution(project_name=req.key, version='0')
61
- # Fool the .key property into using our string.
62
- dist._key = raw_req
63
- dists.append(dist)
64
- return dists
65
- try:
66
- # For Python 2.
67
- get_installed_distributions.func_code = replacement.func_code
68
- except AttributeError:
69
- # For Python 3.
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
- parse_pip_outdated(outdated).each do |name, candidate|
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('list', %w{--outdated} + requirements, input: PIP_HACK_SCRIPT, pip_runner: %w{-})
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
- if current_resource.version
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
- shell_out!([new_resource.parent.python_binary, temp.path], environment: new_resource.parent.python_environment.merge('PIP_NO_SETUPTOOLS' => '1', 'PIP_NO_WHEEL' => '1'))
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 = shell_out([new_resource.parent.python_binary, '-m', 'pip.__main__', '--version'], environment: new_resource.parent.python_environment)
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
- test_import('requests')
132
- test_import('six')
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}"
@@ -16,5 +16,5 @@
16
16
 
17
17
 
18
18
  module PoisePython
19
- VERSION = '1.2.0'
19
+ VERSION = '1.2.1'
20
20
  end
@@ -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
- python_runtime_test '3'
25
-
26
- python_runtime_test 'pypy'
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
- version ''
30
- runtime_provider :system
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{- list --outdated foo}, input: kind_of(String), stdout: "foo (Current: 0 Latest: 1.0.0 [wheel])\n")
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{- 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")
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{- list --outdated foo}, input: kind_of(String), stdout: "foo (Current: 0 Latest: 1.0.0 [wheel])\n")
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.0
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-15 00:00:00.000000000 Z
11
+ date: 2016-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: halite