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 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