#!/usr/bin/env python """ qgis_plugins.py author: Matthew Perry license: GPL date: 2007-Oct-21 """ import urllib import sys import os import tempfile import zipfile from xml.dom import minidom, Node class unzip: """ unzip.py Version: 1.1 Extract a zipfile to the directory provided It first creates the directory structure to house the files then it extracts the files to it. import unzip un = unzip.unzip() un.extract(r'c:\testfile.zip', 'c:\testoutput') By Doug Tolton (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252508) """ def __init__(self, verbose = True, percent = 10): self.verbose = verbose self.percent = percent def extract(self, file, dir): if not dir.endswith(':') and not os.path.exists(dir): os.mkdir(dir) zf = zipfile.ZipFile(file) # create directory structure to house files print "Creating plugin structure" self._createstructure(file, dir) num_files = len(zf.namelist()) percent = self.percent divisions = 100 / percent perc = int(num_files / divisions) # extract files to directory structure for i, name in enumerate(zf.namelist()): if self.verbose == True: print "Extracting %s" % name elif perc > 0 and (i % perc) == 0 and i > 0: complete = int (i / perc) * percent print "%s%% complete" % complete if not name.endswith('/'): outfile = open(os.path.join(dir, name), 'wb') outfile.write(zf.read(name)) outfile.flush() outfile.close() def _createstructure(self, file, dir): self._makedirs(self._listdirs(file), dir) def _makedirs(self, directories, basedir): """ Create any directories that don't currently exist """ print "Creating directories contained in the zip file: %s" % directories for dir in directories: curdir = os.path.join(basedir, dir) # normalize the path curdir = os.path.normpath(curdir) print "Checking to see if we should create %s" % curdir if not os.path.exists(curdir): # use makedirs to create parent directories as well print "Creating %s" % curdir os.makedirs(curdir) def _listdirs(self, file): """ Grabs all the directories in the zip structure This is necessary to create the structure before trying to extract the file to it. """ zf = zipfile.ZipFile(file) dirs = [] for file in zf.filelist: if file.external_attr >> 28 == 4: print "Adding %s to the list of directories to create" % file.filename dirs.append(file.filename) #for name in zf.namelist(): # if name.endswith('/'): # dirs.append(name) ## Check for subdirectories by assuming a file with length 0 ## is a directory (this isn't necessarily true but it allows ## plugins with subdirectories to be installed) #for file in zf.filelist: # if file.file_size == 0: # dirs.append(file.file_name) if len(dirs) == 0: # this means there is no top level directory in the # zip file. We'll assume the first entry contains the # directory and use it entry = zf.namelist()[0] dir = entry.split('/')[0] dir += '/' dirs.append(dir) dirs.sort() return dirs def retrieve_list(repos): repos = urllib.urlopen(repos).read() repos_xml = minidom.parseString(repos) plugin_nodes = repos_xml.getElementsByTagName("pyqgis_plugin") plugins = [ {"name" : x.getAttribute("name").encode(), "version" : x.getAttribute("version").encode(), "desc" : x.getElementsByTagName("description")[0].childNodes[0].nodeValue.encode(), "author" : x.getElementsByTagName("author_name")[0].childNodes[0].nodeValue.encode(), "url" : x.getElementsByTagName("download_url")[0].childNodes[0].nodeValue.encode(), "filename": x.getElementsByTagName("file_name")[0].childNodes[0].nodeValue.encode()} for x in plugin_nodes] return plugins def install_plugin(plugin, plugindir, repos): # normalize the path to the users plugin directory plugindir = os.path.normpath(plugindir) plugin_list = retrieve_list(repos) target = [x for x in plugin_list if x["name"] == plugin] if target: # Take the first match target = target[0] url = target["url"] filename = target["filename"] print "Retrieving from %s" % url try: tmpdir = tempfile.gettempdir() outfile = os.path.join(tmpdir,filename) urllib.urlretrieve(url,outfile) except: return (False, "Failed to download file to %s" % outfile) return # make sure that the parent directory exists if not os.path.exists(plugindir): os.makedirs(plugindir) print "Extracting to plugin directory (%s)" % plugindir try: un = unzip() un.extract(outfile, plugindir) except: return (False, "Failed to unzip file to %s ... check permissions" % plugindir) else: return (False, "No plugins found named %s" % plugin) return (True, "Python plugin installed. Go to Plugins > Plugin Manager to enable %s." % plugin )