]> git.donarmstrong.com Git - neurodebian.git/blobdiff - neurodebian/dde.py
NF: List recommened and suggested packages as 'related packages'.
[neurodebian.git] / neurodebian / dde.py
index 746fee192080f5e518b0f4ed9f3b75bf4629a541..f3c959e25dfd285f2bbc1d4f6021945830275469 100644 (file)
@@ -5,6 +5,7 @@
 import pysvn
 import json
 from debian_bundle import deb822
+import apt
 from ConfigParser import SafeConfigParser
 from optparse import OptionParser, Option, OptionGroup, OptionConflictError
 import sys
@@ -12,6 +13,7 @@ import os
 import shutil
 import urllib2
 import urllib
+import codecs
 import subprocess
 # templating
 from jinja2 import Environment, PackageLoader
@@ -109,7 +111,7 @@ class AptListsCache(object):
                 urllib.urlcleanup()
 
         # open cached file
-        fh = open(cfilename, 'r')
+        fh = codecs.open(cfilename, 'r', 'utf-8')
 
         return fh
 
@@ -166,53 +168,82 @@ def import_blendstask(db, url):
             task_name = st['Task']
             task = (blendname, task_name, taskpage_url)
 
-        # do not stop unless we have a description
-        if not st.has_key('Pkg-Description'):
-            continue
-
         if st.has_key('Depends'):
             pkg = st['Depends']
         elif st.has_key('Suggests'):
             pkg = st['Suggests']
         else:
-            print 'Warning: Cannot determine name of prospective package ' \
-                    '... ignoring.'
+#            print 'Warning: Cannot determine name of prospective package ' \
+#                    '... ignoring. Dump follows:'
+#            print st
             continue
 
-        if not db.has_key(pkg):
-            print 'Ignoring blend package "%s"' % pkg
-            continue
-
-        info = {}
+        # take care of pkg lists
+        for p in pkg.split(', '):
+            if not db.has_key(p):
+                print 'Ignoring blend package "%s"' % p
+                continue
 
-        # blends info
-        info['tasks'] = [task]
-        if st.has_key('License'):
-            info['license'] = st['License']
-        if st.has_key('Responsible'):
-            info['responsible'] = st['Responsible']
-
-        # pkg description
-        descr = st['Pkg-Description'].replace('%', '%%').split('\n')
-        info['description'] = descr[0].strip()
-        info['long_description'] = ' '.join([l.strip() for l in descr[1:]])
-
-        # charge the basic property set
-        db[pkg]['main']['description'] = info['description']
-        db[pkg]['main']['long_description'] = info['long_description']
-        if st.has_key('WNPP'):
-            db[pkg]['main']['debian_itp'] = st['WNPP']
-        if st.has_key('Pkg-URL'):
-            db[pkg]['main']['other_pkg'] = st['Pkg-URL']
-        if st.has_key('Homepage'):
-            db[pkg]['main']['homepage'] = st['Homepage']
-
-        # only store if there isn't something already
-        if not db[pkg].has_key('blends'):
-            db[pkg]['blends'] = info
-        else:
-            # just add this tasks name and id
-            db[pkg]['blends']['tasks'].append(task)
+            info = {}
+
+            # blends info
+            info['tasks'] = [task]
+            if st.has_key('License'):
+                info['license'] = st['License']
+            if st.has_key('Responsible'):
+                info['responsible'] = st['Responsible']
+
+            # pkg description
+            if st.has_key('Pkg-Description'):
+                descr = st['Pkg-Description'].split('\n')
+                info['description'] = descr[0].strip()
+                info['long_description'] = \
+                        u'\n'.join(descr[1:])
+
+                # charge the basic property set
+                db[p]['main']['description'] = info['description']
+                db[p]['main']['long_description'] = info['long_description']
+            if st.has_key('WNPP'):
+                db[p]['main']['debian_itp'] = st['WNPP']
+            if st.has_key('Pkg-URL'):
+                db[p]['main']['other_pkg'] = st['Pkg-URL']
+            if st.has_key('Homepage'):
+                db[p]['main']['homepage'] = st['Homepage']
+
+            # Publications
+            if st.has_key('Published-Title'):
+                pub = {'title': st['Published-Title']}
+                if st.has_key('Published-Authors'):
+                    pub['authors'] = st['Published-Authors']
+                if st.has_key('Published-Year'):
+                    pub['year'] = st['Published-Year']
+                if st.has_key('Published-In'):
+                    pub['in'] = st['Published-In']
+                if st.has_key('Published-URL'):
+                    pub['url'] = st['Published-URL']
+                if st.has_key('Published-DOI'):
+                    pub['doi'] = st['Published-DOI']
+                    # need at least one URL
+                    if not pub.has_key('url'):
+                        pub['url'] = st['Published-DOI']
+
+                db[p]['main']['publication'] = pub
+
+            # Registration
+            if st.has_key('Registration'):
+                db[p]['main']['registration'] = st['Registration']
+
+            # Remarks
+            if st.has_key('Remark'):
+                # prepend a single space to make it look like a long description
+                info['remark'] = convert_longdescr(' ' + st['Remark'])
+
+            # only store if there isn't something already
+            if not db[p].has_key('blends'):
+                db[p]['blends'] = info
+            else:
+                # just add this tasks name and id
+                db[p]['blends']['tasks'].append(task)
 
     return db
 
