Xo-get: Difference between revisions
Jump to navigation
Jump to search
Crazy-chris (talk | contribs) (v0.4) |
Crazy-chris (talk | contribs) (0.4.1: install and remove any local .xo file) |
||
Line 1: | Line 1: | ||
XO-Get is a very simple package-installer for the olpc xo-laptop. |
XO-Get is a very simple package-installer for the olpc xo-laptop. |
||
# [http://www.linuxuser.at/xo-get.txt Source] |
|||
* License: GPL |
|||
# License: GPL |
|||
* The repository syncs with http://www.olpcaustria.org/mediawiki/index.php/Xo-get/Repository |
|||
# Repository syncs with http://www.olpcaustria.org/mediawiki/index.php/Xo-get/Repository |
|||
* Installing with ActivityBundle.install() or plain unzipping |
|||
# Installing & Removing of local .xo files, or download over web |
|||
* Removing via ActivityBundle.uninstall() |
|||
# Installing with ActivityBundle.install() or plain unzipping |
|||
* Infos stored in a local sqlite3 db (in ~/.xo_get/activities.db) |
|||
# Removing Activities via ActivityBundle.uninstall() |
|||
* Supported commands: |
|||
# Infos stored in a local sqlite3 db (in ~/.xo_get/activities.db) |
|||
# Successfully tested on the xo (build_648). [http://www.olpcaustria.org/mediawiki/index.php/Xo-get/Screenshots Screenshots] |
|||
# Supported commands: |
|||
./xo-get.py update |
./xo-get.py update |
||
./xo-get.py list [categories/category_name] |
./xo-get.py list ['categories' / category_name] |
||
./xo-get.py search |
./xo-get.py search activity_name / tag |
||
./xo-get.py install activity_name |
./xo-get.py install activity_name / activity_file.xo |
||
./xo-get.py remove activity_name |
./xo-get.py remove activity_name / activity_file.xo |
||
'''[http://www.linuxuser.at/xo-get.txt xo-get.py]''' |
'''[http://www.linuxuser.at/xo-get.txt xo-get.py]''' |
||
#! /usr/bin/env python |
#! /usr/bin/env python |
||
Line 18: | Line 22: | ||
# project page: http://www.olpcaustria.org/mediawiki/index.php/Xo-get |
# project page: http://www.olpcaustria.org/mediawiki/index.php/Xo-get |
||
# license: gpl |
# license: gpl |
||
# version: 0.4.1 |
|||
VERSION_NEWS = " 1. Install and remove any .xo file (like 'test.xo'): \n\ |
|||
./xo-get.py install test.xo \n\ |
|||
./xo-get.py remove test.xo" |
|||
import os |
import os |
||
Line 37: | Line 45: | ||
con = "" |
con = "" |
||
version = "" |
|||
def __init__(self, db_path): |
|||
def __init__(self, db_path, version): |
|||
self.db_path = db_path |
self.db_path = db_path |
||
self.version = version |
|||
# Change Directory |
# Change Directory |
||
Line 49: | Line 60: | ||
if os.path.isfile(self.db_filename): create_db = False |
if os.path.isfile(self.db_filename): create_db = False |
||
print "- [%s/%s]:" % (self.db_path, self.db_filename), |
|||
self.con = sqlite3.connect(self.db_filename) |
self.con = sqlite3.connect(self.db_filename) |
||
self.cur = self.con.cursor() |
self.cur = self.con.cursor() |
||
Line 58: | Line 68: | ||
self.cur.execute("CREATE TABLE 'activities' ('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'name' VARCHAR( 100 ) NOT NULL, 'desc' VARCHAR( 355 ) NOT NULL, 'xo_url' VARCHAR( 255 ) NOT NULL, 'category' VARCHAR( 255 ) NOT NULL, 'tags' VARCHAR( 255 ) NOT NULL);") |
self.cur.execute("CREATE TABLE 'activities' ('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'name' VARCHAR( 100 ) NOT NULL, 'desc' VARCHAR( 355 ) NOT NULL, 'xo_url' VARCHAR( 255 ) NOT NULL, 'category' VARCHAR( 255 ) NOT NULL, 'tags' VARCHAR( 255 ) NOT NULL);") |
||
self.con.commit() |
self.con.commit() |
||
print "created" |
print "- [%s/%s]: created\n" % (self.db_path, self.db_filename), |
||
# print "created" |
|||
else: |
else: |
||
# print "ok" |
|||
pass |
|||
# Check for version & display version news on update |
|||
self.cur.execute("CREATE TABLE IF NOT EXISTS 'versions' ('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'version' VARCHAR( 10 ) NOT NULL, 'notes' VARCHAR( 355 ) NOT NULL);") |
|||
self.con.commit() |
|||
q = "SELECT count(*) FROM versions WHERE version='%s'" % version |
|||
res = self.query(q) |
|||
if res[0][0] == 0: |
|||
# New Version Update |
|||
q = "INSERT INTO versions (version, notes) VALUES ('%s', '%s')" % (version, VERSION_NEWS.replace("'", '"')) |
|||
self.commit(q) |
|||
print |
|||
print " News to version %s:\n -----------------%s\n%s" % (version, "-"*len(version), VERSION_NEWS) |
|||
# q = "SELECT * FROM activities WHERE 1" |
|||
# print self.query(q) |
|||
def query(self, q): |
def query(self, q): |
||
Line 77: | Line 100: | ||
class XOGet: |
class XOGet: |
||
version = "0.4" |
version = "0.4.1" |
||
update_url = "http://www.linuxuser.at/xo-get.txt" |
update_url = "http://www.linuxuser.at/xo-get.txt" |
||
Line 92: | Line 115: | ||
print " xo-get %s" % self.version |
print " xo-get %s" % self.version |
||
print " %s" % ("~" * (len(self.version)+7)) |
print " %s" % ("~" * (len(self.version)+7)) |
||
# Loading DB |
|||
self.db = Database(self.localpath, self.version) |
|||
print |
|||
if len(sys.argv) == 1: |
if len(sys.argv) == 1: |
||
print " http://www.olpcaustria.org/mediawiki/index.php/Xo-get\n\n use: - update\n - list ['categories' / category_name] \n - search activity_name / tag\n - install activity_name\n - remove activity_name" |
print " http://www.olpcaustria.org/mediawiki/index.php/Xo-get\n\n use: - update\n - list ['categories' / category_name] \n - search activity_name / tag\n - install activity_name / activity_file.xo \n - remove activity_name / activity_file.xo" |
||
print |
print |
||
sys.exit(0) |
sys.exit(0) |
||
# Loading DB |
|||
self.db = Database(self.localpath) |
|||
print |
|||
if sys.argv[1] == "update": self.update() |
if sys.argv[1] == "update": self.update() |
||
if sys.argv[1] == "list": self.list() |
if sys.argv[1] == "list": self.list() |
||
Line 137: | Line 160: | ||
print "- Starting to remove '%s'" % app_name |
print "- Starting to remove '%s'" % app_name |
||
# |
# NEW: Install any .xo-file (outside repo) |
||
if os.path.isfile(app_name): |
|||
q = "SELECT xo_url FROM activities WHERE name = '%s'" % app_name |
|||
print " - (Local file)" |
|||
fn = app_name |
|||
else: |
|||
print " - No exact matching name found." |
|||
# Normal install via activity_name |
|||
q = "SELECT name FROM activities WHERE name LIKE '%s'" % app_name |
|||
# -> Get .xo Filename |
|||
q = "SELECT xo_url FROM activities WHERE name = '%s'" % app_name |
|||
res = self.db.query(q) |
res = self.db.query(q) |
||
if len(res) == 0: |
|||
print " - No exact matching name found." |
|||
q = "SELECT name FROM activities WHERE name LIKE '%s'" % app_name |
|||
res = self.db.query(q) |
res = self.db.query(q) |
||
if len(res) > 0: |
|||
app_name = res[0][0] |
|||
q = "SELECT xo_url FROM activities WHERE name = '%s'" % app_name |
|||
res = self.db.query(q) |
|||
else: |
|||
return False |
|||
# Extract Filename from URL => Write function for that (used 2x) |
|||
# Security Ask |
|||
fn = "%s/%s" % (self.localpath, res[0][0][res[0][0].rindex('/')+1:]) |
|||
if fn.count(";f=") > 0: |
|||
fn = fn[fn.rindex(";f=")+3:] |
|||
# Security Question |
|||
print |
print |
||
i = self.force_input("- Remove activity '%s'?" % app_name, ["y", "n"]) |
i = self.force_input("- Remove activity '%s'?" % app_name, ["y", "n"]) |
||
if i == "n": return False |
if i == "n": return False |
||
# Extract Filename from URL => Write function for that (used 2x) |
|||
fn = "%s/%s" % (self.localpath, res[0][0][res[0][0].rindex('/')+1:]) |
|||
if fn.count(";f=") > 0: |
|||
fn = fn[fn.rindex(";f=")+3:] |
|||
if os.path.isfile(fn): |
if os.path.isfile(fn): |
||
print "- Source file found (%s)" % fn |
print "- Source file found (%s)" % fn |
||
Line 183: | Line 213: | ||
else: |
else: |
||
# DBUS or Sugar Failure |
# DBUS or Sugar Failure |
||
if dbus_loaded == False: print "- Couldn't load dbus.mainloop.glib" |
|||
if sugar_loaded == False: |
if sugar_loaded == False: |
||
print "- Couldn't load sugar environment; removing not possible." |
print "- Couldn't load sugar environment; removing not possible." |
||
print " http://wiki.laptop.org/go/Sugar" |
print " http://wiki.laptop.org/go/Sugar" |
||
if dbus_loaded == False: print "- Couldn't load dbus.mainloop.glib" |
|||
else: |
else: |
||
# len(sys.argv) != 2 |
|||
print "- Plase supply an activity_name (eg: '%s remove imagequiz')" % sys.argv[0] |
print "- Plase supply an activity_name (eg: '%s remove imagequiz')" % sys.argv[0] |
||
return False |
return False |
||
Line 235: | Line 266: | ||
def install(self, s = None): |
def install(self, s = None): |
||
# s = Activity_Name, If not supplied to function, take from sys.argv |
# s = Activity_Name, If not supplied to function, take from sys.argv |
||
# local .xo filename |
|||
fn = None |
|||
# Check Parameters |
|||
if s == None: |
if s == None: |
||
if len(sys.argv) > 2: |
if len(sys.argv) > 2: |
||
s = sys.argv[2] |
s = sys.argv[2] |
||
if os.path.isfile(s): |
|||
# NEW: Supplied .xo app-name will search for .xo file, and if found installs from that |
|||
fn = s |
|||
print "- Installing Activity '%s'" % s |
|||
i = self.force_input(" - Do you want to proceed?", ["y", "n"]) |
|||
if i == "n": return False |
|||
print |
|||
else: |
|||
# Else: Format Name (" " > "_") |
|||
s = s.replace(" ", "_") |
|||
print "- Installing Activity '%s'" % s |
|||
else: |
else: |
||
print "- Plase supply an activity_name (eg: '%s install imagequiz')" % sys.argv[0] |
print "- Plase supply an activity_name (eg: '%s install imagequiz')" % sys.argv[0] |
||
return False |
return False |
||
# If there is no direct .xo-name supplied, search DB for .xo url |
|||
# Start Installation |
|||
if fn == None: |
|||
print "- Installing Activity '%s'" % s |
|||
q = "SELECT xo_url FROM activities WHERE name='%s'" % s |
q = "SELECT xo_url FROM activities WHERE name='%s'" % s |
||
res = self.db.query(q) |
|||
# No xo_url means no found activity |
|||
if len(res) == 0: |
|||
print " - No matching name found." |
|||
# Search DB with LIKE |
|||
q = "SELECT name FROM activities WHERE name LIKE '%s'" % s |
|||
res = self.db.query(q) |
res = self.db.query(q) |
||
# If no xo_url, then Search for similar Name! |
|||
if len(res) == 0: |
if len(res) == 0: |
||
print " - |
print " - No matching name found." |
||
# Search DB with LIKE |
|||
else: |
|||
q = "SELECT name FROM activities WHERE name LIKE '%s'" % s |
|||
res = self.db.query(q) |
|||
if len(res) == 0: |
|||
print " - Nothing found. Please try 'xo-get search'" |
|||
return False |
|||
else: |
|||
print " - Found quite similar name: '%s'" % res[0][0] |
|||
# Only Upper/Lowercase Problem |
# Only Upper/Lowercase Problem |
||
if s.lower() == res[0][0].lower(): |
if s.lower() == res[0][0].lower(): |
||
print |
print |
||
self.install(res[0][0]) |
self.install(res[0][0]) |
||
return True |
return True |
||
# Else Ask if to take it |
# Else Ask if to take it |
||
i = self.force_input(" - Use this name?", ["y", "n"]) |
i = self.force_input(" - Use this name?", ["y", "n"]) |
||
print |
print |
||
if i == "y": |
if i == "y": |
||
print |
|||
self.install(res[0][0]) |
|||
return True |
|||
return True |
|||
else: |
|||
return False |
|||
url = res[0][0] |
|||
# Installation process ready to download |
|||
fn = "%s/%s" % (self.localpath, res[0][0][res[0][0].rindex('/')+1:]) |
|||
i = self.force_input(" - Do you want to proceed?", ["y", "n"]) |
|||
if |
if fn.count(";f=") > 0: |
||
fn = fn[fn.index(";f=")+3:] |
|||
return False |
|||
# Installation process ready to download |
|||
i = self.force_input(" - Do you want to proceed?", ["y", "n"]) |
|||
if i == "n": return False |
|||
print |
print |
||
# start Download |
# start Download |
||
print "- Download => %s" % (fn) |
|||
url = res[0][0] |
|||
# print "- %s => %s" % (url, fn) |
|||
if fn.count(";f=") > 0: |
|||
fn = fn[fn.index(";f=")+3:] |
|||
# 1. Check if file exists |
|||
download = True |
|||
# print "- %s => %s" % (url, fn) |
|||
if os.path.isfile(fn): |
|||
# |
# File Exists: Ask if dl or use |
||
i = self.force_input(" - File already exists. Download again?", ["y", "n"]) |
|||
download = True |
|||
if |
if i == "n": |
||
download = False |
|||
# File Exists: Ask if dl or use |
|||
print |
|||
i = self.force_input(" - File already exists. Download again?", ["y", "n"]) |
|||
if i == "n": |
|||
# 2. If wanted, download .xo |
|||
download = False |
|||
if download: |
|||
try: xo = urllib2.urlopen(url).read() |
|||
except: |
|||
# 2. If wanted, download .xo |
|||
print "- Could not contact server." |
|||
if download: |
|||
return False |
|||
try: xo = urllib2.urlopen(url).read() |
|||
except: |
|||
print "- Could not contact server." |
|||
return False |
|||
f = open(fn, "w") |
f = open(fn, "w") |
||
f.write(xo) |
f.write(xo) |
||
f.close() |
f.close() |
||
else: # (if fn != None) |
|||
# If supplied .xo-filename, it's already checked and ready to go |
|||
pass |
|||
# Start Installation - Try The Sugar Way |
# Start Installation - Try The Sugar Way |
||
# app_name and fn, all ok, proceed to installation |
|||
try: |
try: |
||
sugar_loaded = True |
sugar_loaded = True |
||
Line 330: | Line 384: | ||
bundle = ActivityBundle(fn) |
bundle = ActivityBundle(fn) |
||
try: bundle.install() |
try: bundle.install() |
||
except: print " - |
except: print " - I think it's already installed :-)" |
||
else: |
else: |
||
if sugar_loaded == False: print " - Couldn't load sugar.bundle.activitybundle" |
if sugar_loaded == False: print " - Couldn't load sugar.bundle.activitybundle" |
||
if dbus_loaded == False: print " - Couldn't load dbus.mainloop.glib" |
if dbus_loaded == False: print " - Couldn't load dbus.mainloop.glib" |
||
i = self.force_input(" - Extract the Activity Bundle to %s/?" % self.localpath, ["y", "n"]) |
|||
i = self.force_input(" - Extract the Activity Bundle to %s/?" % self.localpath, ["y", "n"]) |
|||
if i == "y": |
if i == "y": |
||
c = "unzip %s -d %s" % (fn, self.localpath) |
c = "unzip %s -d %s" % (fn, self.localpath) |
||
print c |
print "\n- %s" % c |
||
os.system(c) |
os.system(c) |
||
Line 347: | Line 401: | ||
def update_xoget(self, to_version): |
def update_xoget(self, to_version): |
||
# Set local script filename (/.../xo-get.py) |
# Set local script filename (/.../xo-get.py) |
||
fn = sys.argv[0 |
fn = sys.argv[0] |
||
if fn.count('/') > 0: fn = fn[fn.rindex('/'):] |
|||
fn = "%s%s" % (sys.path[0], fn) |
fn = "%s%s" % (sys.path[0], fn) |
||
print "- Updating", fn |
print "- Updating", fn |
||
Line 364: | Line 420: | ||
def update(self): |
def update(self): |
||
# Download |
# Download |
||
# print "- Contacting server: [ %s%s ]" % (self.domain, self.path) |
|||
print "- Contacting server: [ %s ]" % (self.domain) |
|||
try: content = urllib2.urlopen("%s%s" % (self.domain, self.path)).read() |
try: content = urllib2.urlopen("%s%s" % (self.domain, self.path)).read() |
Revision as of 14:41, 7 December 2007
XO-Get is a very simple package-installer for the olpc xo-laptop.
- Source
- License: GPL
- Repository syncs with http://www.olpcaustria.org/mediawiki/index.php/Xo-get/Repository
- Installing & Removing of local .xo files, or download over web
- Installing with ActivityBundle.install() or plain unzipping
- Removing Activities via ActivityBundle.uninstall()
- Infos stored in a local sqlite3 db (in ~/.xo_get/activities.db)
- Successfully tested on the xo (build_648). Screenshots
- Supported commands:
./xo-get.py update ./xo-get.py list ['categories' / category_name] ./xo-get.py search activity_name / tag ./xo-get.py install activity_name / activity_file.xo ./xo-get.py remove activity_name / activity_file.xo
#! /usr/bin/env python # script started by crazy-chris, olpc-austria # project page: http://www.olpcaustria.org/mediawiki/index.php/Xo-get # license: gpl # version: 0.4.1 VERSION_NEWS = " 1. Install and remove any .xo file (like 'test.xo'): \n\ ./xo-get.py install test.xo \n\ ./xo-get.py remove test.xo" import os import sys import urllib2 import sqlite3 class Activity: name = u"" desc = u"" xo_url = u"" category = u"" tags = u"" class Database: db_path = "" db_filename = "activities.db" cur = "" con = "" version = "" def __init__(self, db_path, version): self.db_path = db_path self.version = version # Change Directory try: os.mkdir(self.db_path) except: pass os.chdir(self.db_path) # Init DB create_db = True if os.path.isfile(self.db_filename): create_db = False self.con = sqlite3.connect(self.db_filename) self.cur = self.con.cursor() self.cur.execute("-- types unicode") if create_db: # Setup New Database self.cur.execute("CREATE TABLE 'activities' ('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'name' VARCHAR( 100 ) NOT NULL, 'desc' VARCHAR( 355 ) NOT NULL, 'xo_url' VARCHAR( 255 ) NOT NULL, 'category' VARCHAR( 255 ) NOT NULL, 'tags' VARCHAR( 255 ) NOT NULL);") self.con.commit() print "- [%s/%s]: created\n" % (self.db_path, self.db_filename), # print "created" else: # print "ok" pass # Check for version & display version news on update self.cur.execute("CREATE TABLE IF NOT EXISTS 'versions' ('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'version' VARCHAR( 10 ) NOT NULL, 'notes' VARCHAR( 355 ) NOT NULL);") self.con.commit() q = "SELECT count(*) FROM versions WHERE version='%s'" % version res = self.query(q) if res[0][0] == 0: # New Version Update q = "INSERT INTO versions (version, notes) VALUES ('%s', '%s')" % (version, VERSION_NEWS.replace("'", '"')) self.commit(q) print print " News to version %s:\n -----------------%s\n%s" % (version, "-"*len(version), VERSION_NEWS) def query(self, q): dataList = [] self.cur.execute(q) data = self.cur.fetchall() if data: dataList = [list(row) for row in data] return dataList def commit(self, q): self.cur.execute(q) self.con.commit() class XOGet: version = "0.4.1" update_url = "http://www.linuxuser.at/xo-get.txt" # domain = "http://wiki.laptop.org" # path = "/go/Xo-get/Repository" domain = "http://www.olpcaustria.org" path = "/mediawiki/index.php?title=Xo-get/Repository&printable=yes" localpath = "%s/%s" % (os.path.expanduser( '~' ), ".xo_get") def __init__(self): print print " xo-get %s" % self.version print " %s" % ("~" * (len(self.version)+7)) # Loading DB self.db = Database(self.localpath, self.version) print if len(sys.argv) == 1: print " http://www.olpcaustria.org/mediawiki/index.php/Xo-get\n\n use: - update\n - list ['categories' / category_name] \n - search activity_name / tag\n - install activity_name / activity_file.xo \n - remove activity_name / activity_file.xo" print sys.exit(0) if sys.argv[1] == "update": self.update() if sys.argv[1] == "list": self.list() if sys.argv[1] == "search": self.search() if sys.argv[1] == "install": self.install() if sys.argv[1] == "remove": self.remove() print def force_input(self, question, possibilities): i = "" while i not in possibilities: print "%s [%s]" % (question, "/".join(possibilities)), i = raw_input() return i def remove(self): # To remove, we need sugar, and the .xo file if len(sys.argv) > 2: # Load Sugar try: sugar_loaded = True from sugar.bundle.activitybundle import ActivityBundle except: sugar_loaded = False try: dbus_loaded = True from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) except: dbus_loaded = False if sugar_loaded and dbus_loaded: # Try to get correct app_name, then xo file app_name = sys.argv[2] print "- Starting to remove '%s'" % app_name # NEW: Install any .xo-file (outside repo) if os.path.isfile(app_name): print " - (Local file)" fn = app_name else: # Normal install via activity_name # -> Get .xo Filename q = "SELECT xo_url FROM activities WHERE name = '%s'" % app_name res = self.db.query(q) if len(res) == 0: print " - No exact matching name found." q = "SELECT name FROM activities WHERE name LIKE '%s'" % app_name res = self.db.query(q) if len(res) > 0: app_name = res[0][0] q = "SELECT xo_url FROM activities WHERE name = '%s'" % app_name res = self.db.query(q) else: return False # Extract Filename from URL => Write function for that (used 2x) fn = "%s/%s" % (self.localpath, res[0][0][res[0][0].rindex('/')+1:]) if fn.count(";f=") > 0: fn = fn[fn.rindex(";f=")+3:] # Security Question print i = self.force_input("- Remove activity '%s'?" % app_name, ["y", "n"]) if i == "n": return False if os.path.isfile(fn): print "- Source file found (%s)" % fn else: print "- No source file found (%s)" % fn return False bundle = ActivityBundle(fn) if bundle.is_installed(): print "- Removing..." bundle.uninstall() print "- Finished!" return True else: print "- Activity is not yet installed" return False else: # DBUS or Sugar Failure if dbus_loaded == False: print "- Couldn't load dbus.mainloop.glib" if sugar_loaded == False: print "- Couldn't load sugar environment; removing not possible." print " http://wiki.laptop.org/go/Sugar" else: # len(sys.argv) != 2 print "- Plase supply an activity_name (eg: '%s remove imagequiz')" % sys.argv[0] return False def list(self): # Lists available Activities q = "SELECT name, desc, category, tags FROM activities WHERE 1" print "- Listing", if len(sys.argv) > 2: if sys.argv[2] == "categories": print "Categories:" q = "SELECT DISTINCT category FROM activities WHERE 1 ORDER BY category ASC" res = self.db.query(q) for r in res: print " - [%s]" % r[0] return True else: print "Category '%s'" % sys.argv[2] q = "%s AND category LIKE '%s'" % (q, sys.argv[2]) else: print "All Activities" q = "%s%s" % (q, " ORDER BY category ASC, name ASC") res = self.db.query(q) spaces = 18 spaces2 = 14 for r in res: print " -", " " * (spaces2 - len(r[2])), print "[ %s ] " % r[2], r[0], "." * (spaces - len(r[0])), r[1] def search(self): # Search for tags and name if len(sys.argv) > 2: s = sys.argv[2].replace(" ", "_") print "- Results for '%s':" % s q = "SELECT name, desc, category FROM activities WHERE tags LIKE '%s%s%s' OR name LIKE '%s%s%s' ORDER BY category ASC, name ASC" % ('%', s, '%', '%', s, '%') res = self.db.query(q) spaces = 18 spaces2 = 8 for r in res: print " - [%s]" % r[2], " " * (spaces2 - len(r[2])), r[0], "." * (spaces - len(r[0])), r[1] else: print "- Please supply query-string (eg: '%s search quiz')" % sys.argv[0] def install(self, s = None): # s = Activity_Name, If not supplied to function, take from sys.argv # local .xo filename fn = None # Check Parameters if s == None: if len(sys.argv) > 2: s = sys.argv[2] if os.path.isfile(s): # NEW: Supplied .xo app-name will search for .xo file, and if found installs from that fn = s print "- Installing Activity '%s'" % s i = self.force_input(" - Do you want to proceed?", ["y", "n"]) if i == "n": return False print else: # Else: Format Name (" " > "_") s = s.replace(" ", "_") print "- Installing Activity '%s'" % s else: print "- Plase supply an activity_name (eg: '%s install imagequiz')" % sys.argv[0] return False # If there is no direct .xo-name supplied, search DB for .xo url if fn == None: q = "SELECT xo_url FROM activities WHERE name='%s'" % s res = self.db.query(q) # If no xo_url, then Search for similar Name! if len(res) == 0: print " - No matching name found." # Search DB with LIKE q = "SELECT name FROM activities WHERE name LIKE '%s'" % s res = self.db.query(q) if len(res) == 0: print " - Nothing found. Please try 'xo-get search'" return False else: print " - Found quite similar name: '%s'" % res[0][0] # Only Upper/Lowercase Problem if s.lower() == res[0][0].lower(): print self.install(res[0][0]) return True # Else Ask if to take it i = self.force_input(" - Use this name?", ["y", "n"]) print if i == "y": print self.install(res[0][0]) return True else: return False url = res[0][0] fn = "%s/%s" % (self.localpath, res[0][0][res[0][0].rindex('/')+1:]) if fn.count(";f=") > 0: fn = fn[fn.index(";f=")+3:] # Installation process ready to download i = self.force_input(" - Do you want to proceed?", ["y", "n"]) if i == "n": return False print # start Download print "- Download => %s" % (fn) # print "- %s => %s" % (url, fn) # 1. Check if file exists download = True if os.path.isfile(fn): # File Exists: Ask if dl or use i = self.force_input(" - File already exists. Download again?", ["y", "n"]) if i == "n": download = False print # 2. If wanted, download .xo if download: try: xo = urllib2.urlopen(url).read() except: print "- Could not contact server." return False f = open(fn, "w") f.write(xo) f.close() else: # (if fn != None) # If supplied .xo-filename, it's already checked and ready to go pass # Start Installation - Try The Sugar Way # app_name and fn, all ok, proceed to installation try: sugar_loaded = True from sugar.bundle.activitybundle import ActivityBundle except: sugar_loaded = False try: dbus_loaded = True from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) except: dbus_loaded = False print "- Starting Installation" if sugar_loaded and dbus_loaded: # install the sugar way # like os.system("sugar-install-bundle %s" % fn), but in here: bundle = ActivityBundle(fn) try: bundle.install() except: print " - I think it's already installed :-)" else: if sugar_loaded == False: print " - Couldn't load sugar.bundle.activitybundle" if dbus_loaded == False: print " - Couldn't load dbus.mainloop.glib" i = self.force_input(" - Extract the Activity Bundle to %s/?" % self.localpath, ["y", "n"]) if i == "y": c = "unzip %s -d %s" % (fn, self.localpath) print "\n- %s" % c os.system(c) print print "- Finished" def update_xoget(self, to_version): # Set local script filename (/.../xo-get.py) fn = sys.argv[0] if fn.count('/') > 0: fn = fn[fn.rindex('/'):] fn = "%s%s" % (sys.path[0], fn) print "- Updating", fn # Download new Script content = urllib2.urlopen(self.update_url).read() f = open(fn, "w") f.write(content) f.close() # os.system("python %s init" % sys.argv[0]) # print "rm %s/%s" % (self.localpath, self.db.db_filename) print "- Update to version %s finished" % to_version def update(self): # Download # print "- Contacting server: [ %s%s ]" % (self.domain, self.path) print "- Contacting server: [ %s ]" % (self.domain) try: content = urllib2.urlopen("%s%s" % (self.domain, self.path)).read() except: "- Server Down :(" return False # Extract Version => version try: version = content[content.index('cur_ver=')+8:] version = version[:version.index('<')] except: version = None print "- Local version: %s (current: %s)" % (self.version, version) # Check Version if self.version != version and version != None: # Update Possible i = self.force_input(" - Update xo-get to version: %s?" % version, ["y", "n"]) if i == "y": # Update Now print self.update_xoget(version) return True # Extract Repository => content print content = content[content.index('<table border="0"'):]
content = content[:content.index('')]
# Clear DB print "- Clearing database:", self.db.commit("DELETE FROM activities WHERE 1") print "ok" # Add Activities print "- Adding activities:",
content_arr = content.split("") act_count = 0 for act_html in content_arr: # Extract Each Activity if act_html.count("") > 0:
# Add Activity
act_html = act_html.replace("", "") act_html = act_html.replace("", "") # Put all Info in class a = Activity() a = Activity() act_html_arr = act_html.split("")
a.name = act_html_arr[1].strip().replace(" ", "_") if a.name.count('">') > 0: a.name = a.name[a.name.index('">')+2:] a.name = a.name[:a.name.index('<')] # Existing Activity? if a.name != "": a.xo_url = act_html_arr[2].strip().replace("%s%s" % ("&a", "mp"), "&") a.xo_url = a.xo_url[a.xo_url.index("http"):] if a.xo_url.count('"') > 0: a.xo_url = a.xo_url[:a.xo_url.index('"')] a.desc = act_html_arr[3].strip() a.category = act_html_arr[4].strip() a.tags = act_html_arr[5].strip() # Submit to DB q = "INSERT INTO activities (name, xo_url, desc, category, tags) VALUES ('%s', '%s', '%s', '%s', '%s')" % (a.name, a.xo_url, a.desc, a.category, a.tags) act_count += 1 self.db.commit(q) print act_count print "- Database is up-to-date" if __name__ == "__main__": xoget = XOGet()