Merge lp:~sergiusens/snapcraft/pull-python-projects into lp:~snappy-dev/snapcraft/core

Proposed by Sergio Schvezov on 2015-09-23
Status: Merged
Approved by: John Lenton on 2015-09-23
Approved revision: 204
Merged at revision: 202
Proposed branch: lp:~sergiusens/snapcraft/pull-python-projects
Merge into: lp:~snappy-dev/snapcraft/core
Diff against target: 407 lines (+133/-152)
11 files modified
integration-tests/data/pip-requirements/snapcraft.yaml (+2/-2)
plugins/python2-project.yaml (+3/-3)
plugins/python2.yaml (+0/-3)
plugins/python3-project.yaml (+3/-3)
plugins/python3.yaml (+0/-3)
runtests.sh (+1/-1)
snapcraft/cmds.py (+2/-0)
snapcraft/plugins/python2.py (+0/-63)
snapcraft/plugins/python2_project.py (+60/-4)
snapcraft/plugins/python3.py (+0/-65)
snapcraft/plugins/python3_project.py (+62/-5)
To merge this branch: bzr merge lp:~sergiusens/snapcraft/pull-python-projects
Reviewer Review Type Date Requested Status
John Lenton 2015-09-23 Approve on 2015-09-23
Review via email: mp+272057@code.launchpad.net

Commit Message

Make the py 2 and 3 projects smarter and have dependencies pulled during the pull phase

Description of the Change

This is a side effect of needing internet access only done during the pull phases of the lifecycle to comply with launchpad.

It would be possible if the python2 or python3 plugins could be staged before running the pull cycle for the corresponding -project ones. Since this is not a viable alternative, moving everything to the py projects is what was done.

To post a comment you must log in.
201. By Sergio Schvezov on 2015-09-23

be smarter about origin of setup.py

202. By Sergio Schvezov on 2015-09-23

simplify complexity a tiny insy bit

203. By Sergio Schvezov on 2015-09-23

goof requirement

204. By Sergio Schvezov on 2015-09-23

Merging trunk

John Lenton (chipaca) wrote :

