Merge lp:~edgar-b-dsouza/acire/snippet_dependency_res_2 into lp:acire

Proposed by Ed S
Status: Needs review
Proposed branch: lp:~edgar-b-dsouza/acire/snippet_dependency_res_2
Merge into: lp:acire
Diff against target: 873 lines (+812/-2)
6 files modified
acire/README.dep_checker.txt (+123/-0)
acire/depchecker.py (+179/-0)
acire/distropkgutils.py (+243/-0)
acire/install_packages.py (+208/-0)
acire/utils.py (+47/-0)
bin/acire (+12/-2)
To merge this branch: bzr merge lp:~edgar-b-dsouza/acire/snippet_dependency_res_2
Reviewer Review Type Date Requested Status
Jono Bacon Needs Fixing
Review via email: mp+24813@code.launchpad.net

Description of the change

Merged in snippet dependency checker against trunk rev 61.

The (newly added) README.dep_checker.txt file contains lots of info about the added files and how it hangs together.

I have tested earlier on Karmic and now on Lucid, with a Clutter script, and it works. Doesn't mean it's bug-free, of course :-) And from the performance viewpoint, I'd hope that contributors could change the check to a regex-based one, which ought to be faster.

Have incorporated your points from https://code.launchpad.net/~edgar-b-dsouza/acire/snippet_dependency_res_1/+merge/21924 as regards:

