Merge lp:~ken-vandine/quickly/quickly-python-library into lp:quickly
- quickly-python-library
- Merge into trunk
Proposed by
Ken VanDine
Status: | Rejected |
---|---|
Rejected by: | Didier Roche-Tolomelli |
Proposed branch: | lp:~ken-vandine/quickly/quickly-python-library |
Merge into: | lp:quickly |
Diff against target: |
1853 lines (+1732/-0) 23 files modified
data/templates/python-library/available_licenses/header_BSD (+26/-0) data/templates/python-library/available_licenses/header_GPL-2 (+11/-0) data/templates/python-library/available_licenses/header_GPL-3 (+11/-0) data/templates/python-library/available_licenses/header_LGPL-2 (+1/-0) data/templates/python-library/available_licenses/header_LGPL-3 (+1/-0) data/templates/python-library/available_licenses/header_MIT (+17/-0) data/templates/python-library/commandsconfig (+7/-0) data/templates/python-library/configure.py (+103/-0) data/templates/python-library/create.py (+113/-0) data/templates/python-library/edit.py (+68/-0) data/templates/python-library/help/index.html (+24/-0) data/templates/python-library/internal/packaging.py (+183/-0) data/templates/python-library/internal/quicklyutils.py (+158/-0) data/templates/python-library/license.py (+266/-0) data/templates/python-library/package.py (+74/-0) data/templates/python-library/project_root/Copyright (+3/-0) data/templates/python-library/project_root/setup.py (+93/-0) data/templates/python-library/python/__init__.py (+6/-0) data/templates/python-library/python/project_name.py (+4/-0) data/templates/python-library/release.py (+286/-0) data/templates/python-library/save.py (+55/-0) data/templates/python-library/share.py (+181/-0) data/templates/python-library/tutorial.py (+41/-0) |
To merge this branch: | bzr merge lp:~ken-vandine/quickly/quickly-python-library |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Didier Roche-Tolomelli | Abstain | ||
Review via email: mp+14931@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Ken VanDine (ken-vandine) wrote : | # |
Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote : | # |
Hey Ken,
I think you really should wait for one week, Quickly would get an option on importing command from other template without really copying the code there. That can be a good option for that precise new template.
review:
Abstain
Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote : | # |
I think this MR doesn't apply anymore :)
Unmerged revisions
- 362. By Ken VanDine
-
added license and copyright to __init__.py
- 361. By Ken VanDine
-
added save and share
- 360. By Ken VanDine
-
set the default license to LGPL-3, we assume it is a library
- 359. By Ken VanDine
-
added tutorial to python-library with a stub index.html
- 358. By Ken VanDine
-
added python-library template
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'data/templates/python-library' |
2 | === added directory 'data/templates/python-library/available_licenses' |
3 | === added file 'data/templates/python-library/available_licenses/header_BSD' |
4 | --- data/templates/python-library/available_licenses/header_BSD 1970-01-01 00:00:00 +0000 |
5 | +++ data/templates/python-library/available_licenses/header_BSD 2009-11-16 23:40:24 +0000 |
6 | @@ -0,0 +1,26 @@ |
7 | +# Copyright (c) The Regents of the University of California. |
8 | +# All rights reserved. |
9 | + |
10 | +# Redistribution and use in source and binary forms, with or without |
11 | +# modification, are permitted provided that the following conditions |
12 | +# are met: |
13 | +# 1. Redistributions of source code must retain the above copyright |
14 | +# notice, this list of conditions and the following disclaimer. |
15 | +# 2. Redistributions in binary form must reproduce the above copyright |
16 | +# notice, this list of conditions and the following disclaimer in the |
17 | +# documentation and/or other materials provided with the distribution. |
18 | +# 3. Neither the name of the University nor the names of its contributors |
19 | +# may be used to endorse or promote products derived from this software |
20 | +# without specific prior written permission. |
21 | + |
22 | +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
23 | +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | +#SUCH DAMAGE. |
33 | |
34 | === added file 'data/templates/python-library/available_licenses/header_GPL-2' |
35 | --- data/templates/python-library/available_licenses/header_GPL-2 1970-01-01 00:00:00 +0000 |
36 | +++ data/templates/python-library/available_licenses/header_GPL-2 2009-11-16 23:40:24 +0000 |
37 | @@ -0,0 +1,11 @@ |
38 | +#This program is free software: you can redistribute it and/or modify it |
39 | +#under the terms of the GNU General Public License version 2, as published |
40 | +#by the Free Software Foundation. |
41 | +# |
42 | +#This program is distributed in the hope that it will be useful, but |
43 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
44 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
45 | +#PURPOSE. See the GNU General Public License for more details. |
46 | +# |
47 | +#You should have received a copy of the GNU General Public License along |
48 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
49 | |
50 | === added file 'data/templates/python-library/available_licenses/header_GPL-3' |
51 | --- data/templates/python-library/available_licenses/header_GPL-3 1970-01-01 00:00:00 +0000 |
52 | +++ data/templates/python-library/available_licenses/header_GPL-3 2009-11-16 23:40:24 +0000 |
53 | @@ -0,0 +1,11 @@ |
54 | +#This program is free software: you can redistribute it and/or modify it |
55 | +#under the terms of the GNU General Public License version 3, as published |
56 | +#by the Free Software Foundation. |
57 | +# |
58 | +#This program is distributed in the hope that it will be useful, but |
59 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
60 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
61 | +#PURPOSE. See the GNU General Public License for more details. |
62 | +# |
63 | +#You should have received a copy of the GNU General Public License along |
64 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
65 | |
66 | === added file 'data/templates/python-library/available_licenses/header_LGPL-2' |
67 | --- data/templates/python-library/available_licenses/header_LGPL-2 1970-01-01 00:00:00 +0000 |
68 | +++ data/templates/python-library/available_licenses/header_LGPL-2 2009-11-16 23:40:24 +0000 |
69 | @@ -0,0 +1,1 @@ |
70 | +# This file is distributed under the license LGPL version 2 or later |
71 | |
72 | === added file 'data/templates/python-library/available_licenses/header_LGPL-3' |
73 | --- data/templates/python-library/available_licenses/header_LGPL-3 1970-01-01 00:00:00 +0000 |
74 | +++ data/templates/python-library/available_licenses/header_LGPL-3 2009-11-16 23:40:24 +0000 |
75 | @@ -0,0 +1,1 @@ |
76 | +# This file is distributed under the license LGPL version 3 or later |
77 | |
78 | === added file 'data/templates/python-library/available_licenses/header_MIT' |
79 | --- data/templates/python-library/available_licenses/header_MIT 1970-01-01 00:00:00 +0000 |
80 | +++ data/templates/python-library/available_licenses/header_MIT 2009-11-16 23:40:24 +0000 |
81 | @@ -0,0 +1,17 @@ |
82 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
83 | +# of this software and associated documentation files (the "Software"), to deal |
84 | +# in the Software without restriction, including without limitation the rights |
85 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
86 | +# copies of the Software, and to permit persons to whom the Software is |
87 | +# furnished to do so, subject to the following conditions: |
88 | +# |
89 | +# The above copyright notice and this permission notice shall be included in |
90 | +# all copies or substantial portions of the Software. |
91 | +# |
92 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
93 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
94 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
95 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
96 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
97 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
98 | +# THE SOFTWARE. |
99 | |
100 | === added file 'data/templates/python-library/commandsconfig' |
101 | --- data/templates/python-library/commandsconfig 1970-01-01 00:00:00 +0000 |
102 | +++ data/templates/python-library/commandsconfig 2009-11-16 23:40:24 +0000 |
103 | @@ -0,0 +1,7 @@ |
104 | +# define parameters for commands, putting them in a list seperated |
105 | +# by ';' |
106 | +# if nothing specified, default is to launch command inside a project |
107 | +# only and not be followed by a template |
108 | +COMMANDS_LAUNCHED_IN_OR_OUTSIDE_PROJECT = tutorial |
109 | +COMMANDS_LAUNCHED_OUTSIDE_PROJECT_ONLY = create |
110 | +COMMANDS_FOLLOWED_BY_COMMAND = |
111 | |
112 | === added file 'data/templates/python-library/configure.py' |
113 | --- data/templates/python-library/configure.py 1970-01-01 00:00:00 +0000 |
114 | +++ data/templates/python-library/configure.py 2009-11-16 23:40:24 +0000 |
115 | @@ -0,0 +1,103 @@ |
116 | +#!/usr/bin/python |
117 | +# -*- coding: utf-8 -*- |
118 | +# Copyright 2009 Canonical Ltd. |
119 | +# Author 2009 Didier Roche |
120 | +# |
121 | +# This file is part of Quickly python-library-template |
122 | +# |
123 | +#This program is free software: you can redistribute it and/or modify it |
124 | +#under the terms of the GNU General Public License version 3, as published |
125 | +#by the Free Software Foundation. |
126 | + |
127 | +#This program is distributed in the hope that it will be useful, but |
128 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
129 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
130 | +#PURPOSE. See the GNU General Public License for more details. |
131 | + |
132 | +#You should have received a copy of the GNU General Public License along |
133 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
134 | + |
135 | +import os |
136 | +import sys |
137 | + |
138 | +from internal import quicklyutils, packaging |
139 | +from quickly import configurationhandler, templatetools |
140 | +from quickly import launchpadaccess |
141 | + |
142 | + |
143 | +import gettext |
144 | +from gettext import gettext as _ |
145 | +# set domain text |
146 | +gettext.textdomain('quickly') |
147 | + |
148 | +argv = sys.argv |
149 | +options = ('lp-project', 'ppa') |
150 | + |
151 | +def help(): |
152 | + print _("""Usage: |
153 | +$ quickly configure [%s] <args> |
154 | + |
155 | +Enable to set or change some parameters of the project, like to which |
156 | +launchpad project should be binded with the current ubuntu project, what |
157 | +ppa should we use by default to share your packageā¦ |
158 | +""") % ("|".join(available_options)) |
159 | +def shell_completion(argv): |
160 | + ''' Complete args ''' |
161 | + # option completion |
162 | + if len(argv) == 1: |
163 | + print " ".join([option for option in options if option.startswith(sys.argv[-1])]) |
164 | + elif len(argv) > 1 and argv[-2] == 'ppa': # if argument following ppa keyname, complete by ppa |
165 | + print " ".join(packaging.shell_complete_ppa(argv[-1])) |
166 | + |
167 | +templatetools.handle_additional_parameters(sys.argv, help, shell_completion) |
168 | + |
169 | + |
170 | +# connect to LP |
171 | +try: |
172 | + launchpad = launchpadaccess.initialize_lpi() |
173 | +except launchpadaccess.launchpad_connexion_error, e: |
174 | + print(e) |
175 | + sys.exit(1) |
176 | + |
177 | +# set the project, skipping the interactive phase if project_name is provided |
178 | +if argv[1] == "lp-project": |
179 | + project_name = None |
180 | + if len(argv > 2): |
181 | + project_name = argv[2] |
182 | + try: |
183 | + project = launchpadaccess.link_project(launchpad, "Change your launchpad project:", project_name) |
184 | + except launchpadaccess.launchpad_project_error, e: |
185 | + print(e) |
186 | + sys.exit(1) |
187 | + # get the project now and save the url into setup.py |
188 | + quicklyutils.set_setup_value('url', launchpadaccess.launchpad_url + '/' + project.name) |
189 | + |
190 | +# change default ppa |
191 | +elif argv[1] == "ppa": |
192 | + if len(argv != 3): |
193 | + print(_('''Changing ppa parameter should be: quickly configure ppa <ppaname>. |
194 | +Use shell completion to find all available ppas''')) |
195 | + sys.exit(1) |
196 | + |
197 | + ppa_name = argv[2] |
198 | + # choose right ppa parameter (users, etc.) ppa or staging |
199 | + try: |
200 | + (ppa_user, ppa_name, dput_ppa_name, ppa_url) = packaging.choose_ppa(launchpad, ppa_name) |
201 | + except packaging.user_team_not_found, e: |
202 | + print(_("User or Team %s not found on Launchpad") % e) |
203 | + sys.exit(1) |
204 | + except packaging.not_ppa_owner, e: |
205 | + print(_("You have to be a member of %s team to upload to its ppas") % e) |
206 | + sys.exit(1) |
207 | + |
208 | + try: |
209 | + ppa_name = packaging.check_and_return_ppaname(launchpad, ppa_user, ppa_name) # ppa_name can be ppa name or ppa display name. Find the right one if exists |
210 | + except packaging.ppa_not_found, e: |
211 | + print(_("%s does not exist. Please create it on launchpad if you want to upload to it. %s has the following ppas available:") % (e, ppa_user.name)) |
212 | + for ppa_name, ppa_display_name in packaging.get_all_ppas(launchpad, ppa_user): |
213 | + print "%s - %s" % (ppa_name, ppa_display_name) |
214 | + sys.exit(1) |
215 | + |
216 | + configurationhandler.project_config['ppa'] = ppa_name |
217 | + configurationhandler.saveConfig() |
218 | + |
219 | |
220 | === added file 'data/templates/python-library/create.py' |
221 | --- data/templates/python-library/create.py 1970-01-01 00:00:00 +0000 |
222 | +++ data/templates/python-library/create.py 2009-11-16 23:40:24 +0000 |
223 | @@ -0,0 +1,113 @@ |
224 | +#!/usr/bin/python |
225 | +# -*- coding: utf-8 -*- |
226 | +# Copyright 2009 Canonical Ltd. |
227 | +# Author 2009 Didier Roche |
228 | +# |
229 | +# This file is part of Quickly python-library-template |
230 | +# |
231 | +#This program is free software: you can redistribute it and/or modify it |
232 | +#under the terms of the GNU General Public License version 3, as published |
233 | +#by the Free Software Foundation. |
234 | + |
235 | +#This program is distributed in the hope that it will be useful, but |
236 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
237 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
238 | +#PURPOSE. See the GNU General Public License for more details. |
239 | + |
240 | +#You should have received a copy of the GNU General Public License along |
241 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
242 | + |
243 | +import sys |
244 | +import os |
245 | +import shutil |
246 | +import subprocess |
247 | + |
248 | +from quickly import templatetools |
249 | +from internal import quicklyutils |
250 | + |
251 | +import gettext |
252 | +from gettext import gettext as _ |
253 | +# set domain text |
254 | +gettext.textdomain('quickly') |
255 | + |
256 | + |
257 | + |
258 | +def help(): |
259 | + print _("""Usage: |
260 | +$ quickly create python-library path/to/project_name |
261 | + |
262 | +where "project_name" is one or more words separated by an underscore and |
263 | +path/to can be any existing path. |
264 | + |
265 | +This will create a new python library project, including Python code, |
266 | + and packaging files to make the project work. After |
267 | +creating the project, get started by: |
268 | + |
269 | +1. Changing your working directory to the new project: |
270 | +$ cd path/to/project_name |
271 | + |
272 | +2. Edit the Python code: |
273 | +$ quickly edit |
274 | +""") |
275 | +templatetools.handle_additional_parameters(sys.argv, help) |
276 | + |
277 | +# get origin path |
278 | +pathname = os.path.dirname(__file__) |
279 | +abs_path = os.path.abspath(pathname) + "/" |
280 | + |
281 | + |
282 | +# get the name of the project |
283 | +if len(sys.argv) < 2: |
284 | + print _(""" |
285 | +ERROR: project name not defined. Usage is project_name""") |
286 | + sys.exit(1) |
287 | + |
288 | +os.chdir(sys.argv[1]) |
289 | + |
290 | +path_and_project = sys.argv[1].split('/') |
291 | +project_name = path_and_project[-1] |
292 | + |
293 | +# check that project name follow quickly rules and reformat it. |
294 | +try: |
295 | + project_name = templatetools.quickly_name(project_name) |
296 | +except templatetools.bad_project_name, e: |
297 | + print(e) |
298 | + sys.exit(1) |
299 | + |
300 | +python_dir = project_name |
301 | +print _("Creating project directory %s") % python_dir |
302 | +os.mkdir(python_dir) |
303 | +print _("Directory %s created\n") % python_dir |
304 | + |
305 | +sentence_name, camel_case_name = quicklyutils.conventional_names(project_name) |
306 | + |
307 | +substitutions = (("project_name",project_name), |
308 | + ("camel_case_name",camel_case_name), |
309 | + ("sentence_name",sentence_name),) |
310 | + |
311 | + |
312 | +# create the python directory and files |
313 | +template_python_dir = abs_path + "python/" |
314 | +target_python_dir = project_name |
315 | + |
316 | +# copy the files needed for packaging |
317 | +quicklyutils.file_from_template(abs_path, "project_root/setup.py", ".", substitutions) |
318 | +quicklyutils.file_from_template(template_python_dir, "__init__.py", target_python_dir, substitutions) |
319 | + |
320 | +# copy the initial python library file |
321 | +quicklyutils.file_from_template(template_python_dir,"project_name.py",target_python_dir, substitutions) |
322 | + |
323 | + |
324 | +# copy the licence file |
325 | +quicklyutils.file_from_template(abs_path ,"project_root/Copyright",".", substitutions) |
326 | + |
327 | +# add it to revision control |
328 | +print _("Creating bzr repository and commiting") |
329 | +subprocess.call(["bzr", "init"]) |
330 | +subprocess.call(["bzr", "add"]) |
331 | +subprocess.call(["bzr", "commit", "-m", "Initial project creation with Quickly!"]) |
332 | + |
333 | +print _("Congrats, your new project is setup! cd %s/ to start hacking. Then '$ quickly tutorial' for quickly python-library tutorial and reference") % os.getcwd() |
334 | + |
335 | +sys.exit(0) |
336 | + |
337 | |
338 | === added file 'data/templates/python-library/edit.py' |
339 | --- data/templates/python-library/edit.py 1970-01-01 00:00:00 +0000 |
340 | +++ data/templates/python-library/edit.py 2009-11-16 23:40:24 +0000 |
341 | @@ -0,0 +1,68 @@ |
342 | +#!/usr/bin/python |
343 | +# -*- coding: utf-8 -*- |
344 | +# Copyright 2009 Canonical Ltd. |
345 | +# Author 2009 Didier Roche |
346 | +# |
347 | +# This file is part of Quickly python-library-template |
348 | +# |
349 | +#This program is free software: you can redistribute it and/or modify it |
350 | +#under the terms of the GNU General Public License version 3, as published |
351 | +#by the Free Software Foundation. |
352 | + |
353 | +#This program is distributed in the hope that it will be useful, but |
354 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
355 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
356 | +#PURPOSE. See the GNU General Public License for more details. |
357 | + |
358 | +#You should have received a copy of the GNU General Public License along |
359 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
360 | + |
361 | + |
362 | +import os |
363 | +import sys |
364 | + |
365 | +from quickly import configurationhandler, templatetools |
366 | + |
367 | +import gettext |
368 | +from gettext import gettext as _ |
369 | +# set domain text |
370 | +gettext.textdomain('quickly') |
371 | + |
372 | + |
373 | +def help(): |
374 | + print _("""Usage: |
375 | +$ quickly edit |
376 | + |
377 | +A convenience command to open all of your python files in your project |
378 | +directory in your default editor, ready for editing. |
379 | + |
380 | +If you put yourself EDITOR or SELECTED_EDITOR environment variable, this latter |
381 | +will be used. Also, if you configured sensible-editor, this one will be |
382 | +choosed. |
383 | +""") |
384 | +templatetools.handle_additional_parameters(sys.argv, help) |
385 | + |
386 | +filelist = "" |
387 | +for root, dirs, files in os.walk('./'): |
388 | + for name in files: |
389 | + if name.endswith('.py') and name not in ('__init__.py', 'setup.py'): |
390 | + filelist += os.path.join(root, name) + ' ' |
391 | + |
392 | +# if config not already loaded |
393 | +if not configurationhandler.project_config: |
394 | + configurationhandler.loadConfig() |
395 | + |
396 | +editor = "gedit" |
397 | +default_editor = os.environ.get("EDITOR") |
398 | +if not default_editor: |
399 | + default_editor = os.environ.get("SELECTED_EDITOR") |
400 | +if not default_editor and os.path.exists('~/.selected_editor'): |
401 | + editor = 'sensible-editor' |
402 | +elif default_editor: |
403 | + editor = default_editor |
404 | + |
405 | +# if editor is still gedit, launch it in background |
406 | +if editor == "gedit": |
407 | + filelist += " &" |
408 | + |
409 | +os.system("%s %s" % (editor, filelist)) |
410 | |
411 | === added directory 'data/templates/python-library/help' |
412 | === added file 'data/templates/python-library/help/index.html' |
413 | --- data/templates/python-library/help/index.html 1970-01-01 00:00:00 +0000 |
414 | +++ data/templates/python-library/help/index.html 2009-11-16 23:40:24 +0000 |
415 | @@ -0,0 +1,24 @@ |
416 | +<HTML> |
417 | +<HEAD> |
418 | +<TITLE>Quickly Help Index</TITLE> |
419 | +<STYLE> |
420 | +img |
421 | +{ |
422 | + display: block; |
423 | + width:668px; |
424 | + padding-top:10px; |
425 | +} |
426 | +p |
427 | +{ |
428 | + width: 800px; |
429 | +} |
430 | +.emphasis |
431 | +{ |
432 | + font-weight: bold; |
433 | +} |
434 | +</STYLE> |
435 | +</HEAD> |
436 | +<BODY> |
437 | + <H1>What is Quickly?</H1> |
438 | +</BODY> |
439 | +</HTML> |
440 | |
441 | === added directory 'data/templates/python-library/internal' |
442 | === added file 'data/templates/python-library/internal/__init__.py' |
443 | === added file 'data/templates/python-library/internal/packaging.py' |
444 | --- data/templates/python-library/internal/packaging.py 1970-01-01 00:00:00 +0000 |
445 | +++ data/templates/python-library/internal/packaging.py 2009-11-16 23:40:24 +0000 |
446 | @@ -0,0 +1,183 @@ |
447 | +# -*- coding: utf-8 -*- |
448 | +# Copyright 2009 Canonical Ltd. |
449 | +# Author 2009 Didier Roche |
450 | +# |
451 | +# This file is part of Quickly ubuntu-project-template |
452 | +# |
453 | +#This program is free software: you can redistribute it and/or modify it |
454 | +#under the terms of the GNU General Public License version 3, as published |
455 | +#by the Free Software Foundation. |
456 | + |
457 | +#This program is distributed in the hope that it will be useful, but |
458 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
459 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
460 | +#PURPOSE. See the GNU General Public License for more details. |
461 | + |
462 | +#You should have received a copy of the GNU General Public License along |
463 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
464 | + |
465 | +import re |
466 | +import subprocess |
467 | +import sys |
468 | + |
469 | + |
470 | +from quickly import configurationhandler |
471 | +from quickly import launchpadaccess |
472 | + |
473 | +import gettext |
474 | +from gettext import gettext as _ |
475 | + |
476 | +#set domain text |
477 | +gettext.textdomain('quickly') |
478 | + |
479 | +class ppa_not_found(Exception): |
480 | + pass |
481 | +class not_ppa_owner(Exception): |
482 | + pass |
483 | +class user_team_not_found(Exception): |
484 | + pass |
485 | + |
486 | +def updatepackaging(): |
487 | + """create or update a package using python-mkdebian. |
488 | + |
489 | + Commit after the first packaging creation""" |
490 | + |
491 | + return_code = subprocess.call(["python-mkdebian"]) |
492 | + if return_code == 0: |
493 | + print _("Ubuntu packaging created in debian/") |
494 | + else: |
495 | + print _("An error has occurred") |
496 | + return(return_code) |
497 | + |
498 | + # check if first python-mkdebian (debian/ creation) to commit it |
499 | + # that means debian/ under unknown |
500 | + bzr_instance = subprocess.Popen(["bzr", "status"], stdout=subprocess.PIPE) |
501 | + bzr_status, err = bzr_instance.communicate() |
502 | + if bzr_instance.returncode != 0: |
503 | + return(bzr_instance.returncode) |
504 | + |
505 | + if re.match('(.|\n)*unknown:\n.*debian/(.|\n)*', bzr_status): |
506 | + return_code = subprocess.call(["bzr", "add"]) |
507 | + if return_code == 0: |
508 | + return_code = subprocess.call(["bzr", "commit", "-m 'Creating ubuntu package'"]) |
509 | + |
510 | + return(return_code) |
511 | + |
512 | +def shell_complete_ppa(ppa_to_complete): |
513 | + ''' Complete from available ppas ''' |
514 | + |
515 | + # connect to LP and get ppa to complete |
516 | + try: |
517 | + launchpad = launchpadaccess.initialize_lpi(False) |
518 | + except launchpadaccess.launchpad_connexion_error: |
519 | + sys.exit(0) |
520 | + available_ppas = [] |
521 | + if launchpad is not None: |
522 | + try: |
523 | + (ppa_user, ppa_name) = get_ppa_parameters(launchpad, ppa_to_complete) |
524 | + except user_team_not_found: |
525 | + pass |
526 | + else: |
527 | + for current_ppa_name, current_ppa_displayname in get_all_ppas(launchpad, ppa_user): |
528 | + # print user/ppa form |
529 | + available_ppas.append("%s/%s" % (ppa_user.name, current_ppa_name)) |
530 | + # if it's the user, print in addition just "ppa_name" syntax |
531 | + if ppa_user.name == launchpad.me.name: |
532 | + available_ppas.append(current_ppa_name) |
533 | + # if we don't have provided a team, show all teams were we are member off |
534 | + if not '/' in ppa_to_complete: |
535 | + team = [mem.team for mem in launchpad.me.memberships_details if mem.status in ("Approved", "Administrator")] |
536 | + for elem in team: |
537 | + available_ppas.append(elem.name + '/') |
538 | + return available_ppas |
539 | + |
540 | +def get_ppa_parameters(launchpad, full_ppa_name): |
541 | + ''' Check if we can catch good parameters for specified ppa in form user/ppa or ppa ''' |
542 | + |
543 | + if '/' in full_ppa_name: |
544 | + ppa_user_name = full_ppa_name.split('/')[0] |
545 | + ppa_name = full_ppa_name.split('/')[1] |
546 | + # check that we are in the team/or that we are the user |
547 | + try: |
548 | + lp_ppa_user = launchpad.people[ppa_user_name] |
549 | + if lp_ppa_user.name == launchpad.me.name: |
550 | + ppa_user = launchpad.me |
551 | + else: |
552 | + # check if we are a member of this team |
553 | + team = [mem.team for mem in launchpad.me.memberships_details if mem.status in ("Approved", "Administrator") and mem.team.name == ppa_user_name] |
554 | + if team: |
555 | + ppa_user = team[0] |
556 | + else: |
557 | + raise not_ppa_owner(ppa_user_name) |
558 | + except KeyError: |
559 | + raise user_team_not_found(ppa_user_name) |
560 | + else: |
561 | + ppa_user = launchpad.me |
562 | + ppa_name = full_ppa_name |
563 | + return(ppa_user, ppa_name) |
564 | + |
565 | +def choose_ppa(launchpad, ppa_name=None): |
566 | + '''Look for right ppa parameters where to push the package''' |
567 | + |
568 | + if not ppa_name: |
569 | + if not configurationhandler.project_config: |
570 | + configurationhandler.loadConfig() |
571 | + try: |
572 | + (ppa_user, ppa_name) = get_ppa_parameters(launchpad, configurationhandler.project_config['ppa']) |
573 | + except KeyError: |
574 | + ppa_user = launchpad.me |
575 | + if (launchpadaccess.lp_server == "staging"): |
576 | + ppa_name = 'staging' |
577 | + else: # default ppa |
578 | + ppa_name = 'ppa' |
579 | + else: |
580 | + (ppa_user, ppa_name) = get_ppa_parameters(launchpad, ppa_name) |
581 | + ppa_url = '%s/~%s/+archive/%s' % (launchpadaccess.LAUNCHPAD_URL, ppa_user.name, ppa_name) |
582 | + dput_ppa_name = 'ppa:%s/%s' % (ppa_user.name, ppa_name) |
583 | + return (ppa_user, ppa_name, dput_ppa_name, ppa_url.encode('UTF-8')) |
584 | + |
585 | +def push_to_ppa(dput_ppa_name, changes_file): |
586 | + """ Push some code to a ppa """ |
587 | + |
588 | + # creation/update debian packaging |
589 | + return_code = updatepackaging() |
590 | + if return_code != 0: |
591 | + print _("ERROR: can't create or update ubuntu package") |
592 | + return(return_code) |
593 | + # creating local binary package |
594 | + return_code = subprocess.call(["dpkg-buildpackage", "-S", "-I.bzr"]) |
595 | + if return_code != 0: |
596 | + print _("ERROR: an error occurred during source package creation") |
597 | + return(return_code) |
598 | + # now, pushing it to launchpad personal ppa (or team later) |
599 | + return_code = subprocess.call(["dput", dput_ppa_name, changes_file]) |
600 | + if return_code != 0: |
601 | + print _("ERROR: an error occurred during source upload to launchpad") |
602 | + return(return_code) |
603 | + return(0) |
604 | + |
605 | +def get_all_ppas(launchpad, lp_team_or_user): |
606 | + """ get all from a team or users |
607 | + |
608 | + Return list of tuples (ppa_name, ppa_display_name)""" |
609 | + |
610 | + ppa_list = [] |
611 | + for ppa in lp_team_or_user.ppas: |
612 | + ppa_list.append((ppa.name, ppa.displayname)) |
613 | + return ppa_list |
614 | + |
615 | +def check_and_return_ppaname(launchpad, lp_team_or_user, ppa_name): |
616 | + """ check whether ppa exists using its name or display name for the lp team or user |
617 | + |
618 | + return formated ppaname (not display name)""" |
619 | + |
620 | + # check that the owner really has this ppa: |
621 | + ppa_found = False |
622 | + for current_ppa_name, current_ppa_displayname in get_all_ppas(launchpad, lp_team_or_user): |
623 | + if current_ppa_name == ppa_name or current_ppa_displayname == ppa_name: |
624 | + ppa_found = True |
625 | + break |
626 | + if not ppa_found: |
627 | + raise ppa_not_found('ppa:%s:%s' % (lp_team_or_user.name, ppa_name.encode('UTF-8'))) |
628 | + return(current_ppa_name) |
629 | + |
630 | |
631 | === added file 'data/templates/python-library/internal/quicklyutils.py' |
632 | --- data/templates/python-library/internal/quicklyutils.py 1970-01-01 00:00:00 +0000 |
633 | +++ data/templates/python-library/internal/quicklyutils.py 2009-11-16 23:40:24 +0000 |
634 | @@ -0,0 +1,158 @@ |
635 | +# -*- coding: utf-8 -*- |
636 | +# Copyright 2009 Canonical Ltd. |
637 | +# Author 2009 Didier Roche |
638 | +# |
639 | +# This file is part of Quickly ubuntu-project-template |
640 | +# |
641 | +#This program is free software: you can redistribute it and/or modify it |
642 | +#under the terms of the GNU General Public License version 3, as published |
643 | +#by the Free Software Foundation. |
644 | + |
645 | +#This program is distributed in the hope that it will be useful, but |
646 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
647 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
648 | +#PURPOSE. See the GNU General Public License for more details. |
649 | + |
650 | +#You should have received a copy of the GNU General Public License along |
651 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
652 | + |
653 | +import os |
654 | +import string |
655 | +import sys |
656 | +import subprocess |
657 | + |
658 | +import gettext |
659 | +from gettext import gettext as _ |
660 | +#set domain text |
661 | +gettext.textdomain('quickly') |
662 | + |
663 | + |
664 | +class cant_deal_with_setup_value(Exception): |
665 | + pass |
666 | + |
667 | +def conventional_names(name): |
668 | + #sentence_name = name.replace("_"," ") |
669 | + #sentence_name = string.capwords(sentence_name) |
670 | + sentence_name = string.capwords(name) |
671 | + camel_case_name = sentence_name.replace(" ","") |
672 | + return sentence_name, camel_case_name |
673 | + |
674 | +def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True): |
675 | + target_file = os.path.basename(template_file) # to get only file name (template_file can be internal/file) |
676 | + if rename: |
677 | + for s in substitutions: |
678 | + pattern, sub = s |
679 | + target_file = target_file.replace(pattern,sub) |
680 | + |
681 | + print "Creating %s" % target_dir + "/" + target_file |
682 | + fin = open(template_dir + template_file,'r') |
683 | + file_contents = fin.read() |
684 | + for s in substitutions: |
685 | + pattern, sub = s |
686 | + file_contents = file_contents.replace(pattern,sub) |
687 | + |
688 | + fout = open(target_dir + "/" + target_file, 'w') |
689 | + fout.write(file_contents) |
690 | + fout.flush() |
691 | + fout.close() |
692 | + fin.close() |
693 | + print "%s created\n" % (target_dir + "/" + target_file,) |
694 | + |
695 | +def get_setup_value(key): |
696 | + """ get value from setup.py file. |
697 | + |
698 | + raise cant_deal_with_setup_value if nothing found |
699 | + : return found value""" |
700 | + |
701 | + result = None |
702 | + in_setup = False |
703 | + try: |
704 | + fsetup = file('setup.py', 'r') |
705 | + for line in fsetup: |
706 | + if in_setup: |
707 | + fields = line.split('=') # Separate variable from value |
708 | + if key in fields[0] and not '#' in fields[0]: # if key found and not commented |
709 | + result = fields[1].partition(',')[0].strip() |
710 | + result = result[1:-1] |
711 | + break |
712 | + if "setup(" in line: |
713 | + in_setup = True |
714 | + # if end of the function, finished |
715 | + if in_setup and ')' in line: |
716 | + in_setup = False |
717 | + fsetup.close() |
718 | + except (OSError, IOError), e: |
719 | + print _("ERROR: Can't load setup.py file") |
720 | + sys.exit(1) |
721 | + |
722 | + if result is None: |
723 | + raise cant_deal_with_setup_value() |
724 | + return result |
725 | + |
726 | +def set_setup_value(key, value): |
727 | + """ set value from setup.py file |
728 | + |
729 | + it adds new key in the setup() function if not found. |
730 | + it uncomments a commented value if changed. |
731 | + |
732 | + exit with 0 if everything's all right |
733 | + """ |
734 | + |
735 | + has_changed_something = False |
736 | + in_setup = False |
737 | + try: |
738 | + fsetup = file('setup.py', 'r') |
739 | + fdest = file(fsetup.name + '.new', 'w') |
740 | + for line in fsetup: |
741 | + if in_setup: |
742 | + fields = line.split('=') # Separate variable from value |
743 | + if key in fields[0]: |
744 | + # add new value, uncommenting it if present |
745 | + line = "%s='%s',\n" % (fields[0].replace('#',''), value) |
746 | + has_changed_something = True |
747 | + |
748 | + if "setup(" in line: |
749 | + in_setup = True |
750 | + # add it if the value was not present and reach end of setup() function |
751 | + if not has_changed_something and in_setup and ")" in line: |
752 | + fdest.write(" %s='%s',\n" % (key, value)) |
753 | + in_setup = False |
754 | + fdest.write(line) |
755 | + |
756 | + fdest.close() |
757 | + fsetup.close() |
758 | + os.rename(fdest.name, fsetup.name) |
759 | + except (OSError, IOError), e: |
760 | + print _("ERROR: Can't load setup.py file") |
761 | + sys.exit(1) |
762 | + |
763 | + return 0 |
764 | + |
765 | +def check_gpg_secret_key(): |
766 | + """Check that the gpg secret key corresponding to the right email is present on the system""" |
767 | + |
768 | + gpg_instance = subprocess.Popen(['gpg', '--list-secret-keys', '--with-colon'], stdout=subprocess.PIPE) |
769 | + |
770 | + result, err = gpg_instance.communicate() |
771 | + |
772 | + if gpg_instance.returncode != 0: |
773 | + print(err) |
774 | + return(False) |
775 | + splitted_gpg_list = result.strip().split(':') |
776 | + # prendre la partie mail de DEBEMAIL, puis EMAIL |
777 | + # Sinon, prendre mail LP |
778 | + |
779 | + # regarder s'il se trouve dans gpg, puis reprendre |
780 | + # nom gpg -> DEBEMAIL |
781 | + |
782 | + #launchpadlib: avoir la clef gpg qui est settƩe? |
783 | + |
784 | + if 'sec' in splitted_gpg_list: |
785 | + #TODO: check there that DEBEMAIL (or failback to lp email adress email) gpg key exists and put |
786 | + # the name <adress> in DEBEMAIL if doesn't exists. |
787 | + return(True) |
788 | + |
789 | + |
790 | + print _("No gpg key set. Take a look at quickly tutorial to learn how to setup one") |
791 | + return(False) |
792 | + |
793 | |
794 | === added file 'data/templates/python-library/license.py' |
795 | --- data/templates/python-library/license.py 1970-01-01 00:00:00 +0000 |
796 | +++ data/templates/python-library/license.py 2009-11-16 23:40:24 +0000 |
797 | @@ -0,0 +1,266 @@ |
798 | +#!/usr/bin/python |
799 | +# -*- coding: utf-8 -*- |
800 | +# Copyright 2009 Canonical Ltd. |
801 | +# Author 2009 Didier Roche |
802 | +# |
803 | +# This file is part of Quickly python-library-template |
804 | +# |
805 | +#This program is free software: you can redistribute it and/or modify it |
806 | +#under the terms of the GNU General Public License version 3, as published |
807 | +#by the Free Software Foundation. |
808 | +# |
809 | +#This program is distributed in the hope that it will be useful, but |
810 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
811 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
812 | +#PURPOSE. See the GNU General Public License for more details. |
813 | +# |
814 | +#You should have received a copy of the GNU General Public License along |
815 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
816 | + |
817 | +import datetime |
818 | +import os |
819 | +import re |
820 | +import shutil |
821 | +import sys |
822 | + |
823 | +from quickly import configurationhandler, templatetools |
824 | +from internal import quicklyutils |
825 | + |
826 | +import gettext |
827 | +from gettext import gettext as _ |
828 | +# set domain text |
829 | +gettext.textdomain('quickly') |
830 | + |
831 | + |
832 | +BEGIN_COPYRIGHT_TAG = '### BEGIN AUTOMATIC LICENSE GENERATION' |
833 | +END_COPYRIGHT_TAG = '### END AUTOMATIC LICENSE GENERATION' |
834 | +BEGIN_LICENCE_TAG = '### BEGIN LICENSE' |
835 | +END_LICENCE_TAG = '### END LICENSE' |
836 | + |
837 | + |
838 | +def help(): |
839 | + print _("""Usage: |
840 | +$quickly license <Your_Licence> |
841 | + |
842 | +Adds license to project files. Before using this command, you should: |
843 | + |
844 | +1. Edit the file Copyright to include your authorship (this step is automatically done |
845 | + if you directly launch "$ quickly release" or "$ quickly share" before changing license) |
846 | + In this case, license is LGPL-3 by default. |
847 | +2. If you want to put your own quickly unsupported Licence, remove and replace the tags |
848 | + ### BEGIN AUTOMATIC LICENCE GENERATION and ### END AUTOMATIC LICENCE GENERATION |
849 | + in it by your own licence. |
850 | +3. Executes either $ quickly license or $ quickly licence <License> |
851 | + where <License> can be either: |
852 | + - LGPL-3 (default) |
853 | + - GPL-3 |
854 | + - GPL-2 |
855 | + |
856 | +This will modify the Copyright file with the chosen licence (with LGPL-3 by default). |
857 | +Updating previous chosen Licence if needed. |
858 | +If you previously removed the tags to add your own licence, it will leave it pristine. |
859 | +If no name is attributed to the Copyright, it will try to retrieve it from Launchpad |
860 | +(in quickly release or quickly share command only) |
861 | + |
862 | +Finally, this will copy the Copyright at the head of every files. |
863 | + |
864 | +Note that if you don't run quickly licence before calling quickly release or quickly |
865 | +share, this one will execute it for you and guess the copyright holder from your |
866 | +launchpad account if you didn't update it. |
867 | +""") |
868 | + |
869 | +def get_supported_licenses(): |
870 | + """Get supported licenses""" |
871 | + |
872 | + available_licenses = [] |
873 | + |
874 | + for license_file in os.listdir(os.path.dirname(__file__) + "/available_licenses"): |
875 | + result = re.split("header_(.*)", license_file) |
876 | + if len(result) == 3: |
877 | + available_licenses.append(result[1]) |
878 | + |
879 | + return available_licenses |
880 | + |
881 | + |
882 | +def copy_license_to_files(): |
883 | + """Copy generated Copyright file to every .py files""" |
884 | + |
885 | + # get the project name |
886 | + if not configurationhandler.project_config: |
887 | + configurationhandler.loadConfig() |
888 | + project_name = configurationhandler.project_config['project'] |
889 | + |
890 | + # put full license into a string, stripping metatags |
891 | + fcopyright_name = "Copyright" |
892 | + try: |
893 | + license = file(fcopyright_name, 'r').read().replace(BEGIN_COPYRIGHT_TAG + '\n', '').replace(END_COPYRIGHT_TAG + '\n', '') |
894 | + except (OSError, IOError), e: |
895 | + print _("%s file was not found") % fcopyright_name |
896 | + sys.exit(1) |
897 | + |
898 | + # open each python file and main bin file |
899 | + for root, dirs, files in os.walk('./'): |
900 | + for name in files: |
901 | + if name.endswith('.py') or os.path.join(root, name) == "./bin/" + project_name: |
902 | + skip_until_end_found = False |
903 | + try: |
904 | + target_file_name = os.path.join(root, name) |
905 | + ftarget_file_name = file(target_file_name, 'r') |
906 | + ftarget_file_name_out = file(ftarget_file_name.name + '.new', 'w') |
907 | + for line in ftarget_file_name: |
908 | + # seek if we have to add or Replace a License |
909 | + if BEGIN_LICENCE_TAG in line: |
910 | + ftarget_file_name_out.write(line) # write this line, otherwise will be skipped |
911 | + skip_until_end_found = True |
912 | + ftarget_file_name_out.write(license) |
913 | + |
914 | + if END_LICENCE_TAG in line: |
915 | + skip_until_end_found = False |
916 | + |
917 | + if not skip_until_end_found: |
918 | + ftarget_file_name_out.write(line) |
919 | + |
920 | + ftarget_file_name.close() |
921 | + ftarget_file_name_out.close() |
922 | + |
923 | + if skip_until_end_found: # that means we didn't find the END_LICENCE_TAG, don't copy the file |
924 | + print _("WARNING: %s was not found in the file %s. No licence replacement") % (END_LICENCE_TAG, ftarget_file_name.name) |
925 | + os.remove(ftarget_file_name_out.name) |
926 | + else: |
927 | + templatetools.apply_file_rights(ftarget_file_name.name, ftarget_file_name_out.name) |
928 | + os.rename(ftarget_file_name_out.name, ftarget_file_name.name) |
929 | + |
930 | + except (OSError, IOError), e: |
931 | + print _("%s file was not found") % fcopyright_name |
932 | + return(1) |
933 | + |
934 | + |
935 | +def licensing(license=None): |
936 | + """Add license or update it to the project files |
937 | + |
938 | + Default is LGPL-3""" |
939 | + |
940 | + |
941 | + # if file was never licensed, choose LGPL-3 |
942 | + fcopyright_name = "Copyright" |
943 | + fauthors_name = "AUTHORS" |
944 | + |
945 | + if license is None: |
946 | + try: |
947 | + # check if file already licensed |
948 | + fcopyright = file(fcopyright_name, 'r').read() |
949 | + if fcopyright.find(BEGIN_COPYRIGHT_TAG + '\n' + END_COPYRIGHT_TAG) != -1: |
950 | + license = "LGPL-3" |
951 | + |
952 | + except (OSError, IOError), e: |
953 | + print _("%s file was not found") % fcopyright_name |
954 | + sys.exit(1) |
955 | + |
956 | + # if license is still None, that means that user uses a either a generated license |
957 | + # or personal one and don't want to update it |
958 | + |
959 | + # check that provided licensed is supported |
960 | + if not license is None and license not in get_supported_licenses(): |
961 | + print _("This license seems to be unsupported by quickly. If you think it really should, " \ |
962 | + "please open a bug in quickly bugtracker") |
963 | + return(1) |
964 | + |
965 | + |
966 | + # check and update (if needed, cf before) Copyright and AUTHORS file |
967 | + skip_until_end_found = False |
968 | + try: |
969 | + fcopyright = file(fcopyright_name, 'r') |
970 | + fcopyright_out = file(fcopyright.name + '.new', 'w') |
971 | + fauthors_out = file(fauthors_name + '.new', 'w') |
972 | + for line in fcopyright: |
973 | + |
974 | + # add autorship if needed |
975 | + if "<Your Name> <Your E-mail>" in line: |
976 | + # if we have an author in setup.py, put it there |
977 | + try: |
978 | + author = quicklyutils.get_setup_value('author') |
979 | + author_email = quicklyutils.get_setup_value('author_email') |
980 | + line = "# Copyright (C) %s %s <%s>\n" % (datetime.datetime.now().year, author, author_email) |
981 | + except quicklyutils.cant_deal_with_setup_value: |
982 | + print _('Copyright is not attributed. ' \ |
983 | + 'Edit the Copyright file to include your name for the copyright in ' \ |
984 | + 'place of <Your Name> <Your E-mail> or use quickly share/quickly release') |
985 | + return 1 |
986 | + |
987 | + # update AUTHORS file |
988 | + if 'copyright' in line.lower(): |
989 | + fauthors_out.write(line) |
990 | + |
991 | + # if we want to update/create the license |
992 | + if license: |
993 | + # seek if we have to add or Replace a License |
994 | + if BEGIN_COPYRIGHT_TAG in line: |
995 | + fcopyright_out.write(line) # write this line, otherwise will be skipped |
996 | + skip_until_end_found = True |
997 | + |
998 | + # get license file to read and write in Copyright |
999 | + flicense = open(os.path.dirname(__file__) + "/available_licenses/header_" + license, 'r') |
1000 | + fcopyright_out.write(flicense.read()) |
1001 | + flicense.close |
1002 | + |
1003 | + if END_COPYRIGHT_TAG in line: |
1004 | + skip_until_end_found = False |
1005 | + |
1006 | + if not skip_until_end_found: |
1007 | + fcopyright_out.write(line) |
1008 | + |
1009 | + fcopyright_out.close() |
1010 | + fcopyright.close() |
1011 | + fauthors_out.close() |
1012 | + |
1013 | + if skip_until_end_found: # that means we didn't find the END_LICENCE_TAG, don't copy the file |
1014 | + print _("WARNING: %s was not found in the file %s. No licence replacement") % (END_COPYRIGHT_TAG, fcopyright.name) |
1015 | + os.remove(fcopyright_out.name) |
1016 | + sys.exit(1) |
1017 | + else: |
1018 | + templatetools.apply_file_rights(fcopyright.name, fcopyright_out.name) |
1019 | + os.rename(fcopyright_out.name, fcopyright.name) |
1020 | + # finish updating copyright file |
1021 | + os.rename(fauthors_out.name, fauthors_name) |
1022 | + |
1023 | + except (OSError, IOError), e: |
1024 | + print _("%s file was not found") % fcopyright_name |
1025 | + return(1) |
1026 | + |
1027 | + # copy system license file to LICENSE |
1028 | + # if not licence variable, that means it has already be copied |
1029 | + if license is not None: |
1030 | + src_license_file = "/usr/share/common-licenses/" + license |
1031 | + if os.path.isfile(src_license_file): |
1032 | + shutil.copy("/usr/share/common-licenses/" + license, "LICENSE") |
1033 | + # license has been changed, remove LICENSE file if exists |
1034 | + else: |
1035 | + if os.path.isfile("LICENSE"): |
1036 | + os.remove("LICENSE") |
1037 | + |
1038 | + # write license to setup.py |
1039 | + quicklyutils.set_setup_value('license', license) |
1040 | + |
1041 | + return(copy_license_to_files()) |
1042 | + |
1043 | + |
1044 | +def shell_completion(argv): |
1045 | + """Propose available license as the third parameter""" |
1046 | + |
1047 | + # if then license argument given, returns available licenses |
1048 | + if len(argv) == 1: |
1049 | + print " ".join(get_supported_licenses()) |
1050 | + |
1051 | + |
1052 | +if __name__ == "__main__": |
1053 | + |
1054 | + templatetools.handle_additional_parameters(sys.argv, help, shell_completion) |
1055 | + license = None |
1056 | + if len(sys.argv) > 2: |
1057 | + print _("This command only take one optional argument: License") |
1058 | + sys.exit(1) |
1059 | + if len(sys.argv) == 2: |
1060 | + license = sys.argv[1] |
1061 | + |
1062 | + sys.exit(licensing(license)) |
1063 | + |
1064 | |
1065 | === added file 'data/templates/python-library/package.py' |
1066 | --- data/templates/python-library/package.py 1970-01-01 00:00:00 +0000 |
1067 | +++ data/templates/python-library/package.py 2009-11-16 23:40:24 +0000 |
1068 | @@ -0,0 +1,74 @@ |
1069 | +#!/usr/bin/python |
1070 | +# -*- coding: utf-8 -*- |
1071 | +# Copyright 2009 Canonical Ltd. |
1072 | +# Author 2009 Didier Roche |
1073 | +# |
1074 | +# This file is part of Quickly python-library-template |
1075 | +# |
1076 | +#This program is free software: you can redistribute it and/or modify it |
1077 | +#under the terms of the GNU General Public License version 3, as published |
1078 | +#by the Free Software Foundation. |
1079 | + |
1080 | +#This program is distributed in the hope that it will be useful, but |
1081 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
1082 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1083 | +#PURPOSE. See the GNU General Public License for more details. |
1084 | + |
1085 | +#You should have received a copy of the GNU General Public License along |
1086 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
1087 | + |
1088 | +import sys |
1089 | +import subprocess |
1090 | + |
1091 | +import gettext |
1092 | +from gettext import gettext as _ |
1093 | +gettext.textdomain('quickly') |
1094 | + |
1095 | +from internal import quicklyutils, packaging |
1096 | +from quickly import templatetools, configurationhandler |
1097 | + |
1098 | + |
1099 | +def help(): |
1100 | + print _("""Usage: |
1101 | +$quickly package |
1102 | + |
1103 | +Creates a debian file (deb) from your project. Before running |
1104 | +the package command you can edit the Icon and Category entry of *.desktop.in |
1105 | +file, where * is the name of your project. |
1106 | + |
1107 | +Note that if you didn't run quickly release, quickly share |
1108 | +or quickly change-lp-project you may miss the name, email in |
1109 | +setup.py. You can edit them if you don't want to use any of these |
1110 | +commands afterwards. Those changes are not a mandatory at all for |
1111 | +testing purpose. |
1112 | +""") |
1113 | +templatetools.handle_additional_parameters(sys.argv, help) |
1114 | + |
1115 | + |
1116 | +# retrieve useful information |
1117 | +if not configurationhandler.project_config: |
1118 | + configurationhandler.loadConfig() |
1119 | +project_name = configurationhandler.project_config['project'] |
1120 | + |
1121 | +try: |
1122 | + release_version = quicklyutils.get_setup_value('version') |
1123 | +except quicklyutils.cant_deal_with_setup_value: |
1124 | + print _("Release version not found in setup.py.") |
1125 | + |
1126 | + |
1127 | +# creation/update debian packaging |
1128 | +if packaging.updatepackaging() != 0: |
1129 | + print _("ERROR: can't create or update ubuntu package") |
1130 | + sys.exit(1) |
1131 | + |
1132 | + |
1133 | +# creating local binary package |
1134 | +return_code = subprocess.call(["dpkg-buildpackage", "-tc", "-I.bzr", "-us", "-uc"]) |
1135 | +if return_code == 0: |
1136 | + print _("Ubuntu package has been successfully created in ../%s_%s_all.deb") % (project_name, release_version) |
1137 | +else: |
1138 | + print _("An error has occurred during package building") |
1139 | + |
1140 | +sys.exit(return_code) |
1141 | + |
1142 | + |
1143 | |
1144 | === added directory 'data/templates/python-library/project_root' |
1145 | === added file 'data/templates/python-library/project_root/Copyright' |
1146 | --- data/templates/python-library/project_root/Copyright 1970-01-01 00:00:00 +0000 |
1147 | +++ data/templates/python-library/project_root/Copyright 2009-11-16 23:40:24 +0000 |
1148 | @@ -0,0 +1,3 @@ |
1149 | +# Copyright (C) YYYY <Your Name> <Your E-mail> |
1150 | +### BEGIN AUTOMATIC LICENSE GENERATION |
1151 | +### END AUTOMATIC LICENSE GENERATION |
1152 | |
1153 | === added file 'data/templates/python-library/project_root/setup.py' |
1154 | --- data/templates/python-library/project_root/setup.py 1970-01-01 00:00:00 +0000 |
1155 | +++ data/templates/python-library/project_root/setup.py 2009-11-16 23:40:24 +0000 |
1156 | @@ -0,0 +1,93 @@ |
1157 | +#!/usr/bin/env python |
1158 | +# -*- coding: utf-8 -*- |
1159 | +### BEGIN LICENSE |
1160 | +# This file is in the public domain |
1161 | +### END LICENSE |
1162 | + |
1163 | +###################### DO NOT TOUCH THIS (HEAD TO THE SECOND PART) ###################### |
1164 | + |
1165 | +try: |
1166 | + import DistUtilsExtra.auto |
1167 | +except ImportError: |
1168 | + import sys |
1169 | + print >> sys.stderr, 'To build project_name you need https://launchpad.net/python-distutils-extra' |
1170 | + sys.exit(1) |
1171 | + |
1172 | +assert DistUtilsExtra.auto.__version__ >= '2.10', 'needs DistUtilsExtra.auto >= 2.10' |
1173 | +import os |
1174 | + |
1175 | + |
1176 | +def update_data_path(prefix, oldvalue=None): |
1177 | + |
1178 | + try: |
1179 | + fin = file('project_name/project_nameconfig.py', 'r') |
1180 | + fout = file(fin.name + '.new', 'w') |
1181 | + |
1182 | + for line in fin: |
1183 | + fields = line.split(' = ') # Separate variable from value |
1184 | + if fields[0] == '__project_name_data_directory__': |
1185 | + # update to prefix, store oldvalue |
1186 | + if not oldvalue: |
1187 | + oldvalue = fields[1] |
1188 | + line = "%s = '%s'\n" % (fields[0], prefix) |
1189 | + else: # restore oldvalue |
1190 | + line = "%s = %s" % (fields[0], oldvalue) |
1191 | + fout.write(line) |
1192 | + |
1193 | + fout.flush() |
1194 | + fout.close() |
1195 | + fin.close() |
1196 | + os.rename(fout.name, fin.name) |
1197 | + except (OSError, IOError), e: |
1198 | + print ("ERROR: Can't find project_name/project_nameconfig.py") |
1199 | + sys.exit(1) |
1200 | + return oldvalue |
1201 | + |
1202 | + |
1203 | +def update_desktop_file(datadir): |
1204 | + |
1205 | + try: |
1206 | + fin = file('project_name.desktop.in', 'r') |
1207 | + fout = file(fin.name + '.new', 'w') |
1208 | + |
1209 | + for line in fin: |
1210 | + if 'Icon=' in line: |
1211 | + line = "Icon=%s\n" % (datadir + 'media/icon.png') |
1212 | + fout.write(line) |
1213 | + fout.flush() |
1214 | + fout.close() |
1215 | + fin.close() |
1216 | + os.rename(fout.name, fin.name) |
1217 | + except (OSError, IOError), e: |
1218 | + print ("ERROR: Can't find project_name.desktop.in") |
1219 | + sys.exit(1) |
1220 | + |
1221 | + |
1222 | +class InstallAndUpdateDataDirectory(DistUtilsExtra.auto.install_auto): |
1223 | + def run(self): |
1224 | + if self.root or self.home: |
1225 | + print "WARNING: You don't use a standard --prefix installation, take care that you eventually " \ |
1226 | + "need to update quickly/quicklyconfig.py file to adjust __quickly_data_directory__. You can " \ |
1227 | + "ignore this warning if you are packaging and uses --prefix." |
1228 | + previous_value = update_data_path(self.prefix + '/share/project_name/') |
1229 | + update_desktop_file(self.prefix + '/share/project_name/') |
1230 | + DistUtilsExtra.auto.install_auto.run(self) |
1231 | + update_data_path(self.prefix, previous_value) |
1232 | + |
1233 | + |
1234 | + |
1235 | +################################################################################## |
1236 | +###################### YOU SHOULD MODIFY ONLY WHAT IS BELOW ###################### |
1237 | +################################################################################## |
1238 | + |
1239 | +DistUtilsExtra.auto.setup( |
1240 | + name='project_name', |
1241 | + version='0.1', |
1242 | + #license='GPL v3', |
1243 | + #author='Your Name', |
1244 | + #author_email='email@ubuntu.com', |
1245 | + #description='UI for managing ā¦', |
1246 | + #long_description='Here a longer description', |
1247 | + #url='https://launchpad.net/project_name', |
1248 | + ) |
1249 | + |
1250 | |
1251 | === added directory 'data/templates/python-library/python' |
1252 | === added file 'data/templates/python-library/python/__init__.py' |
1253 | --- data/templates/python-library/python/__init__.py 1970-01-01 00:00:00 +0000 |
1254 | +++ data/templates/python-library/python/__init__.py 2009-11-16 23:40:24 +0000 |
1255 | @@ -0,0 +1,6 @@ |
1256 | +# -*- coding: utf-8 -*- |
1257 | +### BEGIN LICENSE |
1258 | +# This file is in the public domain |
1259 | +### END LICENSE |
1260 | + |
1261 | +from project_name import * |
1262 | |
1263 | === added file 'data/templates/python-library/python/project_name.py' |
1264 | --- data/templates/python-library/python/project_name.py 1970-01-01 00:00:00 +0000 |
1265 | +++ data/templates/python-library/python/project_name.py 2009-11-16 23:40:24 +0000 |
1266 | @@ -0,0 +1,4 @@ |
1267 | +# -*- coding: utf-8 -*- |
1268 | +### BEGIN LICENSE |
1269 | +# This file is in the public domain |
1270 | +### END LICENSE |
1271 | |
1272 | === added file 'data/templates/python-library/release.py' |
1273 | --- data/templates/python-library/release.py 1970-01-01 00:00:00 +0000 |
1274 | +++ data/templates/python-library/release.py 2009-11-16 23:40:24 +0000 |
1275 | @@ -0,0 +1,286 @@ |
1276 | +#!/usr/bin/python |
1277 | +# -*- coding: utf-8 -*- |
1278 | +# Copyright 2009 Canonical Ltd. |
1279 | +# Author 2009 Didier Roche |
1280 | +# |
1281 | +# This file is part of Quickly python-library-template |
1282 | +# |
1283 | +#This program is free software: you can redistribute it and/or modify it |
1284 | +#under the terms of the GNU General Public License version 3, as published |
1285 | +#by the Free Software Foundation. |
1286 | + |
1287 | +#This program is distributed in the hope that it will be useful, but |
1288 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
1289 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1290 | +#PURPOSE. See the GNU General Public License for more details. |
1291 | + |
1292 | +#You should have received a copy of the GNU General Public License along |
1293 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
1294 | + |
1295 | +import os |
1296 | +import sys |
1297 | +import subprocess |
1298 | +import webbrowser |
1299 | + |
1300 | +from internal import quicklyutils, packaging |
1301 | +from quickly import templatetools, configurationhandler |
1302 | +import license |
1303 | + |
1304 | +import logging |
1305 | + |
1306 | +from quickly import launchpadaccess |
1307 | + |
1308 | +import gettext |
1309 | +from gettext import gettext as _ |
1310 | +gettext.textdomain('quickly') |
1311 | + |
1312 | +options = ("--ppa",) |
1313 | + |
1314 | +def help(): |
1315 | + print _("""Usage: |
1316 | +$quickly release |
1317 | + |
1318 | +Posts a release of your project to a PPA on launchpad so that |
1319 | +users can install the application on their system. |
1320 | + |
1321 | +You can also execute: |
1322 | +$quickly release <release_number> of you don't want to use current |
1323 | +release_number. The release_number must be a number. |
1324 | + |
1325 | +$quickly release <release_number> notes about changes |
1326 | +where "notes about changes" is optional text describing what changes |
1327 | +were made since the last save |
1328 | + |
1329 | +--ppa <your ppa> (name or display name) to specify to which ppa you want |
1330 | +to share |
1331 | +--ppa team/<ppa> (name or display name) to specify to which ppa team you |
1332 | +want to share |
1333 | + |
1334 | +Before running quickly release, you should: create your account |
1335 | +and a project page on http://launchpad.net. |
1336 | +You also have to add a PPA to your launchpad account. |
1337 | + |
1338 | +Name, email and version setup.py will be automatically changed. |
1339 | +(version will be <current_release> and bzr will commit and tagged. |
1340 | +Once the release is done, <current_release> will be incremented |
1341 | +by 0.1 to be ready for next release. |
1342 | +If you previously used quickly shared <current_release>~publicX |
1343 | +will be dropped to release <current_release> version |
1344 | +(<current_release>~publicX < <current_release>) |
1345 | +You can modify the description and long description if you wish. |
1346 | + |
1347 | +You can run $quickly package and test your package to make sure it |
1348 | +installs as expected. (This is not mandatory) |
1349 | +""") |
1350 | +def shell_completion(argv): |
1351 | + ''' Complete --args ''' |
1352 | + # option completion |
1353 | + if argv[-1].startswith("-"): |
1354 | + print " ".join([option for option in options if option.startswith(sys.argv[-1])]) |
1355 | + elif len(argv) > 1 and argv[-2] == '--ppa': # if argument following --ppa, complete by ppa |
1356 | + print " ".join(packaging.shell_complete_ppa(argv[-1])) |
1357 | + |
1358 | +templatetools.handle_additional_parameters(sys.argv, help, shell_completion) |
1359 | + |
1360 | + |
1361 | +launchpad = None |
1362 | +project = None |
1363 | +ppa_name = None |
1364 | +i = 0 |
1365 | +args = [] |
1366 | +argv = sys.argv |
1367 | + |
1368 | +while i < len(argv): |
1369 | + arg = argv[i] |
1370 | + if arg.startswith('-'): |
1371 | + if arg == '--ppa': |
1372 | + if i + 1 < len(argv): |
1373 | + ppa_name = argv[i + 1] |
1374 | + i += 1 |
1375 | + else: |
1376 | + print _("ERROR: --ppa needs one argument: <ppa name>") |
1377 | + sys.exit(1) |
1378 | + else: |
1379 | + print _("Unknown option: %s" % arg) |
1380 | + sys.exit(1) |
1381 | + else: |
1382 | + args.append(arg) |
1383 | + i += 1 |
1384 | + |
1385 | +if len(args) == 1: |
1386 | + |
1387 | + try: |
1388 | + release_version = quicklyutils.get_setup_value('version') |
1389 | + except quicklyutils.cant_deal_with_setup_value: |
1390 | + print _("Release version not found in setup.py and no version specified in command line.") |
1391 | + sys.exit(1) |
1392 | + commit_msg = _('quickly released') |
1393 | +elif len(args) == 2: |
1394 | + release_version = args[1] |
1395 | + # add .0 to release if nothing specified (avoid for mess in search in bzr tags) |
1396 | + if "." not in release_version: |
1397 | + release_version + '.0' |
1398 | + commit_msg = _('quickly released: %s' % release_version) |
1399 | + # write release version to setup.py if user specify it (needed for package build) |
1400 | + quicklyutils.set_setup_value('version', release_version) |
1401 | +elif len(args) > 2: |
1402 | + release_version = args[1] |
1403 | + commit_msg = " ".join(args[2:]) |
1404 | + # write release version to setup.py if user specify it (needed for package build) |
1405 | + quicklyutils.set_setup_value('version', release_version) |
1406 | + |
1407 | +try: |
1408 | + float(release_version) |
1409 | +except ValueError: |
1410 | + # two cases: |
1411 | + # a "quickly share" has already be done, and so, we just remove all the ~publilcX stuff |
1412 | + splitted_release_version = release_version.split("~public") |
1413 | + if len(splitted_release_version) > 1: |
1414 | + release_version = splitted_release_version[0] |
1415 | + |
1416 | + # elsewhere, it's an error |
1417 | + else: |
1418 | + print _("Release version specified in command arguments or in setup.py " \ |
1419 | + "is not a valid number.") |
1420 | + sys.exit(1) |
1421 | + |
1422 | +# warning: project_name can be different from project.name (one local, one on launchpad) |
1423 | +if not configurationhandler.project_config: |
1424 | + configurationhandler.loadConfig() |
1425 | +project_name = configurationhandler.project_config['project'] |
1426 | + |
1427 | +# connect to LP |
1428 | +try: |
1429 | + launchpad = launchpadaccess.initialize_lpi() |
1430 | +except launchpadaccess.launchpad_connexion_error, e: |
1431 | + print(e) |
1432 | + sys.exit(1) |
1433 | + |
1434 | +# check if a gpg key is available |
1435 | +if not quicklyutils.check_gpg_secret_key(): |
1436 | + sys.exit(1) |
1437 | + |
1438 | +# changed upstream author and email |
1439 | +quicklyutils.set_setup_value('author', launchpad.me.display_name.encode('UTF-8')) |
1440 | +quicklyutils.set_setup_value('author_email', launchpad.me.preferred_email_address.email) |
1441 | + |
1442 | +# license if needed (default with author in setup.py and GPL-3). Don't change anything if not needed |
1443 | +license.licensing() |
1444 | + |
1445 | +# get the project now and save the url into setup.py |
1446 | +try: |
1447 | + project = launchpadaccess.get_project(launchpad) |
1448 | +except launchpadaccess.launchpad_project_error, e: |
1449 | + print(e) |
1450 | + sys.exit(1) |
1451 | +quicklyutils.set_setup_value('url', launchpadaccess.launchpad_url + '/' + project.name) |
1452 | + |
1453 | +# if no EMAIL or DEBEMAIL setup, use launchpad prefered email (for changelog) |
1454 | +#TODO: check that the gpg key contains it (or match preferred_email_adress to available gpg keys and take the name) |
1455 | +if not os.getenv("EMAIL") and not os.getenv("DEBEMAIL"): |
1456 | + os.putenv("DEBEMAIL", "%s <%s>" % (launchpad.me.display_name.encode('UTF-8'), launchpad.me.preferred_email_address.email)) |
1457 | + |
1458 | +# choose right ppa parameter (users, etc.) ppa or staging if ppa_name is None |
1459 | +try: |
1460 | + (ppa_user, ppa_name, dput_ppa_name, ppa_url) = packaging.choose_ppa(launchpad, ppa_name) |
1461 | +except packaging.user_team_not_found, e: |
1462 | + print(_("User or Team %s not found on Launchpad") % e) |
1463 | + sys.exit(1) |
1464 | +except packaging.not_ppa_owner, e: |
1465 | + print(_("You have to be a member of %s team to upload to its ppas") % e) |
1466 | + sys.exit(1) |
1467 | + |
1468 | +try: |
1469 | + ppa_name = packaging.check_and_return_ppaname(launchpad, ppa_user, ppa_name) # ppa_name can be ppa name or ppa display name. Find the right one if exists |
1470 | +except packaging.ppa_not_found, e: |
1471 | + print(_("%s does not exist. Please create it on launchpad if you want to upload to it. %s has the following ppas available:") % (e, ppa_user.name)) |
1472 | + for ppa_name, ppa_display_name in packaging.get_all_ppas(launchpad, ppa_user): |
1473 | + print "%s - %s" % (ppa_name, ppa_display_name) |
1474 | + sys.exit(1) |
1475 | + |
1476 | +# check if already released with this name |
1477 | +bzr_instance = subprocess.Popen(["bzr", "tags"], stdout=subprocess.PIPE) |
1478 | +bzr_tags, err = bzr_instance.communicate() |
1479 | +if bzr_instance.returncode !=0: |
1480 | + print(err) |
1481 | + sys.exit(1) |
1482 | +if release_version in bzr_tags: |
1483 | + print _("ERROR: quickly can't release: %s seems to be already released. Choose another name.") % release_version |
1484 | + sys.exit(1) |
1485 | + |
1486 | + |
1487 | +# add files, setup release version, commit and push ! |
1488 | +#TODO: check or fix if we don't have an ssh key (don't tag otherwise to be able to release again) |
1489 | +quicklyutils.set_setup_value('version', release_version) |
1490 | +subprocess.call(["bzr", "add"]) |
1491 | +return_code = subprocess.call(["bzr", "commit", '-m', commit_msg]) |
1492 | +if return_code != 0 and return_code != 3: |
1493 | + print _("ERROR: quickly can't release as it can't commit with bzr") |
1494 | + sys.exit(return_code) |
1495 | +subprocess.call(["bzr", "tag", release_version]) # tag revision |
1496 | + |
1497 | + |
1498 | +# TODO: handle bzr rm |
1499 | + |
1500 | +# check if pull branch is set |
1501 | +bzr_instance = subprocess.Popen(["bzr", "info"], stdout=subprocess.PIPE) |
1502 | +bzr_info, err = bzr_instance.communicate() |
1503 | +if bzr_instance.returncode !=0: |
1504 | + print(err) |
1505 | + sys.exit(1) |
1506 | + |
1507 | + |
1508 | +# TODO: see if we want a strategy to set main branch in the project |
1509 | + |
1510 | +if (launchpadaccess.lp_server == "staging"): |
1511 | + bzr_staging = "//staging/" |
1512 | +else: |
1513 | + bzr_staging = "" |
1514 | + |
1515 | +branch_location = [] |
1516 | +# if no branch, create it in ~user_name/project_name/quickly_trunk |
1517 | +# or switch from staging to production |
1518 | +if not ("parent branch" in bzr_info) or ((".staging." in bzr_info) and not bzr_staging) or (not (".staging." in bzr_info) and bzr_staging): |
1519 | + |
1520 | + branch_location = ['lp:', bzr_staging, '~', launchpad.me.name, '/', project.name, '/quickly_trunk'] |
1521 | + return_code = subprocess.call(["bzr", "push", "--remember", "--overwrite", "".join(branch_location)]) |
1522 | + if return_code != 0: |
1523 | + print _("ERROR: quickly can't release: can't push to launchpad.") |
1524 | + sys.exit(return_code) |
1525 | + |
1526 | + # make first pull too |
1527 | + return_code = subprocess.call(["bzr", "pull", "--remember", "".join(branch_location)]) |
1528 | + if return_code != 0: |
1529 | + print _("ERROR: quickly can't release correctly: can't pull from launchpad.") |
1530 | + sys.exit(return_code) |
1531 | + |
1532 | +else: |
1533 | + |
1534 | + return_code = subprocess.call(["bzr", "pull"]) |
1535 | + if return_code != 0: |
1536 | + print _("ERROR: quickly can't release: can't pull from launchpad.") |
1537 | + sys.exit(return_code) |
1538 | + |
1539 | + subprocess.call(["bzr", "push"]) |
1540 | + if return_code != 0: |
1541 | + print _("ERROR: quickly can't release: can't push to launchpad.") |
1542 | + sys.exit(return_code) |
1543 | + |
1544 | + |
1545 | +# upload to launchpad |
1546 | +print _("pushing to launchpad") |
1547 | +return_code = packaging.push_to_ppa(dput_ppa_name, "../%s_%s_source.changes" % (project_name, release_version)) != 0 |
1548 | +if return_code != 0: |
1549 | + sys.exit(return_code) |
1550 | + |
1551 | +print _("%s %s released and building on Launchpad. Wait for half an hour and have look at %s.") % (project_name, release_version, ppa_url) |
1552 | +# now, we can bump version for next release |
1553 | +next_release_version = float(release_version) + 0.1 |
1554 | +quicklyutils.set_setup_value('version', next_release_version) |
1555 | + |
1556 | +# as launchpad-open doesn't support staging server, put an url |
1557 | +if launchpadaccess.lp_server == "staging": |
1558 | + webbrowser.open(launchpadaccess.LAUNCHPAD_CODE_STAGING_URL + '/~' + launchpad.me.name + '/' + project.name + '/quickly_trunk') |
1559 | +else: |
1560 | + subprocess.call(["bzr", "launchpad-open"]) |
1561 | + |
1562 | |
1563 | === added file 'data/templates/python-library/save.py' |
1564 | --- data/templates/python-library/save.py 1970-01-01 00:00:00 +0000 |
1565 | +++ data/templates/python-library/save.py 2009-11-16 23:40:24 +0000 |
1566 | @@ -0,0 +1,55 @@ |
1567 | +#!/usr/bin/python |
1568 | +# -*- coding: utf-8 -*- |
1569 | +# Copyright 2009 Canonical Ltd. |
1570 | +# Author 2009 Didier Roche |
1571 | +# |
1572 | +# This file is part of Quickly ubuntu-project-template |
1573 | +# |
1574 | +#This program is free software: you can redistribute it and/or modify it |
1575 | +#under the terms of the GNU General Public License version 3, as published |
1576 | +#by the Free Software Foundation. |
1577 | + |
1578 | +#This program is distributed in the hope that it will be useful, but |
1579 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
1580 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1581 | +#PURPOSE. See the GNU General Public License for more details. |
1582 | + |
1583 | +#You should have received a copy of the GNU General Public License along |
1584 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
1585 | + |
1586 | + |
1587 | +import sys |
1588 | +import subprocess |
1589 | + |
1590 | +import gettext |
1591 | +from gettext import gettext as _ |
1592 | +gettext.textdomain('quickly') |
1593 | + |
1594 | +from quickly import templatetools |
1595 | + |
1596 | +def help(): |
1597 | + print _("""Usage: |
1598 | +$quickly save notes about changes |
1599 | +where "notes about changes" is optional text describing what changes |
1600 | +were made since the last save. |
1601 | + |
1602 | +This command commits all changes since the last save to bzr. Note that |
1603 | +it does not push changes to any back up location. If you need revert |
1604 | +or otherwise use the revision control, use bzr directly: |
1605 | +$bzr help |
1606 | +""") |
1607 | +templatetools.handle_additional_parameters(sys.argv, help) |
1608 | + |
1609 | +#set either a default message or the specified message |
1610 | +commit_msg = " ".join(sys.argv[1:]) |
1611 | +if commit_msg == "": |
1612 | + commit_msg = _('quickly saved') |
1613 | + |
1614 | +#save away |
1615 | +subprocess.call(["bzr", "add"]) |
1616 | +return_code = subprocess.call(["bzr", "commit", "-m" + commit_msg]) |
1617 | +if return_code == 3: |
1618 | + print _("It seems that you have no change to record.") |
1619 | + |
1620 | +sys.exit(return_code) |
1621 | + |
1622 | |
1623 | === added file 'data/templates/python-library/share.py' |
1624 | --- data/templates/python-library/share.py 1970-01-01 00:00:00 +0000 |
1625 | +++ data/templates/python-library/share.py 2009-11-16 23:40:24 +0000 |
1626 | @@ -0,0 +1,181 @@ |
1627 | +#!/usr/bin/python |
1628 | +# -*- coding: utf-8 -*- |
1629 | +# Copyright 2009 Canonical Ltd. |
1630 | +# Author 2009 Didier Roche |
1631 | +# |
1632 | +# This file is part of Quickly ubuntu-project-template |
1633 | +# |
1634 | +#This program is free software: you can redistribute it and/or modify it |
1635 | +#under the terms of the GNU General Public License version 3, as published |
1636 | +#by the Free Software Foundation. |
1637 | + |
1638 | +#This program is distributed in the hope that it will be useful, but |
1639 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
1640 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1641 | +#PURPOSE. See the GNU General Public License for more details. |
1642 | + |
1643 | +#You should have received a copy of the GNU General Public License along |
1644 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
1645 | + |
1646 | +import os |
1647 | +import sys |
1648 | +import subprocess |
1649 | +import webbrowser |
1650 | + |
1651 | +from quickly import templatetools |
1652 | +import license |
1653 | + |
1654 | +import gettext |
1655 | +from gettext import gettext as _ |
1656 | +gettext.textdomain('quickly') |
1657 | + |
1658 | +from quickly import configurationhandler |
1659 | +from internal import quicklyutils, packaging |
1660 | +from quickly import launchpadaccess |
1661 | + |
1662 | +launchpad = None |
1663 | +ppa_name = None |
1664 | +i = 0 |
1665 | +args = [] |
1666 | +argv = sys.argv |
1667 | + |
1668 | + |
1669 | +def help(): |
1670 | + print _("""Usage: |
1671 | +$quickly share |
1672 | + |
1673 | +Updates your PPA with the the latest saved project changes. |
1674 | + |
1675 | +Before running quickly release, you should: create your account |
1676 | +on http://launchpad.net. |
1677 | +You also have to add a PPA to your launchpad account. |
1678 | + |
1679 | +Name, email and version setup.py will be automatically changed. |
1680 | +(version will be <current_release~publicX> where X will be incremented |
1681 | +at each quickly share execution) |
1682 | +You can modify the description and long description if you wish. |
1683 | + |
1684 | +--ppa <your ppa> (name or display name) to specify to which ppa you want |
1685 | +to share |
1686 | +--ppa team/<ppa> (name or display name) to specify to which ppa team you |
1687 | +want to share |
1688 | +""") |
1689 | +def shell_completion(argv): |
1690 | + ''' Complete --args ''' |
1691 | + # option completion |
1692 | + if argv[-1].startswith("-"): |
1693 | + options = ("--ppa",) |
1694 | + available_completion = [option for option in options if option.startswith(sys.argv[-1])] |
1695 | + print " ".join(available_completion) |
1696 | + elif len(argv) > 1 and argv[-2] == '--ppa': # if argument following --ppa, complete by ppa |
1697 | + print " ".join(packaging.shell_complete_ppa(argv[-1])) |
1698 | + |
1699 | +templatetools.handle_additional_parameters(sys.argv, help, shell_completion) |
1700 | + |
1701 | + |
1702 | +while i < len(argv): |
1703 | + arg = argv[i] |
1704 | + if arg.startswith('-'): |
1705 | + if arg == '--ppa': |
1706 | + if i + 1 < len(argv): |
1707 | + ppa_name = argv[i + 1] |
1708 | + i += 1 |
1709 | + else: |
1710 | + print _("ERROR: --ppa needs one argument: <ppa name>") |
1711 | + sys.exit(1) |
1712 | + else: |
1713 | + print _("Unknown option: %s" % arg) |
1714 | + sys.exit(1) |
1715 | + else: |
1716 | + args.append(arg) |
1717 | + i += 1 |
1718 | + |
1719 | +# warning: project_name can be different from project.name (one local, one on launchpad) |
1720 | +if not configurationhandler.project_config: |
1721 | + configurationhandler.loadConfig() |
1722 | +project_name = configurationhandler.project_config['project'] |
1723 | + |
1724 | +# connect to LP |
1725 | +try: |
1726 | + launchpad = launchpadaccess.initialize_lpi() |
1727 | +except launchpadaccess.launchpad_connexion_error, e: |
1728 | + print(e) |
1729 | + sys.exit(1) |
1730 | + |
1731 | +# check if a gpg key is available |
1732 | +if not quicklyutils.check_gpg_secret_key(): |
1733 | + sys.exit(1) |
1734 | + |
1735 | +# changed upstream author and email |
1736 | +quicklyutils.set_setup_value('author', launchpad.me.display_name.encode('UTF-8')) |
1737 | +quicklyutils.set_setup_value('author_email', launchpad.me.preferred_email_address.email) |
1738 | + |
1739 | +# license if needed (default with author in setup.py and GPL-3). Don't change anything if not needed |
1740 | +license.licensing() |
1741 | + |
1742 | +# choose right ppa parameter (users, etc.) ppa or staging if ppa_name is None |
1743 | +try: |
1744 | + (ppa_user, ppa_name, dput_ppa_name, ppa_url) = packaging.choose_ppa(launchpad, ppa_name) |
1745 | +except packaging.user_team_not_found, e: |
1746 | + print(_("User or Team %s not found on Launchpad") % e) |
1747 | + sys.exit(1) |
1748 | +except packaging.not_ppa_owner, e: |
1749 | + print(_("You have to be a member of %s team to upload to its ppas") % e) |
1750 | + sys.exit(1) |
1751 | + |
1752 | +try: |
1753 | + ppa_name = packaging.check_and_return_ppaname(launchpad, ppa_user, ppa_name) # ppa_name can be ppa name or ppa display name. Find the right one if exists |
1754 | +except packaging.ppa_not_found, e: |
1755 | + print(_("%s does not exist. Please create it on launchpad if you want to upload to it. %s has the following ppas available:") % (e, ppa_user.name)) |
1756 | + for ppa_name, ppa_display_name in packaging.get_all_ppas(launchpad, ppa_user): |
1757 | + print "%s - %s" % (ppa_name, ppa_display_name) |
1758 | + sys.exit(1) |
1759 | + |
1760 | +# check version |
1761 | +try: |
1762 | + release_version = quicklyutils.get_setup_value('version') |
1763 | +except quicklyutils.cant_deal_with_setup_value: |
1764 | + print _("Release version not found in setup.py and no version specified in command line.") |
1765 | + sys.exit(1) |
1766 | + |
1767 | + |
1768 | +try: |
1769 | + float(release_version) |
1770 | +except ValueError: |
1771 | + # two cases: |
1772 | + # a "quickly share" has already be done, and so, we just bump the number after ~private |
1773 | + splitted_release_version = release_version.split("~public") |
1774 | + if len(splitted_release_version) > 1: |
1775 | + try: |
1776 | + minor_version = float(splitted_release_version[1]) |
1777 | + except ValueError: |
1778 | + print _("Minor release version specified before ~public in setup.py is not a valid number: %s") % splitted_release_version[1] |
1779 | + sys.exit(1) |
1780 | + version = splitted_release_version[0] + '~public' + str(int(minor_version + 1)) |
1781 | + |
1782 | + # elsewhere, it's an error |
1783 | + else: |
1784 | + print _("Release version specified in setup.py is not a valid number.") |
1785 | + sys.exit(1) |
1786 | + |
1787 | +# we have to minimize the release_version to enable future release (release_version is already at NEXT version release) |
1788 | +# change setup.py as needed for python-mkdebian |
1789 | +else: |
1790 | + version = release_version + '~public1' |
1791 | +quicklyutils.set_setup_value('version', version) |
1792 | + |
1793 | +# if no EMAIL or DEBEMAIL setup, use launchpad prefered email (for changelog). |
1794 | +#TODO: check that the gpg key containis it (or match preferred_email_adress to available gpg keys and take the name) |
1795 | +if not os.getenv("EMAIL") and not os.getenv("DEBEMAIL"): |
1796 | + os.putenv("DEBEMAIL", "%s <%s>" % (launchpad.me.display_name.encode('UTF-8'), launchpad.me.preferred_email_address.email)) |
1797 | +# upload to launchpad |
1798 | +print _("pushing to launchpad") |
1799 | +return_code = packaging.push_to_ppa(dput_ppa_name, "../%s_%s_source.changes" % (project_name, version)) != 0 |
1800 | +if return_code != 0: |
1801 | + sys.exit(return_code) |
1802 | + |
1803 | + |
1804 | +print _("%s %s is building on Launchpad. Wait for half an hour and have look at %s.") % (project_name, version, ppa_url) |
1805 | + |
1806 | +sys.exit(0) |
1807 | + |
1808 | |
1809 | === added file 'data/templates/python-library/tutorial.py' |
1810 | --- data/templates/python-library/tutorial.py 1970-01-01 00:00:00 +0000 |
1811 | +++ data/templates/python-library/tutorial.py 2009-11-16 23:40:24 +0000 |
1812 | @@ -0,0 +1,41 @@ |
1813 | +#!/usr/bin/python |
1814 | +# -*- coding: utf-8 -*- |
1815 | +# Copyright 2009 Canonical Ltd. |
1816 | +# Author 2009 Didier Roche |
1817 | +# |
1818 | +# This file is part of Quickly ubuntu-project-template |
1819 | +# |
1820 | +#This program is free software: you can redistribute it and/or modify it |
1821 | +#under the terms of the GNU General Public License version 3, as published |
1822 | +#by the Free Software Foundation. |
1823 | + |
1824 | +#This program is distributed in the hope that it will be useful, but |
1825 | +#WITHOUT ANY WARRANTY; without even the implied warranties of |
1826 | +#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1827 | +#PURPOSE. See the GNU General Public License for more details. |
1828 | + |
1829 | +#You should have received a copy of the GNU General Public License along |
1830 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
1831 | + |
1832 | +import os |
1833 | +import sys |
1834 | +import webbrowser |
1835 | + |
1836 | +import gettext |
1837 | +from gettext import gettext as _ |
1838 | +gettext.textdomain('quickly') |
1839 | + |
1840 | +from quickly import templatetools |
1841 | + |
1842 | +def help(): |
1843 | + print _("""Usage: |
1844 | +$ quickly tutorial |
1845 | + |
1846 | +Opens a web browser with the tutorial for python-library template. |
1847 | +""") |
1848 | +templatetools.handle_additional_parameters(sys.argv, help) |
1849 | + |
1850 | +webbrowser.open(os.path.dirname(__file__) + "/help/index.html") |
1851 | + |
1852 | +sys.exit(0) |
1853 | + |
Added a python-library template for quickly. I had to copy over a fair bit of stuff from the ubuntu-project code. A bunch of the commands are unchanged, but some have been simplified. For example I removed the stuff that installs datadir stuff and bindir stuff. Purely a python library.
Also the tutorial is just an empty stub index.html file. I want feedback on this before I revise the tutorial.