Merge lp:~ken-vandine/quickly/quickly-python-library into lp:quickly

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
Reviewer Review Type Date Requested Status
Didier Roche-Tolomelli Abstain
Review via email: mp+14931@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Ken VanDine (ken-vandine) wrote :

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.

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+

Subscribers

People subscribed via source and target branches