- Firefox-style yellow bar showing atop the GTKSourceView - in fact, the README contains your exact use case, copied from that merge proposal :-) (NB - I have been driven to almost leaving claw marks on the walls by the GtkLabel's wrapping behavior on Karmic and Lucid... every time I think I got it fixed, it springs out in a different way :-/ Somebody who can make that look decent, PLEASE fix the appearance).

- Keeping code out of bin/acire as much as possible - right, have done that, except for the few lines absolutely required to hook it up.

- Mechanism for hackers on other distros to add distro-specific package-handling code (of course, only tested on Ubuntu, may have bugs on other distros, needs to be tried out).

Looking forward to review - hope this one can be accepted to the trunk.

Thanks
Ed.

To post a comment you must log in.
Revision history for this message
Jono Bacon (jonobacon) wrote :

Sorry for the delay, Ed! I just tested on Maverick and this doesn't work when I tested a snippet with Zeitgeist.

Revision history for this message
Jono Bacon (jonobacon) :
review: Needs Fixing
Revision history for this message
Ed S (edgar-b-dsouza) wrote :

Hi Jono,
I tried installing Maverick on an old laptop and ran into problems. Since I'm happily (for the most part) using Lucid on my main laptop, I don't want to put Maverick on that. I started installing into a VM to check, but got sidetracked by other stuff.

I hope to get around to debugging this soon. I think the error is probably in (my use of) the modulefinder module; if so, then I'm at a loss as to what to do, other than go the regex way :-( and I find that a bit too hard; could sure use help with that.

Did you try it with any other snippets that tried to import an unavailable module? Did the code work at least once on your system?

And when you tried it on the Zeitgeist snippet, were any messages printed to stdout (presuming you run Acire from a terminal)? Could you please share those, if any?

Thanks,
Ed.

Unmerged revisions

62. By Ed S

Merged in snippet dependency checker against rev 61

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'acire/README.dep_checker.txt'
--- acire/README.dep_checker.txt 1970-01-01 00:00:00 +0000
+++ acire/README.dep_checker.txt 2010-05-06 10:56:27 +0000
@@ -0,0 +1,123 @@
1README for the Acire Snippet Dependency Checker feature.
2=========================================================
3
4v. 1 - 03 Apr 2010 - Edgar D'Souza <edgar.b.dsouza@gmail.com>
5
6
7Original Problem
8================
9When a code snippet tried to import a module that was missing on the system, an
10ImportError exception was printed to stdout. Users running Acire full-screen
11(or from an Applications menu entry) didn't even see that. It just failed.
12
13Dependency Checker Goal
14=======================
15Check the snippet for missing modules on load of the snippet into Acire's
16GTKSourceview. Prompt the user about the missing dependencies and offer to
17install the missing module(s), if candidate package(s) can be found (in
18repositories already set up on user's system).
19
20Additional Requirements/Goals
21=============================
221. Ensure that code used to interact with the package-management system is
23 NOT distribution-specific to Ubuntu, or can be extended for other distros.
24
252. Have a privilege-elevation mechanism for installation of packages.
26 Some distros differ in how they achieve superuser privileges; this should
27 also be extendable (add a distro-specific function wherever required).
28
293a. Try to make the package installation as GUI-centric as possible.
30 From a merge request discussion with project founder Jono Bacon, this is
31 what he wrote:
32 ------------------------------------
33 my recommendation would be the following use case:
34
35 1. User loads a snippet that does not have a module installed.
36 2. Above the source view a little bar appears (like the plugin missing bar
37 in Firefox) where it says what module(s) are missing and a button called
38 'Install'.
39 3. User clicks the 'Install' button, a dialog box pops up to confirm what
40 will be installed, the user clicks the 'OK' button, is asked for password
41 and then a dialog displays progress of the installation.
42 4. The bar disappears from the snippet.
43
44 I would prefer that the code for this feature does not clutter up bin/acire
45 if possible. Probably best is that the logic lives in a file called
46 moduleinstaller.py and there is a separate .py file with the dialog box.
47 ------------------------------------
483b. Some distros may have problems with superuser-priv processes connecting to
49 the X server for the ordinary user account. The privilege-elevation
50 mechanism is expected to take care of this, or extra code could be added.
51
52First-cut implementation specifics
53==================================
54New files added to Acire by this implementation:
55 depchecker.py
56 distropkgutils.py
57 install_packages.py
58 utils.py
59 README.dep_checker.txt (this file)
60
61The role of each Python file is explained below.
62
63The checking code is invoked from bin/acire (the main executable), in the
64snippet_selected() function, via the line beginning with:
65 "check_results = depchecker.check_script"
66
67The depchecker.py module contains generic (distro-independent, AFAIK) functions
68that use the built-in Python modulefinder module to see if any import
69statements in the snippet use modules that are not installed on the system.
70
71depchecker.py imports distropkgutils.py, creates an instance of the
72distropkgutils.DistroPkgUtils class, and calls said class's methods, to
73accomplish distro-specific functionality. It then builds a GTKEventBox (to show
74a yellow background color), and its contained controls (HBox, which in turn
75contains a GTKLabel and GTKButton). Code in this file customizes the message
76that is displayed, and, if there aren't (enough) installation candidates, the
77caption of the GTKButton. If there are enough packages to install to supply the
78missing modules, then the button caption remains "Install", and the label's
79message lists the packages that will be installed. If unable to find packages
80to install, then the label message is changed to reflect this, and the GTKButton
81caption is changed to "More Info" - clicking this will take the user to a wiki
82page (the URL is at the beginning of depchecker.py).
83
84depchecker.py has a remove_eventbox() function, which is called internally,
85from the handler for the GTKButton, and also from bin/acire, in the
86snippet_selected() function, to hide & destroy the eventbox if it still exists.
87This gets rid of the eventbox both when user clicks the Install button, or if
88user ignores it and clicks another snippet in the treeview.
89
90Class DistroPkgUtils in distropkgutils.py:
91Exposes generically-named methods (see 'Internals' below) to calling code:
92- get_pkg_list(): Returns list of UNinstalled python library packages
93- install_pkgs(pkglist): installs the given packages, as described below.
94
95Class & Module Internals -- distropkgutils.py:
96- In __init__(), class checks which distribution it is running under, and looks
97 for an appropriate distro-specific package-listing function (in the same
98 module) that it exposes as get_pkg_list() to calling code. This is because
99 retrieving a list of uninstalled packages does not need superuser privs.
100 IF an __get_pkg_list function is not found for the current distro, the
101 default implementation of the method simply returns an empty list, warning
102 calling code that something is amiss (if it wants to handle this).
103- The install_pkgs() method accepts a list of packages as a parameter, and
104 calls a private function, _as_superuser(), to launch install_packages.py
105 as a subprocess with superuser privs. The list of packages to install is
106 passed on the command-line as arguments.
107- The _as_superuser() function has a default implementation using gksu,
108 in this same class. However, __init__() checks for a distro-specific
109 implementation of this function; if found, it overwrites the default
110 implementation with the found one. This lets you add privilege
111 escalation code for different distros (which don't use gksu/sudo).
112
113install_packages.py -- contains distro-specific package installation functions.
114As in distropkgutils.py, this script too checks for distro via platform.dist()
115and attempts to retrieve a matching install function from itself. If a callable
116object is obtained, it calls that function, passing the command-line arguments.
117This file expects to be launched with administrative/superuser privileges
118needed to install packages, and does not contain any code for privilege
119escalation.
120
121utils.py -- contains a few functions that are used from multiple files,
122and/or are not exclusively related to the package-management code (i.e. could
123be re-used elsewhere).
0\ No newline at end of file124\ No newline at end of file
1125
=== added file 'acire/depchecker.py'
--- acire/depchecker.py 1970-01-01 00:00:00 +0000
+++ acire/depchecker.py 2010-05-06 10:56:27 +0000
@@ -0,0 +1,179 @@
1#! /usr/bin/env python
2#coding=utf-8
3### BEGIN LICENSE
4# Copyright (C) 2010 Edgar D'Souza <edgar.b.dsouza@gmail.com>
5#This program is free software: you can redistribute it and/or modify it
6#under the terms of the GNU General Public License version 3, as published
7#by the Free Software Foundation.
8#
9#This program is distributed in the hope that it will be useful, but
10#WITHOUT ANY WARRANTY; without even the implied warranties of
11#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12#PURPOSE. See the GNU General Public License for more details.
13#
14#You should have received a copy of the GNU General Public License along
15#with this program. If not, see <http://www.gnu.org/licenses/>.
16### END LICENSE
17
18import modulefinder
19from acire import distropkgutils as dpu
20import webbrowser
21import pygtk
22pygtk.require('2.0')
23import gtk
24
25infoURL = "https://wiki.ubuntu.com/PythonSnippets_Dependencies"
26
27#Grab a list of packages immediately upon import of this module.
28dp_utils = dpu.DistroPkgUtils()
29python_pkgs = dp_utils.get_pkg_list()
30#Other global vars hold data while waiting for user response through UI
31candidates = []
32event_box = None
33
34def check_script(filename, container_vbox):
35 """Entry point for checking a script, to be called when snippet is
36 loaded from file into Acire's GTKSourceView.
37 filename - path+filename to the Python script to be checked.
38 container_vbox - the right-hand pane vbox containing the editor viewport
39 and other controls (more controls are built and packed in below).
40 """
41 global python_pkgs, candidates, event_box
42
43 missing_in_main = []
44 candidate_pkgs = []
45 candidates = candidate_pkgs
46
47 modfinder = modulefinder.ModuleFinder()
48 modfinder.run_script(filename)
49 missing, maybe = modfinder.any_missing_maybe()
50 #Due to bad docs, next 3 lines copied from modulefinder.report() and modded
51 if missing:
52 for name in missing:
53 mods = modfinder.badmodules[name].keys()
54 if "__main__" in mods:
55 missing_in_main.append(name)
56
57 #Python's intelligent iteration will just skip the loop(s) below if:
58 #a) There are no modulenames in missing_in_main, OR
59 #b) There are no python_pkgs (pkg-mgt function for curr distro n/avble)
60 for mod in missing_in_main:
61 for pkg in python_pkgs:
62 if mod in pkg:
63 candidate_pkgs.append(pkg)
64 #print "Candidate package for module %s: %s" % (mod, pkg)
65
66 #Build the GUI if there are missing modulenames - even if there
67 #aren't any, or sufficient, candidates for installation - because if
68 #not, it will look like the dependency was not detected.
69 if len(missing_in_main) > 0:
70 evbox, alert_label, resolve_button, builder = build_ui()
71 event_box = evbox #Put in global var to use in remove_eventbox()
72 msg = alert_label.get_text()
73 #If num-missing-modules == num-installation-candidates, then we
74 #probably have a solution and can propose installation.
75 if len(missing_in_main) == len(candidate_pkgs):
76 #Store the candidate packages list globally, for use in the
77 #resolve_button handler "resolve_deps()".
78 candidates = candidate_pkgs
79 #Replace placeholder in label text with package list.
80 msg = msg % (", ".join(candidate_pkgs))
81 else:
82 #Incomplete or no solution: offer to take user to wiki page.
83 msg = "This snippet uses modules that aren't installed on your"
84 msg += "system, but we cannot find packages to install.\n"
85 msg += "Click the More Info button to visit a wiki page."
86 resolve_button.set_text(" More _Info ")
87 alert_label.set_text(msg)
88 resolve_button.connect("clicked", resolve_deps)
89 container_vbox.pack_start(evbox, False, False, 3)
90 container_vbox.reorder_child(evbox, 0)
91 evbox.show_all()
92
93def resolve_deps(widget, data=None):
94 """Click event handler for resolve_button. """
95 global python_pkgs, candidates, dp_utils, event_box, infoURL
96
97 #If there are installation candidates, check_script() found that number of
98 #candidates matched number of missing modules... install the list of pkgs.
99 if len(candidates) > 0:
100 dp_utils.install_pkgs(candidates)
101 #Refresh the list of uninstalled Python packages.
102 python_pkgs = dp_utils.get_pkg_list()
103 else:
104 #check_script couldn't find a 'complete solution': either the packages
105 #available < num-missing-modules, or there were zero candidate pkgs.
106 webbrowser.open_new_tab(infoURL)
107 remove_eventbox()
108
109def remove_eventbox():
110 global event_box
111 if event_box is not None:
112 event_box.hide()
113 event_box.destroy()
114 event_box = None
115
116def build_ui():
117 ui = '''<interface>
118 <object class="GtkEventBox" id="alert_eventbox">
119 <property name="visible">True</property>
120 <child>
121 <object class="GtkHBox" id="alert_hbox">
122 <child>
123 <object class="GtkLabel" id="alert_label">
124 <property name="visible">True</property>
125 <property name="wrap">True</property>
126 <property name="xpad">5</property>
127 <property name="ypad">5</property>
128 <property name="label">This snippet uses modules that are not installed on your system. Click the Install button to install these packages: %s</property>
129 <property name="track_visited_links">False</property>
130 <attributes>
131 <attribute name="weight" value="semibold"/>
132 <attribute name="gravity" value="north"/>
133 <attribute name="gravity-hint" value="natural"/>
134 <attribute name="style" value="normal"/>
135 <attribute name="gravity" value="east"/>
136 </attributes>
137 </object>
138 <packing>
139 <property name="fill">True</property>
140 <property name="position">0</property>
141 </packing>
142 </child>
143 <child>
144 <object class="GtkButton" id="resolve_button">
145 <property name="label" translatable="yes"> _Install </property>
146 <property name="visible">True</property>
147 <property name="width_request">100</property>
148 <property name="can_focus">True</property>
149 <property name="receives_default">True</property>
150 <property name="use_underline">True</property>
151 <signal name="clicked" handler="resolve_deps"/>
152 </object>
153 <packing>
154 <property name="expand">False</property>
155 <property name="fill">False</property>
156 <property name="padding">3</property>
157 <property name="pack_type">end</property>
158 <property name="position">1</property>
159 </packing>
160 </child>
161 </object>
162 </child>
163 </object>
164 </interface>'''
165 # Create a GTKBuilder instance
166 builder = gtk.Builder()
167 # Add a UI description
168 builder.add_from_string(ui)
169 evbox = builder.get_object("alert_eventbox")
170 evbox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffff00"))
171 alert_label = builder.get_object("alert_label")
172 resolve_button = builder.get_object("resolve_button")
173 return evbox, alert_label, resolve_button, builder
174
175
176if __name__ == "__main__":
177 print "Import this as a module and run utils.check_script('filename.py')"
178 print "to examine the script for dependency modules."
179 print "See check_script() docstring for returned dict contents."
0180
=== added file 'acire/distropkgutils.py'
--- acire/distropkgutils.py 1970-01-01 00:00:00 +0000
+++ acire/distropkgutils.py 2010-05-06 10:56:27 +0000
@@ -0,0 +1,243 @@
1#! /usr/bin/env python
2#coding=utf-8
3### BEGIN LICENSE
4# Copyright (C) 2010 Edgar D'Souza <edgar.b.dsouza@gmail.com> (initial version)
5#This program is free software: you can redistribute it and/or modify it
6#under the terms of the GNU General Public License version 3, as published
7#by the Free Software Foundation.
8#
9#This program is distributed in the hope that it will be useful, but
10#WITHOUT ANY WARRANTY; without even the implied warranties of
11#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12#PURPOSE. See the GNU General Public License for more details.
13#
14#You should have received a copy of the GNU General Public License along
15#with this program. If not, see <http://www.gnu.org/licenses/>.
16### END LICENSE
17
18###
19###
20###
21###
22###
23### PLEASE READ README.dep_checker.txt before hacking - thanks! :-)
24###
25###
26###
27###
28###
29###
30
31import subprocess
32import sys
33import os
34
35try:
36 from acire import utils
37except:
38 #Required when doing singleton-testing of this file (exec it alone)
39 sys.path.insert(0, os.getcwd())
40 import utils
41
42
43class DistroPkgUtils():
44 """Class to abstract distro-specific libraries/commands so that calling
45 code can call generically-named methods of this class without bothering
46 about which distro is being used.
47 """
48 def __init__(self, dummydistname_testingonly=None):
49 #Store distro name in lower case (or a dummy name, for testing)
50 if dummydistname_testingonly is None:
51 self.distname_lower = utils.distro_name()
52 else:
53 self.distname_lower = dummydistname_testingonly
54 #print "Distro name: ", self.distname_lower
55
56 #Pick up distro-specific functions from this module
57 thismodule = sys.modules[__name__]
58 getter_name = "__get_pkg_list_%s" % self.distname_lower
59 as_superuser_name = "__as_superuser_%s" % self.distname_lower
60 #print "Func names sought: ", getter_name, as_superuser_name
61 try:
62 getter_func = getattr(thismodule, getter_name)
63 #print "getter_func: ", getter_func
64 if callable(getter_func):
65 #Override the default empty-list member of this class with
66 #the function containing the actual code.
67 self.get_pkg_list = getter_func
68
69 #the _as_superuser function has a default implementation in this
70 #class, but can be overridden, so:
71 if hasattr(thismodule, as_superuser_name):
72 as_superuser_func = getattr(thismodule, as_superuser_name)
73 #print "as_superuser_func: ", as_superuser_func
74 if callable(as_superuser_func):
75 self.__as_superuser = as_superuser_func
76 except Exception, e:
77 print "Exception while trying to access functions for %s in %s" % (self.distname_lower, __name__)
78 print "Exception was: %s" % str(e)
79
80 def get_pkg_list():
81 """Default implementation of this function returns an empty list of
82 packages, if there is no distro-specific function found."""
83 return []
84
85 def __as_superuser(self, pkglist):
86 """Shells to a gksu invocation of install_packages.py, waiting till
87 it's done. To override, create a _as_superuser_DISTRONAME() below;
88 __init__() will find it and replace this with your specific
89 implementation."""
90 #Spawn a subprocess with gksu, to run the install_packages.py script.
91 try:
92 cwd = os.path.dirname(os.path.abspath(__file__))
93 print "cwd: ", cwd
94 cc_args = ["/usr/bin/gksu", "--", "python",
95 "install_packages.py", "-d", "-i"]
96 for item in pkglist:
97 cc_args.append('%s' % item)
98 print "cc_args: ", cc_args
99 #check_call waits for command to complete before returning.
100 subprocess.check_call(cc_args, cwd=cwd)
101 except subprocess.CalledProcessError, cpe:
102 print "CalledProcessError: %s" % repr(cpe)
103 raise
104
105 def install_pkgs(self, pkglist):
106 """Method accepts the list of packages to be installed, then calls
107 _as_superuser to run install_packages.py with elevated privileges.
108 That script does its own distro detection and calls the appropriate
109 function with the package list passed on the command line."""
110 self.__as_superuser(pkglist)
111
112#------------------------------------------------------------------------------
113###Package-management listing functions for different distros.
114###Some distros may have an optional privilege-elevation function too.
115### Please read README.dep_checker.txt for explanation.
116
117###Unimplemented function stubs call the "utils.not_implemented()" function
118### to display a message. Contributions welcome for your favorite distro!
119###Distros taken from _supported_dists in platform module, have not added stubs
120### for Mint, PCLinuxOS, Sabayon, Puppy, Arch and many others, since am not
121### sure what platform.dist() returns on each.
122###
123###Function naming convention:
124### NB: DISTRONAME => the lower-case version of the name returned
125### by platform.linux_distribution()[0]
126### - __get_pkg_list_DISTRONAME()
127### Func to return list of uninstalled python library packages.
128### Please adjust the filtering code for the package-naming conventions
129### of the distro for which you're writing the function.
130### Does not have GUI or other display of this operation.
131### - (Optional) __as_superuser_DISTRONAME()
132### Optional override of the default privilege-escalation mechanism
133### implemented in the class above.
134
135def __get_pkg_list_ubuntu():
136 """Run subprocess with aptitude search to fetch a list of package names
137 with regex 'python-*'; filter it to keep those which are not installed.
138 Returns: list of uninstalled python packages. """
139
140 cmd = "/usr/bin/aptitude search '^python-[a-z]*$' --disable-columns -F '%p\$%v'"
141 proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
142 pkg_list = proc.communicate()[0]
143 #Convert to a list of packages, filtering to keep those where the Version
144 #is "<none>" (i.e. not installed)
145 python_uninst_pkgs = []
146 for pkg in pkg_list.split("\n"):
147 if len(pkg.strip()) > 0:
148 parts = pkg.split("$")
149 #print parts
150 if parts[1].strip() == "<none>":
151 python_uninst_pkgs.append(parts[0])
152 return python_uninst_pkgs
153
154#------------------------------------------------------------------------------
155
156def __get_pkg_list_debian():
157 """Returns a list of Python library packages that are not installed yet."""
158 return __get_pkg_list_ubuntu() #Redirect to Ubuntu code - same family
159
160#------------------------------------------------------------------------------
161
162def __get_pkg_list_redhat():
163 """Returns a list of Python library packages that are not installed yet."""
164 utils.not_implemented(utils.funcname())
165 return []
166
167#------------------------------------------------------------------------------
168
169def __get_pkg_list_centos():
170 """Returns a list of Python library packages that are not installed yet."""
171 return __get_pkg_list_redhat() #Redirect to RH code - same family
172
173#------------------------------------------------------------------------------
174
175def __get_pkg_list_fedora():
176 """Returns a list of Python library packages that are not installed yet."""
177 return __get_pkg_list_redhat() #Redirect to RH code - same family
178
179#------------------------------------------------------------------------------
180
181def __get_pkg_list_mandriva():
182 """Returns a list of Python library packages that are not installed yet."""
183 utils.not_implemented(utils.funcname())
184 return []
185
186#------------------------------------------------------------------------------
187
188def __get_pkg_list_suse():
189 """Returns a list of Python library packages that are not installed yet."""
190 utils.not_implemented(utils.funcname())
191 return []
192
193#------------------------------------------------------------------------------
194
195def __get_pkg_list_slackware():
196 """Returns a list of Python library packages that are not installed yet."""
197 utils.not_implemented(utils.funcname())
198 return []
199
200#------------------------------------------------------------------------------
201
202def __get_pkg_list_gentoo():
203 """Returns a list of Python library packages that are not installed yet."""
204 utils.not_implemented(utils.funcname())
205 return []
206
207#------------------------------------------------------------------------------
208
209def __get_pkg_list_yellowdog():
210 """Returns a list of Python library packages that are not installed yet."""
211 utils.not_implemented(utils.funcname())
212 return []
213
214#------------------------------------------------------------------------------
215
216def __get_pkg_list_unitedlinux():
217 """Returns a list of Python library packages that are not installed yet."""
218 utils.not_implemented(utils.funcname())
219 return []
220
221#------------------------------------------------------------------------------
222
223def __get_pkg_list_turbolinux():
224 """Returns a list of Python library packages that are not installed yet."""
225 utils.not_implemented(utils.funcname())
226 return []
227
228#------------------------------------------------------------------------------
229
230def __get_pkg_list_rocks():
231 """Returns a list of Python library packages that are not installed yet."""
232 utils.not_implemented(utils.funcname())
233 return []
234
235#------------------------------------------------------------------------------
236
237
238### Module self-test (limited)
239if __name__ == "__main__":
240 for distro in ["fedora", "rocks", "turbolinux", "debian"]:
241 dpu = DistroPkgUtils(distro)
242 if len(dpu.get_pkg_list()) > 0:
243 dpu.install_pkgs(["python-clutter"])
0\ No newline at end of file244\ No newline at end of file
1245
=== added file 'acire/install_packages.py'
--- acire/install_packages.py 1970-01-01 00:00:00 +0000
+++ acire/install_packages.py 2010-05-06 10:56:27 +0000
@@ -0,0 +1,208 @@
1#! /usr/bin/python
2#coding=utf-8
3### BEGIN LICENSE
4# Copyright (C) 2010 Edgar D'Souza <edgar.b.dsouza@gmail.com>
5#This program is free software: you can redistribute it and/or modify it
6#under the terms of the GNU General Public License version 3, as published
7#by the Free Software Foundation.
8#
9#This program is distributed in the hope that it will be useful, but
10#WITHOUT ANY WARRANTY; without even the implied warranties of
11#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12#PURPOSE. See the GNU General Public License for more details.
13#
14#You should have received a copy of the GNU General Public License along
15#with this program. If not, see <http://www.gnu.org/licenses/>.
16### END LICENSE
17
18import pygtk
19pygtk.require("2.0")
20import gtk
21import subprocess
22import os
23import sys
24import time
25
26# Check if we are working in the source tree or from the installed
27# package and mangle the python path accordingly
28if os.path.dirname(sys.argv[0]) != ".":
29 if sys.argv[0][0] == "/":
30 fullPath = os.path.dirname(sys.argv[0])
31 else:
32 fullPath = os.getcwd() + "/" + os.path.dirname(sys.argv[0])
33else:
34 fullPath = os.getcwd()
35sys.path.insert(0, os.path.dirname(fullPath))
36import utils
37
38#Helper function - writes debug messages to a log file.
39def log(msg):
40 filename = '/tmp/install_packages.log'
41 dumpstr = "%s\n" % msg
42 write_mode = 'a'
43 tmpfile = open(filename, write_mode, 0)
44 tmpfile.write(dumpstr)
45 tmpfile.close()
46
47
48def __install_pkgs_ubuntu(pkglist):
49 """Install the packages passed as the pkglist parameter.
50 python-apt must be installed (must be a dependency of the Acire package).
51 """
52 try:
53 import apt.progress.gtk2
54
55 win = gtk.Window()
56 win.connect("destroy", gtk.main_quit)
57 win.set_size_request(450, 440)
58 win.set_position(gtk.WIN_POS_CENTER_ALWAYS)
59 win.set_title("Acire Module Installation")
60
61 vbox = gtk.VBox(False, 3)
62 vbox.set_border_width(10)
63
64 progress = apt.progress.gtk2.GtkAptProgress()
65 vbox.pack_start(progress)
66
67 hbox = gtk.HButtonBox()
68 hbox.set_layout(gtk.BUTTONBOX_END)
69 close_button = gtk.Button("Close", gtk.STOCK_CLOSE)
70 close_button.connect("clicked", gtk.main_quit)
71 hbox.add(close_button)
72
73 vbox.pack_end(hbox, True, True, 0)
74
75 win.add(vbox)
76
77 close_button.show()
78 progress.show()
79 vbox.show()
80 win.show()
81 cache = apt.cache.Cache(progress.open)
82 for pkg in pkglist:
83 cache[pkg].markInstall()
84 progress.show_terminal(expanded=True)
85 cache.commit(progress.fetch, progress.install)
86 hbox.show()
87 gtk.main()
88 time.sleep(1)
89 except Exception, e:
90 log("%s: Exception: %s" % (utils.funcname(), repr(e)))
91 time.sleep(1)
92
93#------------------------------------------------------------------------------
94
95def __install_pkgs_debian(pkglist):
96 """Installs the packages passed as the pkglist parameter."""
97 __install_pkgs_ubuntu(pkglist) #Redirect to Ubuntu code - same family
98
99#------------------------------------------------------------------------------
100
101def __install_pkgs_redhat(pkglist):
102 """Installs the packages passed as the pkglist parameter."""
103 utils.not_implemented(utils.funcname(), True)
104
105#------------------------------------------------------------------------------
106
107def __install_pkgs_centos(pkglist):
108 """Installs the packages passed as the pkglist parameter."""
109 __install_pkgs_redhat(pkglist) #Redirect to RH code - same family
110
111#------------------------------------------------------------------------------
112
113def __install_pkgs_fedora(pkglist):
114 """Installs the packages passed as the pkglist parameter."""
115 __install_pkgs_redhat(pkglist) #Redirect to RH code - same family
116
117#------------------------------------------------------------------------------
118
119def __install_pkgs_mandriva(pkglist):
120 """Installs the packages passed as the pkglist parameter."""
121 utils.not_implemented(utils.funcname(), True)
122
123#------------------------------------------------------------------------------
124
125def __install_pkgs_suse(pkglist):
126 """Installs the packages passed as the pkglist parameter."""
127 utils.not_implemented(utils.funcname(), True)
128
129#------------------------------------------------------------------------------
130
131def __install_pkgs_slackware(pkglist):
132 """Installs the packages passed as the pkglist parameter."""
133 utils.not_implemented(utils.funcname(), True)
134
135#------------------------------------------------------------------------------
136
137def __install_pkgs_gentoo(pkglist):
138 """Installs the packages passed as the pkglist parameter."""
139 utils.not_implemented(utils.funcname(), True)
140
141#------------------------------------------------------------------------------
142
143def __install_pkgs_yellowdog(pkglist):
144 """Installs the packages passed as the pkglist parameter."""
145 utils.not_implemented(utils.funcname(), True)
146
147#------------------------------------------------------------------------------
148
149def __install_pkgs_unitedlinux(pkglist):
150 """Installs the packages passed as the pkglist parameter."""
151 utils.not_implemented(utils.funcname(), True)
152
153#------------------------------------------------------------------------------
154
155def __install_pkgs_turbolinux(pkglist):
156 """Installs the packages passed as the pkglist parameter."""
157 utils.not_implemented(utils.funcname(), True)
158
159#------------------------------------------------------------------------------
160
161def __install_pkgs_rocks(pkglist):
162 """Installs the packages passed as the pkglist parameter."""
163 utils.not_implemented(utils.funcname(), True)
164
165#------------------------------------------------------------------------------
166#------------------------------------------------------------------------------
167
168
169import sys
170import optparse
171
172if __name__ == "__main__":
173 parser = optparse.OptionParser()
174 parser.add_option("-i","--install",action="store_true",dest="instaction")
175 parser.add_option("-d","--debug",action="store",type="string",dest="debug")
176
177 (options, args) = parser.parse_args()
178
179 log("Starting run at: %s" % time.asctime())
180
181 # Make sure we have our mandatory argument (at least one package)
182 if len(args) == 0:
183 print "This file is not for general usage, but meant for use from"
184 print "Acire's distropkgutils library. It should be invoked with "
185 print "a list of packages to install."
186 sys.exit(1)
187
188 log("Args: ")
189 log(str(args))
190
191 #Choose distro-specific install function from this module
192 distname_lower = utils.distro_name()
193 log("Detected distro %s" % distname_lower)
194
195 thismodule = sys.modules[__name__]
196 inst_func_name = "__install_pkgs_%s" % distname_lower
197 try:
198 inst_func = getattr(thismodule, inst_func_name)
199 if callable(inst_func):
200 log("Calling install function: %s" % inst_func.__name__)
201 inst_func(args)
202 time.sleep(0.25)
203 except Exception, e:
204 log("Exception while trying to access install function for %s in %s" % (distname_lower, __name__))
205 log("Exception was: %s" % str(e))
206 time.sleep(0.25)
207 sys.exit(1)
208
0\ No newline at end of file209\ No newline at end of file
1210
=== added file 'acire/utils.py'
--- acire/utils.py 1970-01-01 00:00:00 +0000
+++ acire/utils.py 2010-05-06 10:56:27 +0000
@@ -0,0 +1,47 @@
1#! /usr/bin/env python
2#coding=utf-8
3### BEGIN LICENSE
4# Copyright (C) 2010 Edgar D'Souza <edgar.b.dsouza@gmail.com>
5#This program is free software: you can redistribute it and/or modify it
6#under the terms of the GNU General Public License version 3, as published
7#by the Free Software Foundation.
8#
9#This program is distributed in the hope that it will be useful, but
10#WITHOUT ANY WARRANTY; without even the implied warranties of
11#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12#PURPOSE. See the GNU General Public License for more details.
13#
14#You should have received a copy of the GNU General Public License along
15#with this program. If not, see <http://www.gnu.org/licenses/>.
16### END LICENSE
17
18import pygtk
19pygtk.require("2.0")
20import gtk
21import sys
22import platform
23import string
24
25def not_implemented(function_name_string, show_dialog=False):
26 """Utility function for outputting info message that the (pkg-mgt) function
27 whose name is passed as the sole param is not yet implemented."""
28
29 msg = "%s: Not implemented yet, please contribute!" % function_name_string
30
31 print msg
32
33 if show_dialog:
34 md = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT,
35 gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, msg)
36 md.run()
37 md.destroy()
38
39def funcname():
40 """Utility function, returns the name of the function
41 that calls this one."""
42 return sys._getframe(1).f_code.co_name
43
44def distro_name():
45 p = platform.linux_distribution()
46 return string.lower(p[0])
47
0\ No newline at end of file48\ No newline at end of file
149
=== modified file 'bin/acire'
--- bin/acire 2010-03-26 19:41:43 +0000
+++ bin/acire 2010-05-06 10:56:27 +0000
@@ -48,6 +48,7 @@
4848
49from acire import AboutAcireDialog, PreferencesAcireDialog49from acire import AboutAcireDialog, PreferencesAcireDialog
50from acire.acireconfig import getdatapath50from acire.acireconfig import getdatapath
51from acire import depchecker
5152
52# Set up translations53# Set up translations
53import gettext54import gettext
@@ -103,14 +104,14 @@
103 self.terminal_expander = self.builder.get_object("terminal_expander")104 self.terminal_expander = self.builder.get_object("terminal_expander")
104 self.status_label = self.builder.get_object("status_label")105 self.status_label = self.builder.get_object("status_label")
105 self.docs_box = self.builder.get_object("docs_box")106 self.docs_box = self.builder.get_object("docs_box")
107 self.right_pane_vbox = self.builder.get_object("vbox4")
106 108
107 # set up source view109 # set up source view
108 110
109 self.editor_buffer = gtksourceview2.Buffer()111 self.editor_buffer = gtksourceview2.Buffer()
110 self.editor_view = gtksourceview2.View(self.editor_buffer)112 self.editor_view = gtksourceview2.View(self.editor_buffer)
111 self.editor_view.set_show_line_numbers(True)113 self.editor_view.set_show_line_numbers(True)
112 114
113
114 # read system's monospace font, fallback to 'monospace 10'115 # read system's monospace font, fallback to 'monospace 10'
115 self.gconf = gconf.client_get_default()116 self.gconf = gconf.client_get_default()
116 gconf_mono_font = self.gconf.get_string("/desktop/gnome/interface/monospace_font_name")117 gconf_mono_font = self.gconf.get_string("/desktop/gnome/interface/monospace_font_name")
@@ -251,6 +252,15 @@
251 self.location_label.set_text(self.current_filename)252 self.location_label.set_text(self.current_filename)
252 self.description_label.set_text(self.snippetsdata[self.current_filename]["description"])253 self.description_label.set_text(self.snippetsdata[self.current_filename]["description"])
253254
255 ###Snippet modules dependency checker (depchecker) invocation
256 # Remove the eventbox for missing modules - it will be added again if
257 # needed for the snippet that is just loaded.
258 depchecker.remove_eventbox()
259
260 # Check the script for missing modules, alert user.
261 check_results = depchecker.check_script(self.current_filename, self.right_pane_vbox)
262 ###Snippet modules dependency checker (depchecker) invocation -- ENDS
263
254 # update docs264 # update docs
255265
256 ## first delete any existing docs buttons:266 ## first delete any existing docs buttons:

Subscribers

People subscribed via source and target branches

to all changes: