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
1=== modified file 'data/templates/ubuntu-application/add.py'
2--- data/templates/ubuntu-application/add.py 2010-11-12 00:28:53 +0000
3+++ data/templates/ubuntu-application/add.py 2011-05-24 23:28:25 +0000
4@@ -16,61 +16,199 @@
5 #You should have received a copy of the GNU General Public License along
6 #with this program. If not, see <http://www.gnu.org/licenses/>.
7
8+'''Add something to your project
9+
10+where something can identify a python file or a script
11+usual role for script is to mangle a file, load non-python files, or both'''
12+
13+import ast
14+import glob
15+import os.path
16+import subprocess
17 import sys
18-from quickly import templatetools, commands
19-
20-import gettext
21-from gettext import gettext as _
22+
23+
24+from gettext import textdomain, gettext as _
25 # set domain text
26-gettext.textdomain('quickly')
27+textdomain('quickly')
28
29-argv = sys.argv
30+from quickly import templatetools, commands, configurationhandler
31
32 from store import *
33 import store
34
35-addable = [x for x in dir(store) if x[0] != '_']
36+ADDABLE = [x for x in dir(store) if x[0] != '_']
37
38-options = {}
39-for module in addable:
40+OPTIONS = {}
41+for module in ADDABLE:
42 try:
43- options[module] = getattr(store, module).option
44+ OPTIONS[module] = getattr(store, module).option
45 except AttributeError:
46 # ignore files in store that have no option for us
47 pass
48
49+# if config not already loaded
50+if not configurationhandler.project_config:
51+ configurationhandler.loadConfig()
52+ PROJECT_CONFIG = configurationhandler.project_config
53+
54+def get_options_from_plugin(plugin):
55+ '''if the plugin needs options it should describe them'''
56+
57+ quickly_options = ''
58+ for subnode in ast.iter_child_nodes(plugin[2]):
59+ if type(subnode) == ast.Assign:
60+
61+ result_as_dict = {}
62+ for item in ast.iter_child_nodes(subnode):
63+ field = dict(ast.iter_fields(item))
64+ if field.get('id') == 'QUICKLY_OPTIONS':
65+ result_as_dict['id'] = 'QUICKLY_OPTIONS'
66+ if field.get('s') is not None:
67+ result_as_dict['s'] = field.get('s')
68+
69+ if result_as_dict.get('id') == 'QUICKLY_OPTIONS':
70+ quickly_options = result_as_dict.get('s')
71+
72+ result = 'quickly add %s %s' % (plugin[0], quickly_options)
73+ return result
74+
75+
76+def get_plugins_from_path(_path):
77+ '''parse plugin files using ast'''
78+ _path = os.path.expanduser(_path)
79+ globs = glob.glob('%s/*' % _path)
80+ # get only files
81+ plugin_files = [y for y in globs if os.path.isfile(y)]
82+ # exclude __init__.py
83+ plugin_files = [y for y in plugin_files if os.path.basename(y)[0] != '_']
84+
85+ _basenames = [os.path.basename(y) for y in plugin_files]
86+ _names = [os.path.splitext(y)[0] for y in _basenames]
87+
88+ nodes = []
89+ for plugin_file in plugin_files:
90+ with open(plugin_file) as filepointer:
91+ contents = filepointer.read()
92+ node = ast.parse(contents)
93+ nodes.append(node)
94+
95+ plugin_list = zip(_names, plugin_files, nodes)
96+ results = [(y[0], y[1:]) for y in plugin_list]
97+
98+ _adds = [get_options_from_plugin(y) for y in plugin_list]
99+
100+ plugin_options = zip(_names, _adds)
101+ OPTIONS.update(plugin_options)
102+
103+ return results
104+
105+PLUGIN_PATH = templatetools.option(
106+ PROJECT_CONFIG['template'], 'plugin_path')
107+
108+PLUGINS = {}
109+PLUGIN_PATHS = PLUGIN_PATH.split(':')
110+for path in PLUGIN_PATHS:
111+ # handle preference with superfluous colons e.g. plugin_path = :::/path1:
112+ if len(path):
113+ PLUGINS.update(get_plugins_from_path(path))
114+
115+def get_help_from_plugin(_plugin_name):
116+ 'use first line of docstring as help text'
117+
118+ _docstring = ast.get_docstring(PLUGINS.get(_plugin_name)[1], clean=True)
119+ if _docstring is not None:
120+ docstring_lines = _docstring.split('\n')
121+ help_text = docstring_lines[0]
122+ else:
123+ help_text = 'no help for %s yet' % _plugin_name
124+
125+ return '%s\n%s' % (_plugin_name, help_text)
126+
127+def insert_plugin(chosen_plugin):
128+ '''copy plugin to project
129+ or run plugin in project'''
130+ _path = chosen_plugin[0]
131+ if not os.access(_path, os.X_OK):
132+ project_name = PROJECT_CONFIG['project']
133+ python_name = templatetools.python_name(project_name)
134+
135+ #to add non-python files use a runnable plugin script
136+ target_dir = os.path.join(os.getcwd(), python_name)
137+ templatetools.file_from_template(
138+ '', _path, target_dir, [], False)
139+ else:
140+ # run a plugin script - similar to store/dialog.py
141+ _instance = subprocess.Popen([_path] + sys.argv[2:], cwd=os.getcwd())
142+ _instance.wait()
143+
144+# skeleton for runnable plugin script
145+"""#!/usr/bin/python
146+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
147+### BEGIN LICENSE
148+# This file is in the public domain
149+### END LICENSE
150+
151+'''A simple plugin'''
152+import os
153+import sys
154+
155+QUICKLY_OPTIONS = '<option>'
156+
157+if __name__ == "__main__":
158+ SRC, DEST = os.path.dirname(os.path.abspath(__file__)), os.getcwd()
159+ print __doc__
160+ print 'plugin files path', SRC
161+ print 'quickly project path', DEST
162+ print 'options', sys.argv
163+ assert SRC != DEST """
164+
165 def usage():
166- templatetools.print_usage(options.values())
167+ '''a quickly API'''
168+ templatetools.print_usage(OPTIONS.values())
169
170-def help():
171+def help(): # pylint: disable=W0622
172+ '''a quickly API'''
173 help_list = [_('Add something to your project\n')]
174- for module in addable:
175+ for store_module in ADDABLE:
176 try:
177- help_list.append(getattr(store, module).help_text)
178+ help_list.append(getattr(store, store_module).help_text)
179 except AttributeError:
180 # ignore files in store that have no help for us
181 pass
182+ for plugin in PLUGINS:
183+ help_list.append(get_help_from_plugin(plugin))
184+
185 help_text = '\n\n'.join(help_list)
186 print help_text
187
188+ARGV = sys.argv
189+
190 def shell_completion(argv):
191 ''' Complete args '''
192 # option completion
193- rv = []
194+ allowable_args = []
195 if len(argv) == 1:
196- rv = options.keys()
197- if rv:
198- rv.sort()
199- print ' '.join(rv)
200-templatetools.handle_additional_parameters(sys.argv, help, shell_completion, usage=usage)
201+ allowable_args = OPTIONS.keys()
202+ if allowable_args:
203+ allowable_args.sort()
204+ print ' '.join(allowable_args)
205+
206+templatetools.handle_additional_parameters(
207+ sys.argv, help, shell_completion, usage=usage)
208
209 if len(sys.argv) < 2:
210- cmd = commands.get_command('add', 'ubuntu-application')
211- templatetools.usage_error(_("Cannot add, no plugin name provided."), cmd=cmd, template='ubuntu-application')
212+ CMD = commands.get_command('add', 'ubuntu-application')
213+ templatetools.usage_error(_("Cannot add, no plugin name provided."),
214+ cmd=CMD, template='ubuntu-application')
215
216-if argv[1] in addable:
217- getattr(store, argv[1]).add(options)
218+if sys.argv[1] in ADDABLE:
219+ getattr(store, sys.argv[1]).add(OPTIONS)
220+elif sys.argv[1] in PLUGINS.keys():
221+ insert_plugin(PLUGINS[sys.argv[1]])
222 else:
223- cmd = commands.get_command('add', 'ubuntu-application')
224- templatetools.usage_error(_('Cannot add, did not recognize plugin name: %s' % argv[1]), cmd=cmd, template='ubuntu-application')
225+ CMD = commands.get_command('add', 'ubuntu-application')
226+ templatetools.usage_error(
227+ _('Cannot add, did not recognize plugin name: %s' % sys.argv[1]),
228+ cmd=CMD, template='ubuntu-application')
229 sys.exit(4)
230
231=== modified file 'data/templates/ubuntu-application/configure.py'
232--- data/templates/ubuntu-application/configure.py 2010-10-18 18:39:04 +0000
233+++ data/templates/ubuntu-application/configure.py 2011-05-24 23:28:25 +0000
234@@ -82,7 +82,7 @@
235 if len(argv) > 2:
236 project_name = argv[2]
237 else:
238- project_name = quicklyutils.read_input()
239+ project_name = templatetools.read_input()
240 # need to try and get the original project name if it exists. We'll need this
241 # to replace any existing settings
242 if not configurationhandler.project_config:
243@@ -158,7 +158,7 @@
244 dependencies = [elem.strip() for elem in configurationhandler.project_config['dependencies'].split(',') if elem]
245 except KeyError:
246 dependencies = []
247- userinput = quicklyutils.read_input('\n'.join(dependencies))
248+ userinput = templatetools.read_input('\n'.join(dependencies))
249 dependencies = []
250 for depends in userinput.split('\n'):
251 dependencies.extend([elem.strip() for elem in depends.split(',') if elem])
252@@ -174,4 +174,3 @@
253 configurationhandler.loadConfig()
254 configurationhandler.project_config["target_distribution"] = argv[2]
255 configurationhandler.saveConfig()
256-
257
258=== modified file 'data/templates/ubuntu-application/create.py'
259--- data/templates/ubuntu-application/create.py 2011-02-08 14:30:08 +0000
260+++ data/templates/ubuntu-application/create.py 2011-05-24 23:28:25 +0000
261@@ -90,7 +90,7 @@
262 directory = directory.replace('python', python_name)
263 os.mkdir(os.path.join(relative_dir, directory))
264 for filename in files:
265- quicklyutils.file_from_template(root, filename, relative_dir, substitutions)
266+ templatetools.file_from_template(root, filename, relative_dir, substitutions)
267
268 # set the mode to executable for executable file
269 exec_file = os.path.join('bin', project_name)
270
271=== modified file 'data/templates/ubuntu-application/edit.py'
272--- data/templates/ubuntu-application/edit.py 2011-04-27 15:02:41 +0000
273+++ data/templates/ubuntu-application/edit.py 2011-05-24 23:28:25 +0000
274@@ -65,7 +65,8 @@
275 # add helpfile sources
276 filelist.extend(glob.glob('help/C/*.page'))
277
278-editor = quicklyutils.get_quickly_editors()
279+editor = templatetools.get_ide(configurationhandler.project_config['template'])
280+
281 if templatetools.in_verbose_mode():
282 instance = subprocess.Popen([editor] + filelist)
283 else:
284
285=== modified file 'data/templates/ubuntu-application/internal/apportutils.py'
286--- data/templates/ubuntu-application/internal/apportutils.py 2011-04-04 14:28:36 +0000
287+++ data/templates/ubuntu-application/internal/apportutils.py 2011-05-24 23:28:25 +0000
288@@ -80,13 +80,13 @@
289 print _("Creating new apport crashdb configuration")
290 if not os.path.isdir(relative_crashdb_dir):
291 os.makedirs(relative_crashdb_dir)
292- quicklyutils.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)
293+ templatetools.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)
294
295 if not os.path.isfile(existing_hook) and os.path.isdir(template_hook_dir):
296 print _("Creating new apport hooks")
297 if not os.path.isdir(relative_apport_dir):
298 os.makedirs(relative_apport_dir)
299- quicklyutils.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)
300+ templatetools.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)
301
302 def insert_lpi_if_required(project_name):
303 camel_case_project_name = quickly.templatetools.get_camel_case_name(project_name)
304
305=== modified file 'data/templates/ubuntu-application/internal/quicklyutils.py'
306--- data/templates/ubuntu-application/internal/quicklyutils.py 2011-03-02 15:04:44 +0000
307+++ data/templates/ubuntu-application/internal/quicklyutils.py 2011-05-24 23:28:25 +0000
308@@ -43,30 +43,6 @@
309 camel_case_name = templatetools.get_camel_case_name(name)
310 return sentence_name, camel_case_name
311
312-def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True):
313-
314- if not os.path.isfile(os.path.join(template_dir, template_file)):
315- return
316- target_file = os.path.basename(template_file) # to get only file name (template_file can be internal/file)
317- if rename:
318- for s in substitutions:
319- pattern, sub = s
320- target_file = target_file.replace(pattern,sub)
321-
322- fin = open(os.path.join(template_dir, template_file),'r')
323- file_contents = fin.read()
324- for s in substitutions:
325- pattern, sub = s
326- file_contents = file_contents.replace(pattern,sub)
327-
328- target_path = os.path.join(target_dir, target_file)
329- if os.path.exists(target_path):
330- print _("Failed to add file to project\n cannot add: %s - this file already exists." % target_path)
331- sys.exit(4)
332-
333- templatetools.set_file_contents(target_path, file_contents)
334- fin.close()
335-
336 def update_file(target_file, substitutions=[], rename = True):
337
338 if not os.path.isfile(target_file):
339@@ -229,44 +205,6 @@
340 buffered_message +=' %s' % line
341 return(changelog)
342
343-
344-def get_quickly_editors():
345- '''Return prefered editor for ubuntu-application template'''
346-
347- default_editor = os.environ.get("QUICKLY_EDITOR")
348- if not default_editor:
349- default_editor = os.environ.get("EDITOR")
350- if not default_editor:
351- default_editor = os.environ.get("SELECTED_EDITOR")
352- if default_editor:
353- editor = default_editor
354- elif templatetools.is_X_display():
355- editor = "gedit"
356- else:
357- editor = "nano"
358- return editor
359-
360-def read_input(start=''):
361- depfile_name = tempfile.mkstemp()[1]
362- open(depfile_name,'w').write(start)
363-
364- # Run the editor with a new tmpdir. This is because gedit uses tmpdir
365- # to find other instances of gedit, and we don't want that. If we allowed
366- # that, gedit would return immediately and open a new tab in the other
367- # gedit. This makes it difficult to tell when user is done editing (how
368- # to detect that vs nano opening and closing without the user saving it?).
369- editor = get_quickly_editors()
370- subenv = dict(os.environ)
371- subenv['TMPDIR'] = tempfile.mkdtemp()
372- subprocess.call([editor, depfile_name], stdout=subprocess.PIPE, env=subenv)
373- os.rmdir(subenv['TMPDIR'])
374-
375- # Grab file contents
376- rv = file(depfile_name, 'r').read().strip()
377- os.remove(depfile_name)
378-
379- return rv
380-
381 def take_email_from_string(value):
382 '''Try to take an email from a string'''
383
384
385=== modified file 'data/templates/ubuntu-application/store/dialog.py'
386--- data/templates/ubuntu-application/store/dialog.py 2010-11-12 00:28:53 +0000
387+++ data/templates/ubuntu-application/store/dialog.py 2011-05-24 23:28:25 +0000
388@@ -109,17 +109,17 @@
389 ("dialog_sentence_name",dialog_sentence_name),
390 ("python_name",python_name))
391
392- quicklyutils.file_from_template(template_ui_dir,
393+ templatetools.file_from_template(template_ui_dir,
394 "dialog_camel_case_nameDialog.ui",
395 target_ui_dir,
396 substitutions)
397
398- quicklyutils.file_from_template(template_ui_dir,
399+ templatetools.file_from_template(template_ui_dir,
400 "dialog_python_name_dialog.xml",
401 target_ui_dir,
402 substitutions)
403
404- quicklyutils.file_from_template(template_python_dir,
405+ templatetools.file_from_template(template_python_dir,
406 "dialog_camel_case_nameDialog.py",
407 target_python_dir,
408 substitutions)
409
410=== modified file 'data/templates/ubuntu-application/store/help-guide.py'
411--- data/templates/ubuntu-application/store/help-guide.py 2010-11-22 16:01:03 +0000
412+++ data/templates/ubuntu-application/store/help-guide.py 2011-05-24 23:28:25 +0000
413@@ -80,6 +80,6 @@
414 ('sentence_name', sentence_name),
415 )
416
417- quicklyutils.file_from_template(template_help_dir,
418+ templatetools.file_from_template(template_help_dir,
419 'g_u_i_d_e.page',
420 target_help_dir, substitutions)
421
422=== modified file 'data/templates/ubuntu-application/store/help-topic.py'
423--- data/templates/ubuntu-application/store/help-topic.py 2010-11-22 16:01:03 +0000
424+++ data/templates/ubuntu-application/store/help-topic.py 2011-05-24 23:28:25 +0000
425@@ -83,6 +83,6 @@
426 ('sentence_name', sentence_name),
427 )
428
429- quicklyutils.file_from_template(template_help_dir,
430+ templatetools.file_from_template(template_help_dir,
431 't_o_p_i_c.page',
432 target_help_dir, substitutions)
433
434=== modified file 'data/templates/ubuntu-application/store/indicator.py'
435--- data/templates/ubuntu-application/store/indicator.py 2010-11-22 16:01:03 +0000
436+++ data/templates/ubuntu-application/store/indicator.py 2011-05-24 23:28:25 +0000
437@@ -59,7 +59,7 @@
438 substitutions = (("project_name",project_name),
439 ( "python_name",python_name))
440
441- quicklyutils.file_from_template(template_python_dir,
442+ templatetools.file_from_template(template_python_dir,
443 "indicator.py",
444 target_python_dir,
445 substitutions)
446
447=== modified file 'data/templates/ubuntu-application/upgrade.py'
448--- data/templates/ubuntu-application/upgrade.py 2011-01-31 21:59:12 +0000
449+++ data/templates/ubuntu-application/upgrade.py 2011-05-24 23:28:25 +0000
450@@ -150,7 +150,7 @@
451 if not os.path.isfile('%s/helpers.py' % python_name) and os.path.isdir(python_name):
452 source_dir = os.path.join(os.path.dirname(__file__), 'project_root',
453 'python')
454- quicklyutils.file_from_template(source_dir,
455+ templatetools.file_from_template(source_dir,
456 "helpers.py",
457 python_name,
458 substitutions)
459
460=== modified file 'data/templates/ubuntu-flash-game/create.py'
461--- data/templates/ubuntu-flash-game/create.py 2011-01-31 21:12:12 +0000
462+++ data/templates/ubuntu-flash-game/create.py 2011-05-24 23:28:25 +0000
463@@ -121,7 +121,7 @@
464 directory = python_name
465 os.mkdir(os.path.join(relative_dir, directory))
466 for filename in files:
467- quicklyutils.file_from_template(root, filename, relative_dir, substitutions)
468+ templatetools.file_from_template(root, filename, relative_dir, substitutions)
469
470 # set the mode to executable for executable file
471 exec_file = os.path.join('bin', project_name)
472
473=== modified file 'data/templates/ubuntu-flash-game/internal/apportutils.py'
474--- data/templates/ubuntu-flash-game/internal/apportutils.py 2011-01-03 15:07:28 +0000
475+++ data/templates/ubuntu-flash-game/internal/apportutils.py 2011-05-24 23:28:25 +0000
476@@ -6,6 +6,7 @@
477
478 import quickly
479 import quicklyutils
480+from quickly import templatetools
481
482 from lxml import etree
483
484@@ -66,18 +67,18 @@
485
486 if os.path.isfile(existing_crashdb):
487 print _("Updating project name references in existing apport crashdb configuration")
488- quicklyutils.file_from_template(relative_crashdb_dir, crashdb_file, relative_crashdb_dir, subst_existing)
489+ templatetools.file_from_template(relative_crashdb_dir, crashdb_file, relative_crashdb_dir, subst_existing)
490 elif os.path.isdir(template_crashdb_dir):
491 print _("Creating new apport crashdb configuration")
492 if not os.path.isdir(relative_crashdb_dir):
493 os.makedirs(relative_crashdb_dir)
494- quicklyutils.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)
495+ templatetools.file_from_template(template_crashdb_dir, "project_name-crashdb.conf", relative_crashdb_dir, subst_new)
496
497 if not os.path.isfile(existing_hook) and os.path.isdir(template_hook_dir):
498 print _("Creating new apport hooks")
499 if not os.path.isdir(relative_apport_dir):
500 os.makedirs(relative_apport_dir)
501- quicklyutils.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)
502+ templatetools.file_from_template(template_hook_dir, "source_project_name.py", relative_apport_dir, subst_new)
503
504 def insert_lpi_if_required(project_name):
505 existing_bin_filename = os.path.join("bin",project_name)
506
507=== modified file 'data/templates/ubuntu-flash-game/internal/quicklyutils.py'
508--- data/templates/ubuntu-flash-game/internal/quicklyutils.py 2011-01-03 15:07:28 +0000
509+++ data/templates/ubuntu-flash-game/internal/quicklyutils.py 2011-05-24 23:28:25 +0000
510@@ -42,33 +42,6 @@
511 camel_case_name = templatetools.get_camel_case_name(name)
512 return sentence_name, camel_case_name
513
514-def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True):
515-
516- if not os.path.isfile(os.path.join(template_dir, template_file)):
517- return
518- target_file = os.path.basename(template_file) # to get only file name (template_file can be internal/file)
519- if rename:
520- for s in substitutions:
521- pattern, sub = s
522- target_file = target_file.replace(pattern,sub)
523-
524- fin = open(os.path.join(template_dir, template_file),'r')
525- file_contents = fin.read()
526- for s in substitutions:
527- pattern, sub = s
528- file_contents = file_contents.replace(pattern,sub)
529-
530- target_path = os.path.join(target_dir, target_file)
531- if os.path.exists(target_path):
532- print _("Failed to add file to project\n cannot add: %s - this file already exists." % target_path)
533- sys.exit(4)
534-
535- fout = open(target_path, 'w')
536- fout.write(file_contents)
537- fout.flush()
538- fout.close()
539- fin.close()
540-
541 def get_setup_value(key):
542 """ get value from setup.py file.
543
544@@ -209,19 +182,6 @@
545 buffered_message +=' %s' % line
546 return(changelog)
547
548-
549-def get_quickly_editors():
550- '''Return prefered editor for ubuntu-application template'''
551-
552- editor = "gedit"
553- default_editor = os.environ.get("EDITOR")
554- if not default_editor:
555- default_editor = os.environ.get("SELECTED_EDITOR")
556- if default_editor:
557- editor = default_editor
558- return editor
559-
560-
561 def take_email_from_string(value):
562 '''Try to take an email from a string'''
563
564
565=== modified file 'quickly/builtincommands.py'
566--- quickly/builtincommands.py 2010-11-29 15:18:46 +0000
567+++ quickly/builtincommands.py 2011-05-24 23:28:25 +0000
568@@ -15,8 +15,10 @@
569 #You should have received a copy of the GNU General Public License along
570 #with this program. If not, see <http://www.gnu.org/licenses/>.
571
572+import ConfigParser
573 import os
574 import shutil
575+import StringIO
576 import sys
577
578 import configurationhandler
579@@ -211,7 +213,37 @@
580 os.rename(filedest.name, commandsconfig_path)
581 return 0
582
583-
584+help_preferences = _("Edit developers preferences")
585+usage_preferences = _("Usage: quickly preferences")
586+def preferences(project_template, project_dir, command_args, shell_completion=False):
587+ """Configure preferences"""
588+
589+ # We have nothing for this
590+ if shell_completion:
591+ return("")
592+
593+ preferences = templatetools.get_preferences()
594+
595+ #convert preferences into editable contents
596+ fp_current = StringIO.StringIO()
597+ # TODO use a pretty printer
598+ preferences.write(fp_current)
599+ contents = fp_current.getvalue()
600+ fp_current.close()
601+
602+ # ask developer to edit the contents
603+ newcontents = templatetools.read_input(contents)
604+
605+ # convert the contents back into a ConfigParser object
606+ newIO = StringIO.StringIO(newcontents)
607+ new_preferences = ConfigParser.SafeConfigParser()
608+ # an exception here reject bad edits
609+ new_preferences.readfp(newIO)
610+
611+ templatetools.set_preferences(new_preferences)
612+
613+
614+ return 0
615
616 # here, special builtin commands properties (if nothing specified, commands can be launched inside and outside projects)
617 launched_inside_project_only = []
618
619=== modified file 'quickly/templatetools.py'
620--- quickly/templatetools.py 2010-12-20 20:33:12 +0000
621+++ quickly/templatetools.py 2011-05-24 23:28:25 +0000
622@@ -15,15 +15,20 @@
623 #You should have received a copy of the GNU General Public License along
624 #with this program. If not, see <http://www.gnu.org/licenses/>.
625
626+import ConfigParser
627 import os
628 import stat
629 import string
630+import subprocess
631 import sys
632 import re
633+import tempfile
634
635 import gettext
636 from gettext import gettext as _
637
638+import glib
639+
640 import configurationhandler
641 import tools
642 import quicklyconfig
643@@ -256,3 +261,116 @@
644 print_command_candidates(template)
645 sys.exit(4)
646
647+def get_preferences():
648+ 'parse ~/.config/quickly/preferences for configuration'
649+
650+ # fill in defaults
651+ defaults = {}
652+ defaults['plugin_path'] = '/usr/share/pyshared/quickly/widgets'
653+ defaults['#plugin_path'] = 'files which can be used with quickly add command'
654+
655+ ide = get_quickly_editors()
656+ defaults['ide'] = get_quickly_editors()
657+ defaults['#ide'] = 'editor defined in environment'
658+
659+ preferences = ConfigParser.RawConfigParser(defaults)
660+
661+ # ensure there is a section for each template
662+ template_names = commands.get_all_templates()
663+ for template_name in template_names:
664+ preferences.add_section(template_name)
665+
666+ config_dir = os.path.join(glib.get_user_config_dir(), 'quickly')
667+ config_file = os.path.join(config_dir, 'preferences')
668+ preferences.read(config_file)
669+
670+ return preferences
671+
672+def set_preferences(new_preferences):
673+ 'write ~/.config/quickly/preferences'
674+
675+ config_dir = os.path.join(glib.get_user_config_dir(), 'quickly')
676+ config_file = os.path.join(config_dir, 'preferences')
677+
678+ # ensure config_dir exists
679+ if not os.path.isdir(config_dir):
680+ os.makedirs(config_dir)
681+
682+ # write the preferences file
683+ with open(config_file, 'w') as fp:
684+ new_preferences.write(fp)
685+
686+def get_quickly_editors():
687+ '''Return prefered editor for any template'''
688+
689+ default_editor = os.environ.get("QUICKLY_EDITOR")
690+ if not default_editor:
691+ default_editor = os.environ.get("EDITOR")
692+ if not default_editor:
693+ default_editor = os.environ.get("SELECTED_EDITOR")
694+ if default_editor:
695+ editor = default_editor
696+ elif is_X_display():
697+ editor = "gedit"
698+ else:
699+ editor = "nano"
700+ return editor
701+
702+def read_input(start=''):
703+ depfile_name = tempfile.mkstemp()[1]
704+ open(depfile_name,'w').write(start)
705+
706+ # Run the editor with a new tmpdir. This is because gedit uses tmpdir
707+ # to find other instances of gedit, and we don't want that. If we allowed
708+ # that, gedit would return immediately and open a new tab in the other
709+ # gedit. This makes it difficult to tell when user is done editing (how
710+ # to detect that vs nano opening and closing without the user saving it?).
711+ editor = get_quickly_editors()
712+ subenv = dict(os.environ)
713+ subenv['TMPDIR'] = tempfile.mkdtemp()
714+ subprocess.call([editor, depfile_name], stdout=subprocess.PIPE, env=subenv)
715+ os.rmdir(subenv['TMPDIR'])
716+
717+ # Grab file contents
718+ rv = file(depfile_name, 'r').read().strip()
719+ os.remove(depfile_name)
720+
721+ return rv
722+
723+def get_ide(template):
724+ '''Return prefered editor for specified template'''
725+ preferences = get_preferences()
726+
727+ if preferences.has_option(template, 'ide'):
728+ return preferences.get(template, 'ide')
729+ else:
730+ return get_quickly_editors()
731+
732+def option(template, option):
733+ '''Return prefered option for specified template'''
734+ preferences = get_preferences()
735+ return preferences.get(template, option)
736+
737+def file_from_template(template_dir, template_file, target_dir, substitutions=[], rename = True):
738+
739+ if not os.path.isfile(os.path.join(template_dir, template_file)):
740+ return
741+ target_file = os.path.basename(template_file) # to get only file name (template_file can be internal/file)
742+ if rename:
743+ for s in substitutions:
744+ pattern, sub = s
745+ target_file = target_file.replace(pattern,sub)
746+
747+ fin = open(os.path.join(template_dir, template_file),'r')
748+ file_contents = fin.read()
749+ for s in substitutions:
750+ pattern, sub = s
751+ file_contents = file_contents.replace(pattern,sub)
752+
753+ target_path = os.path.join(target_dir, target_file)
754+ if os.path.exists(target_path):
755+ print _("Failed to add file to project\n cannot add: %s - this file already exists." % target_path)
756+ sys.exit(4)
757+
758+ set_file_contents(target_path, file_contents)
759+ fin.close()

Subscribers

People subscribed via source and target branches