lgtm.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'integration-tests/data/pip-requirements/snapcraft.yaml'
2--- integration-tests/data/pip-requirements/snapcraft.yaml 2015-09-09 20:19:12 +0000
3+++ integration-tests/data/pip-requirements/snapcraft.yaml 2015-09-23 12:25:26 +0000
4@@ -7,8 +7,8 @@
5
6 parts:
7 python2:
8- type: python2
9+ type: python2-project
10 requirements: requirements.txt
11 python3:
12- type: python3
13+ type: python3-project
14 requirements: requirements.txt
15
16=== modified file 'plugins/python2-project.yaml'
17--- plugins/python2-project.yaml 2015-09-22 03:08:07 +0000
18+++ plugins/python2-project.yaml 2015-09-23 12:25:26 +0000
19@@ -1,8 +1,8 @@
20-requires:
21- - python2
22 options:
23+ requirements:
24+ required: false
25 source:
26- required: true
27+ required: false
28 source-type:
29 source-tag:
30 source-branch:
31
32=== removed file 'plugins/python2.yaml'
33--- plugins/python2.yaml 2015-09-01 14:10:18 +0000
34+++ plugins/python2.yaml 1970-01-01 00:00:00 +0000
35@@ -1,3 +0,0 @@
36-options:
37- requirements:
38- required: false
39
40=== modified file 'plugins/python3-project.yaml'
41--- plugins/python3-project.yaml 2015-09-22 03:08:07 +0000
42+++ plugins/python3-project.yaml 2015-09-23 12:25:26 +0000
43@@ -1,8 +1,8 @@
44-requires:
45- - python3
46 options:
47+ requirements:
48+ required: false
49 source:
50- required: true
51+ required: false
52 source-type:
53 source-tag:
54 source-branch:
55
56=== removed file 'plugins/python3.yaml'
57--- plugins/python3.yaml 2015-09-09 21:35:18 +0000
58+++ plugins/python3.yaml 1970-01-01 00:00:00 +0000
59@@ -1,3 +0,0 @@
60-options:
61- requirements:
62- required: false
63
64=== modified file 'runtests.sh'
65--- runtests.sh 2015-09-18 09:10:52 +0000
66+++ runtests.sh 2015-09-23 12:25:26 +0000
67@@ -54,7 +54,7 @@
68
69 # mccabe in 'warning' mode as we have high complexity
70 mccabe_list=
71- for unit in $(find . -type f -name '*.py')
72+ for unit in $(find snapcraft -type f -name '*.py')
73 do
74 output=$(python3 -m mccabe --min 10 "$unit")
75 [ -n "$output" ] && mccabe_list="- $unit:\n $output\n$mccabe_list"
76
77=== modified file 'snapcraft/cmds.py'
78--- snapcraft/cmds.py 2015-09-21 19:20:43 +0000
79+++ snapcraft/cmds.py 2015-09-23 12:25:26 +0000
80@@ -267,6 +267,8 @@
81 for f in common:
82 this = os.path.join(part.installdir, f)
83 other = os.path.join(parts_files[other_part_name]['installdir'], f)
84+ if os.path.islink(this) and os.path.islink(other):
85+ continue
86 if not filecmp.cmp(this, other, shallow=False):
87 conflict_files.append(f)
88
89
90=== removed file 'snapcraft/plugins/python2.py'
91--- snapcraft/plugins/python2.py 2015-09-18 21:23:40 +0000
92+++ snapcraft/plugins/python2.py 1970-01-01 00:00:00 +0000
93@@ -1,63 +0,0 @@
94-# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
95-#
96-# Copyright (C) 2015 Canonical Ltd
97-#
98-# This program is free software: you can redistribute it and/or modify
99-# it under the terms of the GNU General Public License version 3 as
100-# published by the Free Software Foundation.
101-#
102-# This program is distributed in the hope that it will be useful,
103-# but WITHOUT ANY WARRANTY; without even the implied warranty of
104-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105-# GNU General Public License for more details.
106-#
107-# You should have received a copy of the GNU General Public License
108-# along with this program. If not, see <http://www.gnu.org/licenses/>.
109-
110-import os
111-import snapcraft
112-
113-
114-class Python2Plugin(snapcraft.BasePlugin):
115-
116- _PLUGIN_STAGE_PACKAGES = [
117- 'python-dev',
118- 'python-setuptools',
119- ]
120-
121- def __init__(self, name, options):
122- if options.requirements:
123- self.requirements = options.requirements
124- self._PLUGIN_STAGE_PACKAGES.extend(['python-pkg-resources', 'python-setuptools'])
125- else:
126- self.requirements = None
127- super().__init__(name, options)
128-
129- def snap_fileset(self):
130- return [
131- '-usr/share',
132- ]
133-
134- # note that we don't need to set PYTHONHOME here,
135- # python discovers this automatically from it installed
136- # location. And PATH is automatically set by snapcraft.
137-
138- def env(self, root):
139- return ["PYTHONPATH=%s" % os.path.join(
140- root, 'usr', 'lib', self.python_version, 'dist-packages')]
141-
142- def pull(self):
143- # A nice idea here would be to be asking setup tools
144- # to use the deb layout, but that doesn't work with
145- # prefix sadly
146-
147- if self.requirements and not (self.run(
148- ['ln', '-s', os.path.join(self.installdir, 'usr', 'lib', self.python_version, 'dist-packages'), os.path.join(self.installdir, 'usr', 'lib', self.python_version, 'site-packages')]) and self.run(
149- ['python2', os.path.join(self.installdir, 'usr', 'bin', 'easy_install'), '--prefix', os.path.join(self.installdir, 'usr'), 'pip']) and self.run(
150- ['python2', os.path.join(self.installdir, 'usr', 'bin', 'pip2'), 'install', '--target', os.path.join(self.installdir, 'usr', 'lib', self.python_version, 'site-packages'), '--requirement', os.path.join(os.getcwd(), self.requirements)])):
151- return False
152- return True
153-
154- @property
155- def python_version(self):
156- return self.run_output(['pyversions', '-i'])
157
158=== modified file 'snapcraft/plugins/python2_project.py'
159--- snapcraft/plugins/python2_project.py 2015-09-22 23:14:22 +0000
160+++ snapcraft/plugins/python2_project.py 2015-09-23 12:25:26 +0000
161@@ -22,20 +22,76 @@
162
163 class Python2ProjectPlugin(snapcraft.BasePlugin):
164
165- # note that we don't need to setup env(), python figures it out
166- # see python2.py for more details
167+ _PLUGIN_STAGE_PACKAGES = [
168+ 'python-dev',
169+ 'python-pkg-resources',
170+ 'python-setuptools',
171+ ]
172+
173+ def __init__(self, name, options):
174+ super().__init__(name, options)
175+ self.requirements = options.requirements
176+ self.source = options.source
177+
178+ def env(self, root):
179+ return ["PYTHONPATH=%s" % os.path.join(
180+ root, 'usr', 'lib', self.python_version, 'dist-packages')]
181
182 def pull(self):
183- return self.handle_source_options()
184+ if self.source and not self.handle_source_options():
185+ return False
186+
187+ return self._pip()
188+
189+ def _pip(self):
190+ setup = 'setup.py'
191+ if os.listdir(self.sourcedir):
192+ setup = os.path.join(self.sourcedir, 'setup.py')
193+
194+ if self.requirements:
195+ requirements = os.path.join(os.getcwd(), self.requirements)
196+
197+ if not os.path.exists(setup) and not self.requirements:
198+ return True
199+
200+ easy_install = os.path.join(
201+ self.installdir, 'usr', 'bin', 'easy_install')
202+ prefix = os.path.join(self.installdir, 'usr')
203+ site_packages_dir = os.path.join(
204+ prefix, 'lib', self.python_version, 'site-packages')
205+
206+ if not os.path.exists(site_packages_dir):
207+ os.symlink(
208+ os.path.join(prefix, 'lib', self.python_version, 'dist-packages'),
209+ site_packages_dir)
210+
211+ if not self.run(['python2', easy_install, '--prefix', prefix, 'pip']):
212+ return False
213+
214+ pip2 = os.path.join(self.installdir, 'usr', 'bin', 'pip2')
215+ pip_install = ['python2', pip2, 'install', '--target',
216+ site_packages_dir]
217+
218+ if self.requirements and not self.run(
219+ pip_install + ['--requirement', requirements]):
220+ return False
221+
222+ if os.path.exists(setup) and not self.run(pip_install + ['.', ]):
223+ return False
224+
225+ return True
226
227 def build(self):
228 # If setuptools is used, it tries to create files in the
229 # dist-packages dir and import from there, so it needs to exist
230 # and be in the PYTHONPATH. It's harmless if setuptools isn't
231 # used.
232+
233+ if not os.path.exists(os.path.join(self.builddir, 'setup.py')):
234+ return True
235+
236 os.makedirs(self.dist_packages_dir, exist_ok=True)
237 setuptemp = self.copy_setup()
238-
239 return self.run(
240 ['python2', setuptemp.name, 'install', '--install-layout=deb',
241 '--prefix={}/usr'.format(self.installdir)], cwd=self.builddir)
242
243=== removed file 'snapcraft/plugins/python3.py'
244--- snapcraft/plugins/python3.py 2015-09-18 21:23:40 +0000
245+++ snapcraft/plugins/python3.py 1970-01-01 00:00:00 +0000
246@@ -1,65 +0,0 @@
247-# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
248-#
249-# Copyright (C) 2015 Canonical Ltd
250-#
251-# This program is free software: you can redistribute it and/or modify
252-# it under the terms of the GNU General Public License version 3 as
253-# published by the Free Software Foundation.
254-#
255-# This program is distributed in the hope that it will be useful,
256-# but WITHOUT ANY WARRANTY; without even the implied warranty of
257-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
258-# GNU General Public License for more details.
259-#
260-# You should have received a copy of the GNU General Public License
261-# along with this program. If not, see <http://www.gnu.org/licenses/>.
262-
263-import os
264-import snapcraft
265-
266-
267-class Python3Plugin(snapcraft.BasePlugin):
268-
269- _PLUGIN_STAGE_PACKAGES = [
270- 'python3-dev',
271- 'python3-setuptools',
272- ]
273-
274- def __init__(self, name, options):
275- if options.requirements:
276- self.requirements = options.requirements
277- self._PLUGIN_STAGE_PACKAGES.extend(['python3-pkg-resources', 'python3-setuptools'])
278- else:
279- self.requirements = None
280- super().__init__(name, options)
281-
282- def snap_fileset(self):
283- return [
284- '-usr/share',
285- ]
286-
287- # note that we don't need to set PYTHONHOME here,
288- # python discovers this automatically from it installed
289- # location, see https://code.launchpad.net/~mvo/snapcraft/python3-project/+merge/264521/comments/664308
290- #
291- # PATH is automatically set by snapcraft
292-
293- def env(self, root):
294- return ["PYTHONPATH=%s" % os.path.join(
295- root, 'usr', 'lib', 'python3', 'dist-packages')]
296-
297- def pull(self):
298- # A nice idea here would be to be asking setup tools
299- # to use the deb layout, but that doesn't work with
300- # prefix sadly
301-
302- if self.requirements and not (self.run(
303- ['ln', '-s', os.path.join(self.installdir, 'usr', 'lib', 'python3', 'dist-packages'), os.path.join(self.installdir, 'usr', 'lib', self.python_version, 'site-packages')]) and self.run(
304- ['python3', os.path.join(self.installdir, 'usr', 'bin', 'easy_install3'), '--prefix', os.path.join(self.installdir, 'usr'), 'pip']) and self.run(
305- ['python3', os.path.join(self.installdir, 'usr', 'bin', 'pip3'), 'install', '--target', os.path.join(self.installdir, 'usr', 'lib', self.python_version, 'site-packages'), '--requirement', os.path.join(os.getcwd(), self.requirements)])):
306- return False
307- return True
308-
309- @property
310- def python_version(self):
311- return self.run_output(['py3versions', '-i'])
312
313=== modified file 'snapcraft/plugins/python3_project.py'
314--- snapcraft/plugins/python3_project.py 2015-09-21 22:22:36 +0000
315+++ snapcraft/plugins/python3_project.py 2015-09-23 12:25:26 +0000
316@@ -22,21 +22,74 @@
317
318 class Python3ProjectPlugin(snapcraft.BasePlugin):
319
320- # note that we don't need to setup env(), python figures it out
321- # see python3.py for more details
322+ _PLUGIN_STAGE_PACKAGES = [
323+ 'python3-dev',
324+ 'python3-pkg-resources',
325+ 'python3-setuptools',
326+ ]
327+
328+ def __init__(self, name, options):
329+ super().__init__(name, options)
330+ self.requirements = options.requirements
331+ self.source = options.source
332
333 def env(self, root):
334 return ["PYTHONPATH=%s" % os.path.join(
335- root, 'usr', 'lib', 'python3', 'dist-packages')]
336+ root, 'usr', 'lib', self.python_version, 'dist-packages')]
337
338 def pull(self):
339- return self.handle_source_options()
340+ if self.source and not self.handle_source_options():
341+ return False
342+
343+ return self._pip()
344+
345+ def _pip(self):
346+ setup = 'setup.py'
347+ if os.listdir(self.sourcedir):
348+ setup = os.path.join(self.sourcedir, 'setup.py')
349+
350+ if self.requirements:
351+ requirements = os.path.join(os.getcwd(), self.requirements)
352+
353+ if not os.path.exists(setup) and not self.requirements:
354+ return True
355+
356+ easy_install = os.path.join(
357+ self.installdir, 'usr', 'bin', 'easy_install3')
358+ prefix = os.path.join(self.installdir, 'usr')
359+ site_packages_dir = os.path.join(
360+ prefix, 'lib', self.python_version, 'site-packages')
361+
362+ if not os.path.exists(site_packages_dir):
363+ os.symlink(
364+ os.path.join(prefix, 'lib', 'python3', 'dist-packages'),
365+ site_packages_dir)
366+
367+ if not self.run(['python3', easy_install, '--prefix', prefix, 'pip']):
368+ return False
369+
370+ pip3 = os.path.join(self.installdir, 'usr', 'bin', 'pip3')
371+ pip_install = ['python3', pip3, 'install', '--target',
372+ site_packages_dir]
373+
374+ if self.requirements and not self.run(
375+ pip_install + ['--requirement', requirements]):
376+ return False
377+
378+ if os.path.exists(setup) and not self.run(pip_install + ['.', ]):
379+ return False
380+
381+ return True
382
383 def build(self):
384 # If setuptools is used, it tries to create files in the
385 # dist-packages dir and import from there, so it needs to exist
386 # and be in the PYTHONPATH. It's harmless if setuptools isn't
387 # used.
388+
389+ if not os.path.exists(os.path.join(self.builddir, 'setup.py')):
390+ return True
391+
392 os.makedirs(self.dist_packages_dir, exist_ok=True)
393 setuptemp = self.copy_setup()
394 return self.run(
395@@ -46,7 +99,11 @@
396 @property
397 def dist_packages_dir(self):
398 return os.path.join(
399- self.installdir, 'usr', 'lib', 'python3', 'dist-packages')
400+ self.installdir, 'usr', 'lib', self.python_version, 'dist-packages')
401+
402+ @property
403+ def python_version(self):
404+ return self.run_output(['py3versions', '-i'])
405
406 # Takes the setup.py file and puts a couple little gems on the
407 # front to make things work better.

Subscribers

People subscribed via source and target branches