Merge lp:~quickly-committers/quickly/add_widgets into lp:quickly

Proposed by Tony Byrne
Status: Needs review
Proposed branch: lp:~quickly-committers/quickly/add_widgets
Merge into: lp:quickly
Diff against target: 759 lines (+334/-147)
16 files modified
data/templates/ubuntu-application/add.py (+164/-26)
data/templates/ubuntu-application/configure.py (+2/-3)
data/templates/ubuntu-application/create.py (+1/-1)
data/templates/ubuntu-application/edit.py (+2/-1)
data/templates/ubuntu-application/internal/apportutils.py (+2/-2)
data/templates/ubuntu-application/internal/quicklyutils.py (+0/-62)
data/templates/ubuntu-application/store/dialog.py (+3/-3)
data/templates/ubuntu-application/store/help-guide.py (+1/-1)
data/templates/ubuntu-application/store/help-topic.py (+1/-1)
data/templates/ubuntu-application/store/indicator.py (+1/-1)
data/templates/ubuntu-application/upgrade.py (+1/-1)
data/templates/ubuntu-flash-game/create.py (+1/-1)
data/templates/ubuntu-flash-game/internal/apportutils.py (+4/-3)
data/templates/ubuntu-flash-game/internal/quicklyutils.py (+0/-40)
quickly/builtincommands.py (+33/-1)
quickly/templatetools.py (+118/-0)
To merge this branch: bzr merge lp:~quickly-committers/quickly/add_widgets
Reviewer Review Type Date Requested Status
Quickly Developers Pending
Review via email: mp+62222@code.launchpad.net

Description of the change

Allows $quickly add to add files from outside a quickly template

To post a comment you must log in.
Revision history for this message
Michael Terry (mterry) wrote :

This would be a lot easier to read if the ide branch wasn't interwoven. You can specify a prerequisite branch when filing a merge (and unfortunately, seemingly only then) which would hide that prerequisite branch on this page. Just FYI. For now I can review this using bzr directly.

Changes like this and the preferences might best be discussed on quickly-talk first, to get a sense of your direction and the technical ramifications. Especially if the discussion might change how you implement it (so you don't waste work).

I'm not sure what the goal of adding outside files from quickly widgets is? Quickly widgets is an external library meant to be used like any other python library, not pulled in directly.

Revision history for this message
Tony Byrne (tony-badwolf) wrote :

The point of this branch is for the developer who wants to make a
small modification to the template but have most of it maintained by
quickly-maintainers. One way to do that is to allow $quickly add to
pull in the developer's mods to the project itself.

Without $quickly add <outside files> means that the developer needs to
$quickly create ubuntu-application app. Then put in his favourite
files manually, app/app/foo.py, app/tests/test_foo.py. Mangle
contents of test_foo.py so it can import app.foo.

Imagine having commands like
$quickly add foo that does all of the above
$quickly add company-logo (not general enough for quickly)
$quickly add dbus-client
$quickly add dbus-server
$quickly add threading (unpopular)

 Using quickly-widgets is only a proof of concept - the simplest
plugin does not need to conform to any requirements. $quickly help add
can read the plugin docstring but doesn't require it.

 A complex plugin will have a loader like store/dialog.py.

 The primary use case, developer's favourite files, are unlikely to be
importable on the target box.

On 27/05/2011, Michael Terry <email address hidden> wrote:
> This would be a lot easier to read if the ide branch wasn't interwoven. You
> can specify a prerequisite branch when filing a merge (and unfortunately,
> seemingly only then) which would hide that prerequisite branch on this page.
> Just FYI. For now I can review this using bzr directly.
>
> Changes like this and the preferences might best be discussed on
> quickly-talk first, to get a sense of your direction and the technical
> ramifications. Especially if the discussion might change how you implement
> it (so you don't waste work).
>
> I'm not sure what the goal of adding outside files from quickly widgets is?
> Quickly widgets is an external library meant to be used like any other
> python library, not pulled in directly.
> --
> https://code.launchpad.net/~quickly-committers/quickly/add_widgets/+merge/62222
> You proposed lp:~quickly-committers/quickly/add_widgets for merging.
>

Unmerged revisions

622. By Tony Byrne <email address hidden>

moved function file_from_template(...) from quicklyutils to templatetools
updated $quickly preferences command (introduced in branch ide) to display default values
$quickly add command can add files from outside quickly
default outside files are from quickly-widgets

621. By Tony Byrne <email address hidden>

removed some junk

620. By Tony Byrne <email address hidden>

allow preferences to be edited outside project
removed quickly configure preferences
added quickly preferences
moved read_input from templates/ubuntu-application/quicklyutils.py
to quickly/templatetools.py

619. By Tony Byrne <email address hidden>

added command configure preferences

618. By Tony Byrne <email address hidden>

moved get_quickly_editors() into templatetools: same code for all templates
use a config file to allow developer use an ide for editing project keeping gedit for read_input()

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/templates/ubuntu-application/add.py'
--- data/templates/ubuntu-application/add.py 2010-11-12 00:28:53 +0000
+++ data/templates/ubuntu-application/add.py 2011-05-24 23:28:25 +0000
@@ -16,61 +16,199 @@
16#You should have received a copy of the GNU General Public License along 16#You should have received a copy of the GNU General Public License along
17#with this program. If not, see <http://www.gnu.org/licenses/>.17#with this program. If not, see <http://www.gnu.org/licenses/>.
1818
19'''Add something to your project
20
21where something can identify a python file or a script
22usual role for script is to mangle a file, load non-python files, or both'''
23
24import ast
25import glob
26import os.path
27import subprocess
19import sys28import sys
20from quickly import templatetools, commands29
2130
22import gettext31from gettext import textdomain, gettext as _
23from gettext import gettext as _
24# set domain text32# set domain text
25gettext.textdomain('quickly')33textdomain('quickly')
2634
27argv = sys.argv35from quickly import templatetools, commands, configurationhandler
2836
29from store import *37from store import *
30import store38import store
3139
32addable = [x for x in dir(store) if x[0] != '_']40ADDABLE = [x for x in dir(store) if x[0] != '_']
3341
34options = {}42OPTIONS = {}
35for module in addable:43for module in ADDABLE:
36 try:44 try:
37 options[module] = getattr(store, module).option45 OPTIONS[module] = getattr(store, module).option
38 except AttributeError:46 except AttributeError:
39 # ignore files in store that have no option for us47 # ignore files in store that have no option for us
40 pass48 pass
4149
50# if config not already loaded
51if not configurationhandler.project_config:
52 configurationhandler.loadConfig()
53 PROJECT_CONFIG = configurationhandler.project_config
54
55def get_options_from_plugin(plugin):
56 '''if the plugin needs options it should describe them'''
57
58 quickly_options = ''
59 for subnode in ast.iter_child_nodes(plugin[2]):
60 if type(subnode) == ast.Assign:
61
62 result_as_dict = {}
63 for item in ast.iter_child_nodes(subnode):
64 field = dict(ast.iter_fields(item))
65 if field.get('id') == 'QUICKLY_OPTIONS':
66 result_as_dict['id'] = 'QUICKLY_OPTIONS'
67 if field.get('s') is not None:
68 result_as_dict['s'] = field.get('s')
69
70 if result_as_dict.get('id') == 'QUICKLY_OPTIONS':
71 quickly_options = result_as_dict.get('s')
72
73 result = 'quickly add %s %s' % (plugin[0], quickly_options)
74 return result
75
76
77def get_plugins_from_path(_path):
78 '''parse plugin files using ast'''
79 _path = os.path.expanduser(_path)
80 globs = glob.glob('%s/*' % _path)
81 # get only files
82 plugin_files = [y for y in globs if os.path.isfile(y)]
83 # exclude __init__.py
84 plugin_files = [y for y in plugin_files if os.path.basename(y)[0] != '_']
85
86 _basenames = [os.path.basename(y) for y in plugin_files]
87 _names = [os.path.splitext(y)[0] for y in _basenames]
88
89 nodes = []
90 for plugin_file in plugin_files:
91 with open(plugin_file) as filepointer:
92 contents = filepointer.read()
93 node = ast.parse(contents)
94 nodes.append(node)
95
96 plugin_list = zip(_names, plugin_files, nodes)
97 results = [(y[0], y[1:]) for y in plugin_list]
98
99 _adds = [get_options_from_plugin(y) for y in plugin_list]
100
101 plugin_options = zip(_names, _adds)
102 OPTIONS.update(plugin_options)
103
104 return results
105
106PLUGIN_PATH = templatetools.option(
107 PROJECT_CONFIG['template'], 'plugin_path')
108
109PLUGINS = {}
110PLUGIN_PATHS = PLUGIN_PATH.split(':')
111for path in PLUGIN_PATHS:
112 # handle preference with superfluous colons e.g. plugin_path = :::/path1:
113 if len(path):
114 PLUGINS.update(get_plugins_from_path(path))
115
116def get_help_from_plugin(_plugin_name):
117 'use first line of docstring as help text'
118
119 _docstring = ast.get_docstring(PLUGINS.get(_plugin_name)[1], clean=True)
120 if _docstring is not None:
121 docstring_lines = _docstring.split('\n')
122 help_text = docstring_lines[0]
123 else:
124 help_text = 'no help for %s yet' % _plugin_name
125
126 return '%s\n%s' % (_plugin_name, help_text)
127
128def insert_plugin(chosen_plugin):
129 '''copy plugin to project
130 or run plugin in project'''
131 _path = chosen_plugin[0]
132 if not os.access(_path, os.X_OK):
133 project_name = PROJECT_CONFIG['project']
134 python_name = templatetools.python_name(project_name)
135
136 #to add non-python files use a runnable plugin script
137 target_dir = os.path.join(os.getcwd(), python_name)
138 templatetools.file_from_template(
139 '', _path, target_dir, [], False)
140 else:
141 # run a plugin script - similar to store/dialog.py
142 _instance = subprocess.Popen([_path] + sys.argv[2:], cwd=os.getcwd())
143 _instance.wait()
144
145# skeleton for runnable plugin script
146"""#!/usr/bin/python
147# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
148### BEGIN LICENSE
149# This file is in the public domain
150### END LICENSE
151
152'''A simple plugin'''
153import os
154import sys
155
156QUICKLY_OPTIONS = '<option>'
157
158if __name__ == "__main__":
159 SRC, DEST = os.path.dirname(os.path.abspath(__file__)), os.getcwd()
160 print __doc__
161 print 'plugin files path', SRC
162 print 'quickly project path', DEST
163 print 'options', sys.argv
164 assert SRC != DEST """
165
42def usage():166def usage():
43 templatetools.print_usage(options.values())167 '''a quickly API'''
168 templatetools.print_usage(OPTIONS.values())
44169
45def help():170def help(): # pylint: disable=W0622
171 '''a quickly API'''
46 help_list = [_('Add something to your project\n')]172 help_list = [_('Add something to your project\n')]
47 for module in addable:173 for store_module in ADDABLE:
48 try:174 try:
49 help_list.append(getattr(store, module).help_text)175 help_list.append(getattr(store, store_module).help_text)
50 except AttributeError:176 except AttributeError:
51 # ignore files in store that have no help for us177 # ignore files in store that have no help for us
52 pass178 pass
179 for plugin in PLUGINS:
180 help_list.append(get_help_from_plugin(plugin))
181
53 help_text = '\n\n'.join(help_list)182 help_text = '\n\n'.join(help_list)
54 print help_text183 print help_text
55184
185ARGV = sys.argv
186
56def shell_completion(argv):187def shell_completion(argv):
57 ''' Complete args '''188 ''' Complete args '''
58 # option completion189 # option completion
59 rv = []190 allowable_args = []
60 if len(argv) == 1:191 if len(argv) == 1:
61 rv = options.keys()192 allowable_args = OPTIONS.keys()
62 if rv:193 if allowable_args:
63 rv.sort()194 allowable_args.sort()
64 print ' '.join(rv)195 print ' '.join(allowable_args)
65templatetools.handle_additional_parameters(sys.argv, help, shell_completion, usage=usage)196
197templatetools.handle_additional_parameters(
198 sys.argv, help, shell_completion, usage=usage)
66199
67if len(sys.argv) < 2:200if len(sys.argv) < 2:
68 cmd = commands.get_command('add', 'ubuntu-application')201 CMD = commands.get_command('add', 'ubuntu-application')
69 templatetools.usage_error(_("Cannot add, no plugin name provided."), cmd=cmd, template='ubuntu-application')202 templatetools.usage_error(_("Cannot add, no plugin name provided."),
203 cmd=CMD, template='ubuntu-application')
70204
71if argv[1] in addable:205if sys.argv[1] in ADDABLE:
72 getattr(store, argv[1]).add(options)206 getattr(store, sys.argv[1]).add(OPTIONS)
207elif sys.argv[1] in PLUGINS.keys():
208 insert_plugin(PLUGINS[sys.argv[1]])
73else:209else:
74 cmd = commands.get_command('add', 'ubuntu-application')210 CMD = commands.get_command('add', 'ubuntu-application')
75 templatetools.usage_error(_('Cannot add, did not recognize plugin name: %s' % argv[1]), cmd=cmd, template='ubuntu-application')211 templatetools.usage_error(
212 _('Cannot add, did not recognize plugin name: %s' % sys.argv[1]),
213 cmd=CMD, template='ubuntu-application')
76 sys.exit(4)214 sys.exit(4)
77215
=== modified file 'data/templates/ubuntu-application/configure.py'
--- data/templates/ubuntu-application/configure.py 2010-10-18 18:39:04 +0000
+++ data/templates/ubuntu-application/configure.py 2011-05-24 23:28:25 +0000
@@ -82,7 +82,7 @@
82 if len(argv) > 2:82 if len(argv) > 2:
83 project_name = argv[2]83 project_name = argv[2]
84 else:84 else:
85 project_name = quicklyutils.read_input()85 project_name = templatetools.read_input()
86 # need to try and get the original project name if it exists. We'll need this86 # need to try and get the original project name if it exists. We'll need this
87 # to replace any existing settings87 # to replace any existing settings
88 if not configurationhandler.project_config:88 if not configurationhandler.project_config:
@@ -158,7 +158,7 @@
158 dependencies = [elem.strip() for elem in configurationhandler.project_config['dependencies'].split(',') if elem]158 dependencies = [elem.strip() for elem in configurationhandler.project_config['dependencies'].split(',') if elem]
159 except KeyError:159 except KeyError:
160 dependencies = []160 dependencies = []
161 userinput = quicklyutils.read_input('\n'.join(dependencies))161 userinput = templatetools.read_input('\n'.join(dependencies))
162 dependencies = []162 dependencies = []
163 for depends in userinput.split('\n'):163 for depends in userinput.split('\n'):
164 dependencies.extend([elem.strip() for elem in depends.split(',') if elem])164 dependencies.extend([elem.strip() for elem in depends.split(',') if elem])
@@ -174,4 +174,3 @@
174 configurationhandler.loadConfig()174 configurationhandler.loadConfig()
175 configurationhandler.project_config["target_distribution"] = argv[2]175 configurationhandler.project_config["target_distribution"] = argv[2]
176 configurationhandler.saveConfig()176 configurationhandler.saveConfig()
177
178177
=== modified file 'data/templates/ubuntu-application/create.py'
--- data/templates/ubuntu-application/create.py 2011-02-08 14:30:08 +0000
+++ data/templates/ubuntu-application/create.py 2011-05-24 23:28:25 +0000
@@ -90,7 +90,7 @@
90 directory = directory.replace('python', python_name)90 directory = directory.replace('python', python_name)
91 os.mkdir(os.path.join(relative_dir, directory))91 os.mkdir(os.path.join(relative_dir, directory))
92 for filename in files:92 for filename in files:
93 quicklyutils.file_from_template(root, filename, relative_dir, substitutions)93 templatetools.file_from_template(root, filename, relative_dir, substitutions)
9494
95# set the mode to executable for executable file 95# set the mode to executable for executable file
96exec_file = os.path.join('bin', project_name)96exec_file = os.path.join('bin', project_name)
9797
=== modified file 'data/templates/ubuntu-application/edit.py'
--- data/templates/ubuntu-application/edit.py 2011-04-27 15:02:41 +0000
+++ data/templates/ubuntu-application/edit.py 2011-05-24 23:28:25 +0000
@@ -65,7 +65,8 @@
65# add helpfile sources65# add helpfile sources
66filelist.extend(glob.glob('help/C/*.page'))66filelist.extend(glob.glob('help/C/*.page'))
6767
68editor = quicklyutils.get_quickly_editors()68editor = templatetools.get_ide(configurationhandler.project_config['template'])
69
69if templatetools.in_verbose_mode():70if templatetools.in_verbose_mode():
70 instance = subprocess.Popen([editor] + filelist)71 instance = subprocess.Popen([editor] + filelist)
71else:72else:
7273
=== modified file 'data/templates/ubuntu-application/internal/apportutils.py'
--- data/templates/ubuntu-application/internal/apportutils.py 2011-04-04 14:28:36 +0000
+++ data/templates/ubuntu-application/internal/apportutils.py 2011-05-24 23:28:25 +0000
@@ -80,13 +80,13 @@
80 print _("Creating new apport crashdb configuration")80 print _("Creating new apport crashdb configuration")
81 if not os.path.isdir(relative_crashdb_dir):81 if not os.path.isdir(relative_crashdb_dir):
82 os.makedirs(relative_crashdb_dir)82 os.makedirs(relative_crashdb_dir)
83 quicklyutils.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)83 templatetools.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)
8484
85 if not os.path.isfile(existing_hook) and os.path.isdir(template_hook_dir):85 if not os.path.isfile(existing_hook) and os.path.isdir(template_hook_dir):
86 print _("Creating new apport hooks")86 print _("Creating new apport hooks")
87 if not os.path.isdir(relative_apport_dir):87 if not os.path.isdir(relative_apport_dir):
88 os.makedirs(relative_apport_dir)88 os.makedirs(relative_apport_dir)
89 quicklyutils.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)89 templatetools.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)
9090
91def insert_lpi_if_required(project_name):91def insert_lpi_if_required(project_name):
92 camel_case_project_name = quickly.templatetools.get_camel_case_name(project_name)92 camel_case_project_name = quickly.templatetools.get_camel_case_name(project_name)
9393
=== modified file 'data/templates/ubuntu-application/internal/quicklyutils.py'
--- data/templates/ubuntu-application/internal/quicklyutils.py 2011-03-02 15:04:44 +0000
+++ data/templates/ubuntu-application/internal/quicklyutils.py 2011-05-24 23:28:25 +0000
@@ -43,30 +43,6 @@
43 camel_case_name = templatetools.get_camel_case_name(name)43 camel_case_name = templatetools.get_camel_case_name(name)
44 return sentence_name, camel_case_name44 return sentence_name, camel_case_name
4545
46def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True):
47
48 if not os.path.isfile(os.path.join(template_dir, template_file)):
49 return
50 target_file = os.path.basename(template_file) # to get only file name (template_file can be internal/file)
51 if rename:
52 for s in substitutions:
53 pattern, sub = s
54 target_file = target_file.replace(pattern,sub)
55
56 fin = open(os.path.join(template_dir, template_file),'r')
57 file_contents = fin.read()
58 for s in substitutions:
59 pattern, sub = s
60 file_contents = file_contents.replace(pattern,sub)
61
62 target_path = os.path.join(target_dir, target_file)
63 if os.path.exists(target_path):
64 print _("Failed to add file to project\n cannot add: %s - this file already exists." % target_path)
65 sys.exit(4)
66
67 templatetools.set_file_contents(target_path, file_contents)
68 fin.close()
69
70def update_file(target_file, substitutions=[], rename = True):46def update_file(target_file, substitutions=[], rename = True):
7147
72 if not os.path.isfile(target_file):48 if not os.path.isfile(target_file):
@@ -229,44 +205,6 @@
229 buffered_message +=' %s' % line205 buffered_message +=' %s' % line
230 return(changelog)206 return(changelog)
231207
232
233def get_quickly_editors():
234 '''Return prefered editor for ubuntu-application template'''
235
236 default_editor = os.environ.get("QUICKLY_EDITOR")
237 if not default_editor:
238 default_editor = os.environ.get("EDITOR")
239 if not default_editor:
240 default_editor = os.environ.get("SELECTED_EDITOR")
241 if default_editor:
242 editor = default_editor
243 elif templatetools.is_X_display():
244 editor = "gedit"
245 else:
246 editor = "nano"
247 return editor
248
249def read_input(start=''):
250 depfile_name = tempfile.mkstemp()[1]
251 open(depfile_name,'w').write(start)
252
253 # Run the editor with a new tmpdir. This is because gedit uses tmpdir
254 # to find other instances of gedit, and we don't want that. If we allowed
255 # that, gedit would return immediately and open a new tab in the other
256 # gedit. This makes it difficult to tell when user is done editing (how
257 # to detect that vs nano opening and closing without the user saving it?).
258 editor = get_quickly_editors()
259 subenv = dict(os.environ)
260 subenv['TMPDIR'] = tempfile.mkdtemp()
261 subprocess.call([editor, depfile_name], stdout=subprocess.PIPE, env=subenv)
262 os.rmdir(subenv['TMPDIR'])
263
264 # Grab file contents
265 rv = file(depfile_name, 'r').read().strip()
266 os.remove(depfile_name)
267
268 return rv
269
270def take_email_from_string(value):208def take_email_from_string(value):
271 '''Try to take an email from a string'''209 '''Try to take an email from a string'''
272210
273211
=== modified file 'data/templates/ubuntu-application/store/dialog.py'
--- data/templates/ubuntu-application/store/dialog.py 2010-11-12 00:28:53 +0000
+++ data/templates/ubuntu-application/store/dialog.py 2011-05-24 23:28:25 +0000
@@ -109,17 +109,17 @@
109 ("dialog_sentence_name",dialog_sentence_name),109 ("dialog_sentence_name",dialog_sentence_name),
110 ("python_name",python_name))110 ("python_name",python_name))
111111
112 quicklyutils.file_from_template(template_ui_dir, 112 templatetools.file_from_template(template_ui_dir,
113 "dialog_camel_case_nameDialog.ui", 113 "dialog_camel_case_nameDialog.ui",
114 target_ui_dir, 114 target_ui_dir,
115 substitutions)115 substitutions)
116116
117 quicklyutils.file_from_template(template_ui_dir, 117 templatetools.file_from_template(template_ui_dir,
118 "dialog_python_name_dialog.xml", 118 "dialog_python_name_dialog.xml",
119 target_ui_dir,119 target_ui_dir,
120 substitutions)120 substitutions)
121121
122 quicklyutils.file_from_template(template_python_dir, 122 templatetools.file_from_template(template_python_dir,
123 "dialog_camel_case_nameDialog.py", 123 "dialog_camel_case_nameDialog.py",
124 target_python_dir, 124 target_python_dir,
125 substitutions)125 substitutions)
126126
=== modified file 'data/templates/ubuntu-application/store/help-guide.py'
--- data/templates/ubuntu-application/store/help-guide.py 2010-11-22 16:01:03 +0000
+++ data/templates/ubuntu-application/store/help-guide.py 2011-05-24 23:28:25 +0000
@@ -80,6 +80,6 @@
80 ('sentence_name', sentence_name),80 ('sentence_name', sentence_name),
81 )81 )
8282
83 quicklyutils.file_from_template(template_help_dir, 83 templatetools.file_from_template(template_help_dir,
84 'g_u_i_d_e.page', 84 'g_u_i_d_e.page',
85 target_help_dir, substitutions)85 target_help_dir, substitutions)
8686
=== modified file 'data/templates/ubuntu-application/store/help-topic.py'
--- data/templates/ubuntu-application/store/help-topic.py 2010-11-22 16:01:03 +0000
+++ data/templates/ubuntu-application/store/help-topic.py 2011-05-24 23:28:25 +0000
@@ -83,6 +83,6 @@
83 ('sentence_name', sentence_name),83 ('sentence_name', sentence_name),
84 )84 )
8585
86 quicklyutils.file_from_template(template_help_dir, 86 templatetools.file_from_template(template_help_dir,
87 't_o_p_i_c.page', 87 't_o_p_i_c.page',
88 target_help_dir, substitutions)88 target_help_dir, substitutions)
8989
=== modified file 'data/templates/ubuntu-application/store/indicator.py'
--- data/templates/ubuntu-application/store/indicator.py 2010-11-22 16:01:03 +0000
+++ data/templates/ubuntu-application/store/indicator.py 2011-05-24 23:28:25 +0000
@@ -59,7 +59,7 @@
59 substitutions = (("project_name",project_name),59 substitutions = (("project_name",project_name),
60 ( "python_name",python_name))60 ( "python_name",python_name))
6161
62 quicklyutils.file_from_template(template_python_dir, 62 templatetools.file_from_template(template_python_dir,
63 "indicator.py", 63 "indicator.py",
64 target_python_dir, 64 target_python_dir,
65 substitutions)65 substitutions)
6666
=== modified file 'data/templates/ubuntu-application/upgrade.py'
--- data/templates/ubuntu-application/upgrade.py 2011-01-31 21:59:12 +0000
+++ data/templates/ubuntu-application/upgrade.py 2011-05-24 23:28:25 +0000
@@ -150,7 +150,7 @@
150 if not os.path.isfile('%s/helpers.py' % python_name) and os.path.isdir(python_name):150 if not os.path.isfile('%s/helpers.py' % python_name) and os.path.isdir(python_name):
151 source_dir = os.path.join(os.path.dirname(__file__), 'project_root',151 source_dir = os.path.join(os.path.dirname(__file__), 'project_root',
152 'python')152 'python')
153 quicklyutils.file_from_template(source_dir, 153 templatetools.file_from_template(source_dir,
154 "helpers.py", 154 "helpers.py",
155 python_name, 155 python_name,
156 substitutions)156 substitutions)
157157
=== modified file 'data/templates/ubuntu-flash-game/create.py'
--- data/templates/ubuntu-flash-game/create.py 2011-01-31 21:12:12 +0000
+++ data/templates/ubuntu-flash-game/create.py 2011-05-24 23:28:25 +0000
@@ -121,7 +121,7 @@
121 directory = python_name121 directory = python_name
122 os.mkdir(os.path.join(relative_dir, directory))122 os.mkdir(os.path.join(relative_dir, directory))
123 for filename in files:123 for filename in files:
124 quicklyutils.file_from_template(root, filename, relative_dir, substitutions)124 templatetools.file_from_template(root, filename, relative_dir, substitutions)
125125
126# set the mode to executable for executable file 126# set the mode to executable for executable file
127exec_file = os.path.join('bin', project_name)127exec_file = os.path.join('bin', project_name)
128128
=== modified file 'data/templates/ubuntu-flash-game/internal/apportutils.py'
--- data/templates/ubuntu-flash-game/internal/apportutils.py 2011-01-03 15:07:28 +0000
+++ data/templates/ubuntu-flash-game/internal/apportutils.py 2011-05-24 23:28:25 +0000
@@ -6,6 +6,7 @@
66
7import quickly7import quickly
8import quicklyutils8import quicklyutils
9from quickly import templatetools
910
10from lxml import etree11from lxml import etree
1112
@@ -66,18 +67,18 @@
6667
67 if os.path.isfile(existing_crashdb):68 if os.path.isfile(existing_crashdb):
68 print _("Updating project name references in existing apport crashdb configuration")69 print _("Updating project name references in existing apport crashdb configuration")
69 quicklyutils.file_from_template(relative_crashdb_dir, crashdb_file, relative_crashdb_dir, subst_existing)70 templatetools.file_from_template(relative_crashdb_dir, crashdb_file, relative_crashdb_dir, subst_existing)
70 elif os.path.isdir(template_crashdb_dir):71 elif os.path.isdir(template_crashdb_dir):
71 print _("Creating new apport crashdb configuration")72 print _("Creating new apport crashdb configuration")
72 if not os.path.isdir(relative_crashdb_dir):73 if not os.path.isdir(relative_crashdb_dir):
73 os.makedirs(relative_crashdb_dir)74 os.makedirs(relative_crashdb_dir)
74 quicklyutils.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)75 templatetools.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)
7576
76 if not os.path.isfile(existing_hook) and os.path.isdir(template_hook_dir):77 if not os.path.isfile(existing_hook) and os.path.isdir(template_hook_dir):
77 print _("Creating new apport hooks")78 print _("Creating new apport hooks")
78 if not os.path.isdir(relative_apport_dir):79 if not os.path.isdir(relative_apport_dir):
79 os.makedirs(relative_apport_dir)80 os.makedirs(relative_apport_dir)
80 quicklyutils.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)81 templatetools.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)
8182
82def insert_lpi_if_required(project_name):83def insert_lpi_if_required(project_name):
83 existing_bin_filename = os.path.join("bin",project_name)84 existing_bin_filename = os.path.join("bin",project_name)
8485
=== modified file 'data/templates/ubuntu-flash-game/internal/quicklyutils.py'
--- data/templates/ubuntu-flash-game/internal/quicklyutils.py 2011-01-03 15:07:28 +0000
+++ data/templates/ubuntu-flash-game/internal/quicklyutils.py 2011-05-24 23:28:25 +0000
@@ -42,33 +42,6 @@
42 camel_case_name = templatetools.get_camel_case_name(name)42 camel_case_name = templatetools.get_camel_case_name(name)
43 return sentence_name, camel_case_name43 return sentence_name, camel_case_name
4444
45def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True):
46
47 if not os.path.isfile(os.path.join(template_dir, template_file)):
48 return
49 target_file = os.path.basename(template_file) # to get only file name (template_file can be internal/file)
50 if rename:
51 for s in substitutions:
52 pattern, sub = s
53 target_file = target_file.replace(pattern,sub)
54
55 fin = open(os.path.join(template_dir, template_file),'r')
56 file_contents = fin.read()
57 for s in substitutions:
58 pattern, sub = s
59 file_contents = file_contents.replace(pattern,sub)
60
61 target_path = os.path.join(target_dir, target_file)
62 if os.path.exists(target_path):
63 print _("Failed to add file to project\n cannot add: %s - this file already exists." % target_path)
64 sys.exit(4)
65
66 fout = open(target_path, 'w')
67 fout.write(file_contents)
68 fout.flush()
69 fout.close()
70 fin.close()
71
72def get_setup_value(key):45def get_setup_value(key):
73 """ get value from setup.py file.46 """ get value from setup.py file.
74 47
@@ -209,19 +182,6 @@
209 buffered_message +=' %s' % line182 buffered_message +=' %s' % line
210 return(changelog)183 return(changelog)
211184
212
213def get_quickly_editors():
214 '''Return prefered editor for ubuntu-application template'''
215
216 editor = "gedit"
217 default_editor = os.environ.get("EDITOR")
218 if not default_editor:
219 default_editor = os.environ.get("SELECTED_EDITOR")
220 if default_editor:
221 editor = default_editor
222 return editor
223
224
225def take_email_from_string(value):185def take_email_from_string(value):
226 '''Try to take an email from a string'''186 '''Try to take an email from a string'''
227187
228188
=== modified file 'quickly/builtincommands.py'
--- quickly/builtincommands.py 2010-11-29 15:18:46 +0000
+++ quickly/builtincommands.py 2011-05-24 23:28:25 +0000
@@ -15,8 +15,10 @@
15#You should have received a copy of the GNU General Public License along 15#You should have received a copy of the GNU General Public License along
16#with this program. If not, see <http://www.gnu.org/licenses/>.16#with this program. If not, see <http://www.gnu.org/licenses/>.
1717
18import ConfigParser
18import os19import os
19import shutil20import shutil
21import StringIO
20import sys22import sys
2123
22import configurationhandler24import configurationhandler
@@ -211,7 +213,37 @@
211 os.rename(filedest.name, commandsconfig_path)213 os.rename(filedest.name, commandsconfig_path)
212 return 0214 return 0
213215
214216help_preferences = _("Edit developers preferences")
217usage_preferences = _("Usage: quickly preferences")
218def preferences(project_template, project_dir, command_args, shell_completion=False):
219 """Configure preferences"""
220
221 # We have nothing for this
222 if shell_completion:
223 return("")
224
225 preferences = templatetools.get_preferences()
226
227 #convert preferences into editable contents
228 fp_current = StringIO.StringIO()
229 # TODO use a pretty printer
230 preferences.write(fp_current)
231 contents = fp_current.getvalue()
232 fp_current.close()
233
234 # ask developer to edit the contents
235 newcontents = templatetools.read_input(contents)
236
237 # convert the contents back into a ConfigParser object
238 newIO = StringIO.StringIO(newcontents)
239 new_preferences = ConfigParser.SafeConfigParser()
240 # an exception here reject bad edits
241 new_preferences.readfp(newIO)
242
243 templatetools.set_preferences(new_preferences)
244
245
246 return 0
215247
216# here, special builtin commands properties (if nothing specified, commands can be launched inside and outside projects)248# here, special builtin commands properties (if nothing specified, commands can be launched inside and outside projects)
217launched_inside_project_only = []249launched_inside_project_only = []
218250
=== modified file 'quickly/templatetools.py'
--- quickly/templatetools.py 2010-12-20 20:33:12 +0000
+++ quickly/templatetools.py 2011-05-24 23:28:25 +0000
@@ -15,15 +15,20 @@
15#You should have received a copy of the GNU General Public License along15#You should have received a copy of the GNU General Public License along
16#with this program. If not, see <http://www.gnu.org/licenses/>.16#with this program. If not, see <http://www.gnu.org/licenses/>.
1717
18import ConfigParser
18import os19import os
19import stat20import stat
20import string21import string
22import subprocess
21import sys23import sys
22import re24import re
25import tempfile
2326
24import gettext27import gettext
25from gettext import gettext as _28from gettext import gettext as _
2629
30import glib
31
27import configurationhandler32import configurationhandler
28import tools33import tools
29import quicklyconfig34import quicklyconfig
@@ -256,3 +261,116 @@
256 print_command_candidates(template)261 print_command_candidates(template)
257 sys.exit(4)262 sys.exit(4)
258263
264def get_preferences():
265 'parse ~/.config/quickly/preferences for configuration'
266
267 # fill in defaults
268 defaults = {}
269 defaults['plugin_path'] = '/usr/share/pyshared/quickly/widgets'
270 defaults['#plugin_path'] = 'files which can be used with quickly add command'
271
272 ide = get_quickly_editors()
273 defaults['ide'] = get_quickly_editors()
274 defaults['#ide'] = 'editor defined in environment'
275
276 preferences = ConfigParser.RawConfigParser(defaults)
277
278 # ensure there is a section for each template
279 template_names = commands.get_all_templates()
280 for template_name in template_names:
281 preferences.add_section(template_name)
282
283 config_dir = os.path.join(glib.get_user_config_dir(), 'quickly')
284 config_file = os.path.join(config_dir, 'preferences')
285 preferences.read(config_file)
286
287 return preferences
288
289def set_preferences(new_preferences):
290 'write ~/.config/quickly/preferences'
291
292 config_dir = os.path.join(glib.get_user_config_dir(), 'quickly')
293 config_file = os.path.join(config_dir, 'preferences')
294
295 # ensure config_dir exists
296 if not os.path.isdir(config_dir):
297 os.makedirs(config_dir)
298
299 # write the preferences file
300 with open(config_file, 'w') as fp:
301 new_preferences.write(fp)
302
303def get_quickly_editors():
304 '''Return prefered editor for any template'''
305
306 default_editor = os.environ.get("QUICKLY_EDITOR")
307 if not default_editor:
308 default_editor = os.environ.get("EDITOR")
309 if not default_editor:
310 default_editor = os.environ.get("SELECTED_EDITOR")
311 if default_editor:
312 editor = default_editor
313 elif is_X_display():
314 editor = "gedit"
315 else:
316 editor = "nano"
317 return editor
318
319def read_input(start=''):
320 depfile_name = tempfile.mkstemp()[1]
321 open(depfile_name,'w').write(start)
322
323 # Run the editor with a new tmpdir. This is because gedit uses tmpdir
324 # to find other instances of gedit, and we don't want that. If we allowed
325 # that, gedit would return immediately and open a new tab in the other
326 # gedit. This makes it difficult to tell when user is done editing (how
327 # to detect that vs nano opening and closing without the user saving it?).
328 editor = get_quickly_editors()
329 subenv = dict(os.environ)
330 subenv['TMPDIR'] = tempfile.mkdtemp()
331 subprocess.call([editor, depfile_name], stdout=subprocess.PIPE, env=subenv)
332 os.rmdir(subenv['TMPDIR'])
333
334 # Grab file contents
335 rv = file(depfile_name, 'r').read().strip()
336 os.remove(depfile_name)
337
338 return rv
339
340def get_ide(template):
341 '''Return prefered editor for specified template'''
342 preferences = get_preferences()
343
344 if preferences.has_option(template, 'ide'):
345 return preferences.get(template, 'ide')
346 else:
347 return get_quickly_editors()
348
349def option(template, option):
350 '''Return prefered option for specified template'''
351 preferences = get_preferences()
352 return preferences.get(template, option)
353
354def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True):
355
356 if not os.path.isfile(os.path.join(template_dir, template_file)):
357 return
358 target_file = os.path.basename(template_file) # to get only file name (template_file can be internal/file)
359 if rename:
360 for s in substitutions:
361 pattern, sub = s
362 target_file = target_file.replace(pattern,sub)
363
364 fin = open(os.path.join(template_dir, template_file),'r')
365 file_contents = fin.read()
366 for s in substitutions:
367 pattern, sub = s
368 file_contents = file_contents.replace(pattern,sub)
369
370 target_path = os.path.join(target_dir, target_file)
371 if os.path.exists(target_path):
372 print _("Failed to add file to project\n cannot add: %s - this file already exists." % target_path)
373 sys.exit(4)
374
375 set_file_contents(target_path, file_contents)
376 fin.close()

Subscribers

People subscribed via source and target branches