- People:
Initial version of what will become the best installer in the world - ever
Review Request #1696 — Created June 28, 2010 and discarded
Initial version of installer with example json file structure for ubuntu that shows working source, easy_install and apt type installs.
All manual - there might be a slight problem with lucene which needs a patch (one more command in source type install for it).
MA
MA
-
-
Personally I put them in order of lowest level to highest level, so common stuff at the top, and more specialized stuff at the bottom .. old habit .. it also happily turns out to make it look nice line length wise :) import os import sys import shutil import platform import simplejson as json from types import ListType from subprocess import Popen, PIPE But really no-one cares .. it's just whatever you're comfortable with and whatever makes it easy to read later; alphabetical is good too.
-
According to good old guido's python style guide, class is preceded with two blank lines. That also goes for tabs characters, they should all be 4 spaces I reckon: http://www.python.org/dev/peps/pep-0008/
-
'file' is a reserved keyword. I wouldn't use it for variable nor attribute names myself. Also I see that the file is actually a filename so probably I'd call it fileName :)
-
-
No need for the i = 0 nor i = i + 1. Just use enumerate: for i, o in enumerate(options): ... does the same thing
-
-
-
Personally I don't like the redundant use of the valid variable .. it might be OK with some people, but I'd prefer something like: while 1: do stuff if done: break sort of style
-
I'd add a try..except around the 'int' conversion, and only need to convert it once .. maybe something like: try: choice = int(choice) except: continue # Basically the choice is not an int, just ignore it .. probably should print some insult or something :P if choice in range(0, len(options)): break return choice
-
-
-
You can just add lists together, no need for the second loop. Either: options += opt.keys() or: options.extend(opt.keys())
-
This is just another option, I like this style myself, but some may see it as a bit freaky: descr = { 'database': 'Choose database:', 'web_server': 'Choose web server:' }.get(key, 'Not set!')
-
-
-
self._source_install() already loops through self.source_list(), no need to call it once for every item.
-
-
I'd use a try: finally: block here oldDir = os.getcwd() os.mkdir('/tmp/reviewboard_installer') try: ... finally: os.chdir(oldDir) shutil.rmtree('/tmp/reviewboard_installer')
MA
- Change Summary:
-
Removed trailing spaces from json file. Last revision addresses problems found in earlier review round.
- Diff:
-
Revision 3 (+258)
-
-
I'm not exactly sure what the semantics of "an array of dicts of a single element" are here. Is there a particular meaning? If not, I'd like to see it just be one dict: { "mysql" : { ... }, "pgsql" : { ... }, ... }
-
-
-
-
Since you're doing a numeric comparison, it'd be a lot easier to use >= 0 and < len(options). The way you've written this it's generating a list and then checking every element.
-
I wonder if instead of having 3 lists and checking the string for each one, if it might be cleaner to have a dict of method name : list { 'pkgmgr': [], 'easy_install': [], 'source': [] } and then you could just do self.pkgs[method].append(pkg)
-
-
After this, you should probably check p1.returncode to make sure that it returned 0 and not an error.
-
-
-
Can you explicitly pass in the mode as 0700? By default os.mkdir() uses 0777, which is a pretty big security risk when this is (presumably) running as a privileged user.
-
MA
- Change Summary:
-
Took into account a lot of comments from previous reviews and irc talks. Error handling is now much better. Versions stuff and description are only provisional, and will be implemented properly later in the process - we might switch to description being hard-coded later on, but as I designed json files it made sense to put them in there, at least temporarily.
MA
-
-
It'd be nice to have a nice comment here explaining what the function does, perhaps with an example output too..
-
You can get rid of the extra 'i' variable by using enumerate: default_num = -1 for (k, v), i in self.depmap[cat]['options'].items(): opt_str += "[%d] %s: %s\n" % (i, v['name'], v['description']) if k == self.depmap[cat]['default']: default_num = i
-
MA
-
-
In my code I make all top level classes children of object: class File2(object): This makes it a 'new style class' rather than an 'old style class' http://www.python.org/doc/newstyle/
-
Function comments should be in the form of a string. That way autodoc tools like Sphinx pick it up well. And they can compile all of your todos into a single page and cool stuff like that
-
-
dep = self.depmap[pkg] pkgver = dep['default'] pkgdata = dep[pkgver] method = pkgdata['method'] if method == 'pkgmgr': ... # Just less lookups .. nit picking .. sorry If you wanted to be really pythony, you could switch the if statements to: myList = {'pkgmgr': self.pkgmgr_list, 'easy_install', self.easy_list}.get(method, self.source_list) myList.append(pkg) in fact it might be a neat idea to init that dictionary of list names to actual lists in the __init__: self.name2list = {'pkgmgr': self.pkgmgr_list, 'easy_install', self.easy_list} then you could use it where ever with: myList = self.name2list.get(methodName, self.source_list)
-
I probably would move the file reading out to a 'process' or 'read' method .. just a personal preference, and keeps with how most python classes are .. you init a 'reader' object, then you fill with some file..
-
This whole block looks similar to above, I'm sure you could probably merge them into a single reusable func. Possibly a base class or utility class sort of thing
-
-
either: deps = self.depmap[self.version]['dependencies']['requirements'][:] or: deps = [] deps.extend(self.depmap[self.version]['dependencies']['requirements'])
-
deps.extend(self.depmap[self.version]['dependencies']['optional']) or possibly: deps += self.depmap[self.version]['dependencies']['optional']