@@ -300,7 +331,9 @@ def _store_pkg(cfg, db, st, origin, codename, component, baseurl):
     info['version'] = st['Version']
 
     # origin
-    info['drc'] = '%s %s %s' % (origin, codename, component)
+    info['distribution'] = origin
+    info['release'] = codename
+    info['component'] = component
 
     # pool url
     info['poolurl'] = '/'.join([os.path.dirname(st['Filename'])])
@@ -308,15 +341,21 @@ def _store_pkg(cfg, db, st, origin, codename, component, baseurl):
     # pkg description
     descr = st['Description'].replace('%', '%%').split('\n')
     info['description'] = descr[0].strip()
-    info['long_description'] = ' '.join([l.strip() for l in descr[1:]])
+    info['long_description'] = u'\n'.join(descr[1:])
 
     db[pkg][distkey] = info
 
     # charge the basic property set
     db[pkg]['main']['description'] = info['description']
     db[pkg]['main']['long_description'] = info['long_description']
+    if st.has_key('Source'):
+        db[pkg]['main']['sv'] = "%s %s" % (st['Source'], st['Version'])
+    else:
+        db[pkg]['main']['sv'] = "%s %s" % (st['Package'], st['Version'])
     if st.has_key('Homepage'):
         db[pkg]['main']['homepage'] = st['Homepage']
+    if st.has_key('Recommends'):
+        db[pkg]['main']['recommends'] = st['Recommends']
 
     return db
 
@@ -349,45 +388,112 @@ def create_dir(path):
 def dde_get(url):
     try:
         return json.read(urllib2.urlopen(url+"?t=json").read())['r']
-    except urllib2.HTTPError:
+    except (urllib2.HTTPError, StopIteration):
+        print "NO PKG INFO AT:", url
         return False
 
 
 def import_dde(cfg, db):
-    dists = cfg.get('dde', 'dists').split()
     query_url = cfg.get('dde', 'pkgquery_url')
     for p in db.keys():
         # get freshest
-        q = dde_get(query_url + "/all/%s" % p)
+        q = dde_get(query_url + "/packages/all/%s" % p)
         if q:
-            db[p]['main'] = q
-        for d in dists:
-            q = dde_get(query_url + "/prio-%s/%s" % (d, p))
-            if q:
-                db[p][(trans_codename(d.split('-')[1], cfg),d)] = q
+            # copy all stuff, while preserving non-overlapping information
+            for k, v in q.iteritems():
+                db[p]['main'][k] = v
+            # get latest popcon info for debian and ubuntu
+            # cannot use origin field itself, since it is none for few packages
+            # i.e. python-nifti
+            origin = q['drc'].split()[0]
+            if origin == 'ubuntu':
+                if q.has_key('popcon'):
+                    db[p]['main']['ubuntu_popcon'] = q['popcon']
+                # if we have ubuntu, need to get debian
+                q = dde_get(query_url + "/packages/prio-debian-sid/%s" % p)
+                if q and q.has_key('popcon'):
+                    db[p]['main']['debian_popcon'] = q['popcon']
+            elif origin == 'debian':
+                if q.has_key('popcon'):
+                    db[p]['main']['debian_popcon'] = q['popcon']
+                # if we have debian, need to get ubuntu
+                q = dde_get(query_url + "/packages/prio-ubuntu-karmic/%s" % p)
+                if q and q.has_key('popcon'):
+                    db[p]['main']['ubuntu_popcon'] = q['popcon']
+            else:
+                print("Ignoring unkown origin '%s' for package '%s'." \
+                        % (origin, p))
+
+        # now get info for package from all releases in UDD
+        q = dde_get(query_url + "/dist/p:%s" % p)
+        if not q:
+            continue
+        # hold all info about this package per distribution release
+        info = {}
+        for cp in q:
+            distkey = (trans_codename(cp['release'], cfg),
+                       "%s-%s" % (cp['distribution'], cp['release']))
+            if not info.has_key(distkey):
+                info[distkey] = cp
+                # turn into a list to append others later
+                info[distkey]['architecture'] = [info[distkey]['architecture']]
+            # accumulate data for multiple over archs
+            else:
+                comp = apt.VersionCompare(cp['version'],
+                                          info[distkey]['version'])
+                # found another arch for the same version
+                if comp == 0:
+                    info[distkey]['architecture'].append(cp['architecture'])
+                # found newer version, dump the old ones
+                elif comp > 0:
+                    info[distkey] = cp
+                    # turn into a list to append others later
+                    info[distkey]['architecture'] = [info[distkey]['architecture']]
+                # simply ignore older versions
+                else:
+                    pass
+
+        # finally assign the new package data
+        for k, v in info.iteritems():
+            db[p][k] = v
 
     return db
 
 
+def convert_longdescr(ld):
+    ld = ld.replace('% ', '%% ')
+    ld = ld.split('\n')
+    for i, l in enumerate(ld):
+        if l == ' .':
+            ld[i] = ' #NEWLINEMARKER#'
+        # look for embedded lists
+        elif len(l) >=3 and l[:2] == '  ' and l[2] in '-*':
+            ld[i] = ' #NEWLINEMARKER# ' + l[2:]
+
+    ld = u' '.join([l[1:] for l in ld])
+    ld = ld.replace('#NEWLINEMARKER# ', '\n\n')
+    # cleanup any leftover (e.g. trailing markers)
+    ld = ld.replace('#NEWLINEMARKER#', '')
+    return ld
+
+
 def generate_pkgpage(pkg, cfg, db, template, addenum_dir):
     # local binding for ease of use
-    db = db[pkg]
+    pkgdb = db[pkg]
     # do nothing if there is not at least the very basic stuff
-    if not db['main'].has_key('description'):
+    if not pkgdb['main'].has_key('description'):
         return
-    title = '**%s** -- %s' % (pkg, db['main']['description'])
+    title = '**%s** -- %s' % (pkg, pkgdb['main']['description'])
     underline = '*' * (len(title) + 2)
     title = '%s\n %s\n%s' % (underline, title, underline)
 
-    # preprocess long description
-    ld = db['main']['long_description']
-    ld = ' '.join([l.lstrip(' .') for l in ld.split('\n')])
-
-    page = template.render(pkg=pkg,
-                           title=title,
-                           long_description=ld,
-                           cfg=cfg,
-                           db=db)
+    page = template.render(
+            pkg=pkg,
+            title=title,
+            long_description=convert_longdescr(pkgdb['main']['long_description']),
+            cfg=cfg,
+            db=pkgdb,
+            fulldb=db)
     # the following can be replaced by something like
     # {% include "sidebar.html" ignore missing %}
     # in the template whenever jinja 2.2 becomes available
@@ -399,13 +505,13 @@ def generate_pkgpage(pkg, cfg, db, template, addenum_dir):
 
 def store_db(db, filename):
     pp = PrettyPrinter(indent=2)
-    f = open(filename, 'w')
+    f = codecs.open(filename, 'w', 'utf-8')
     f.write(pp.pformat(db))
     f.close()
 
 
 def read_db(filename):
-    f = open(filename)
+    f = codecs.open(filename, 'r', 'utf-8')
     db = eval(f.read())
     return db
 
@@ -439,7 +545,7 @@ def write_pkgpages(jinja_env, cfg, db, outdir, addenum_dir):
 
     # generate the TOC with all packages
     toc_template = jinja_env.get_template('pkgs_toc.rst')
-    toc = open(os.path.join(outdir, 'pkgs.rst'), 'w')
+    toc = codecs.open(os.path.join(outdir, 'pkgs.rst'), 'w', 'utf-8')
     toc.write(toc_template.render(pkgs=db.keys()))
     toc.close()
 
@@ -450,8 +556,8 @@ def write_pkgpages(jinja_env, cfg, db, outdir, addenum_dir):
         # when no page is available skip this package
         if page is None:
             continue
-        pf = open(os.path.join(outdir, 'pkgs', p + '.rst'), 'w')
-        pf.write(generate_pkgpage(p, cfg, db, pkg_template, addenum_dir))
+        pf = codecs.open(os.path.join(outdir, 'pkgs', p + '.rst'), 'w', 'utf-8')
+        pf.write(page)
         pf.close()