[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Sage in Debian status update



Le 22/02/2013 11:15, Tobias Hansen a écrit :
As you can see on the Wiki page, the most obvious open tasks are now
updating flint and singular, and packaging libgap and lrcalc. And of
course, starting to package Sage itself. If someone is up for this, now
would already be a good time to start building Sage against the Debian
packages and look for issues that have to be resolved.

When it comes to packaging, there are low-hanging fruits : sage contains databases of Conway polynomials, elliptic curves, graphs and polytopes. They're pretty trivial to package (copy a few files in place).

There is a problem with our fplll which is too recent compared to what ships in sage. They have a bug report (ticket in sage-speak) to make things better, but it contains a patch to sage (ok) and a patch to fpll (I complained, negotiating either to have a better patch or push it in next upstream).

I have scripts to (try to...) build sage against what is in debian, see attached. Notice:
- the comments in spkg_to_dpkg are not all up to date
- feedback on them is welcome
- to use them (1) edit the sagedir variable in debian_pruner.py, then run it from the toplevel of a freshly-untarred sage source tarball, (2) export PYTHONHOME as the script says and finally (3) type 'make'.

One day, that will give a nice working sage (and the day after, sage will be in debian).

Hope that helps,

Snark on #debian-science
#!/usr/bin/python
# -*- coding: utf-8 -*-

import io,os
from apt import *
from spkg_to_dpkg import spkg_deps

do_linking = True # if False, print the colors for the dependencies dot file
verbose = True # if True, print what is done

# FIXME: I wrote code to find the version of the spkg&deb, but that
# code is not used to check we have the correct versions!
# 
# It won't be trivial to code for at least three separate reasons :
#
# - each upstream can have its own numbering scheme ;
#
# - each spkg will have its ".p314" appended, when it's not a
# prepended "cropped"... or something else ;
#
# - each deb will also have modifiers like "-314build314"... or
# - something else.
#
# Wasn't it the beatles who sang "I need love" ?

sagedir = u'/home/jpuydt/sage-5.6'
cache = Cache() # that line can take long...

def build_spkg_versions():
    result = dict()
    for filename in os.listdir(os.path.join (sagedir, u'spkg', u'standard')):
        if filename[-4:] == u'spkg': # use -4 here because there's u'deps'!
            name_and_version = filename[:-5]
            version = u'-'.join(name_and_version.split(u'-')[1:])
            name = name_and_version.split(u'-')[0]
            result[name]=version
    return result

spkg_versions = build_spkg_versions()

def spkg_version(name):
    return spkg_versions[name]

def dpkg_version(package):
    return package.installed.version

def correct_version(s_version, d_version):
    # FIXME
    return True

def remove_file(name):
    os.remove(name)

def create_directory(name):
    try:
        os.makedirs(name)
        if verbose:
            print (u'create_directory(%s)' % name)
    except:
        pass

def symlink_file(source, target):
    try:
        os.symlink(source, target)
        if verbose:
            print (u'symlink(%s, %s)' % (source, target))
    except:
        pass

def symlink_directory(source, target):
    create_directory(target)
    for name in os.listdir(source):
        next_source=os.path.join(source, name)
        next_target=os.path.join(target, name)
        if os.path.isdir(next_source):
            symlink_directory(next_source, next_target)
        else:
            symlink_file(next_source, next_target)

def python_workarounds():
    directory = os.path.join (sagedir, u'local', u'bin')
    symlink_file (os.path.join(directory, u'python2.7'), os.path.join(directory, u'python'))

    directory = os.path.join (sagedir, u'local', u'lib')
    symlink_file (os.path.join(directory, u'python2.7'), os.path.join(directory, u'python'))

    directory = os.path.join (sagedir, u'local', u'lib', u'python2.7')
    symlink_file (os.path.join(directory, u'dist-packages'), os.path.join(directory, u'site-packages'))

    directory = os.path.join (sagedir, u'local', u'lib', u'python2.7')
    symlink_directory (os.path.join(u'/usr', u'lib', u'python2.7', u'dist-packages'), os.path.join(directory, u'dist-packages'))

def setuptools_workarounds():
    directory = os.path.join (sagedir, u'local', u'bin')
    remove_file(os.path.join (directory, u'easy_install'))
    remove_file(os.path.join (directory, u'easy_install-2.7'))
    remove_file(os.path.join (directory, u'easy_install-2.6'))

def cython_workarounds():
    source = os.path.join(u'/usr', u'lib', u'pymodules', u'python2.7', u'Cython')
    target = os.path.join (sagedir, u'local', u'lib', u'python2.7',  u'dist-packages', u'Cython')
    symlink_directory (source, target)

workarounds = {
    u'python2.7': python_workarounds,
    u'python-setuptools': setuptools_workarounds,
    u'cython': cython_workarounds
}

def do_special_thing_if_needed (package):
    if workarounds.has_key(package.name):
        workarounds[package.name]()
        print ('Did something special for %s' % package.name)

def prune_spkg(name, version):
    filename = os.path.join (sagedir, u'spkg', u'installed', '%s-%s' % (name, version))
    stream = io.open(filename, 'w')
    stream.write(u'The SYSTEM package was used!\n')
    stream.close()

def stow_dpkg(package):
    if verbose:
        print ('stow_dpkg(%s)' % package.name)
    excludes = [u'', u'/.', u'/usr']
    for name in package.installed_files:
        if name not in excludes:
            target_name = os.path.join(sagedir, u'local', os.path.relpath(name, u'/usr'))
            if os.path.isdir(name):
                create_directory (target_name)
            else:
                symlink_file (name, target_name)
    do_special_thing_if_needed (package)

def loop_on_spkgs():
    create_directory (os.path.join (sagedir, u'spkg', u'installed'))
    directory = os.path.join (sagedir, u'local')
    create_directory(directory)
    symlink_file (directory, os.path.join(directory, u'local')) # that one is baffling!
    for (spkg_name, dpkg_names) in spkg_deps.items():
        prunable = True
        for dpkg_name in dpkg_names:
            try:
                dpkg = cache[dpkg_name]
                if dpkg.installed == None:
                    prunable = False
                    print ("Can't prune %s: missing package %s" % (spkg_name, dpkg_name))
            except KeyError:
                prunable = False
                if dpkg_name == u'unsupported':
                    if do_linking:
                        print ("Can't prune %s: unsupported" % spkg_name)
                    else:
                        print ("""  %s [color="red"];""" % spkg_name.upper())
                else:
                    if do_linking:
                        print ("Can't prune %s: %s not found" % (spkg_name, dpkg_name))
                    else:
                        print ("""  %s [color="orange"];""" % spkg_name.upper())
            if not prunable:
                break
        if prunable:
            for dpkg_name in dpkg_names:
                dpkg = cache[dpkg_name]
                stow_dpkg (dpkg)
            if do_linking:
                prune_spkg (spkg_name, spkg_version(spkg_name))
                print ("Pruning %s" % spkg_name)
            else:
                print ("""  %s [color="green"];""" % spkg_name.upper())

loop_on_spkgs()
print("Don't forget to export PYTHONHOME=%s/local" % sagedir)
#!/usr/bin/python
# -*- coding: utf-8 -*-

# for each spkg name, a list of debian packages which will cover what
# it provides
#
# with an empty list if nothing is needed (!), and a u'unsupported' if
# we don't know yet what we need (or it doesn't exist... or we know
# we're really outdated)
spkg_deps = {
    u'atlas' : [u'libatlas-dev', u'libatlas-base-dev', u'libatlas3gf-base', u'libatlas3-base'],
    u'blas' : [u'libblas-dev', u'libblas3gf'],
    u'boehm_gc': [u'libgc-dev', u'libgc1c2'],
    u'boost' : [u'unsupported'],
    u'cddlib': [u'libcdd-dev', u'libcdd0'],
    u'cephes' : [u'unsupported'],
    u'cliquer': [u'unsupported', u'libcliquer-dev', u'libcliquer1'], # too recent in debian for sage: http://trac.sagemath.org/sage_trac/ticket/12905
    u'conway' : [u'unsupported'],
    u'cvxopt': [u'python-cvxopt'],
    u'cython' : [u'cython'],
    u'docutils' : [u'python-docutils'],
    u'ecl' : [u'ecl'],
    u'eclib' : [u'eclib-tools', 'libec0', 'libec-dev'],
    u'ecm' : [u'libecm-dev', u'libecm0'],
    u'elliptic_curves' : [u'unsupported'],
    u'extcode' : [u'unsupported'],
    u'fflas_ffpack' : [u'fflas-ffpack', u'fflas-ffpack-common', u'fflas-ffpack-dev'],
    u'flint': [u'unsupported'],
    u'flintqs': [u'unsupported'],
    u'freetype': [u'libfreetype6-dev', u'libfreetype6'],
    u'gap' : [u'gap', u'gap-core', u'gap-dev', u'gap-libs', u'gap-prim-groups', u'gap-small-groups', u'gap-trans-groups', u'gap-character-tables', u'gap-table-of-marks'],
    u'gcc' : [u'gfortran'],
    u'gd' : [u'libgd2-xpm-dev', u'libgd2-xpm'],
    u'gdmodule' : [u'python-gd'],
    u'genus2reduction' : [u'genus2reduction'],
    u'gfan' : [u'gfan'],
    u'givaro' : [u'libgivaro-dev', u'libgivaro1'],
    u'glpk' : [u'python-glpk', u'libglpk-dev', u'libglpk0'],
    u'graphs' : [u'unsupported'],
    u'gsl': [u'libgsl0-dev', u'libgsl0ldbl'],
    u'iconv' : [], # it's in the libc
    u'iml' : [u'libiml-dev', u'libiml0'],
    u'ipython': [u'ipython'],
    u'jinja2' : [u'python-jinja2'], # debian has a newer...
    u'jmol' : [u'jmol'],
    u'lapack' : [u'liblapack-dev', u'liblapack3gf'],
    u'lcalc': [u'unsupported'], # debian doesn't have it with the headers
    u'libfplll' : [u'unsupported', u'libfplll-dev', u'libfplll0'], # personal packages, but sage is too ancient http://trac.sagemath.org/sage_trac/ticket/12835
    u'libm4ri' : [u'libm4ri-0.0.20111203', u'libm4ri-dev'], # personal packages
    u'libm4rie' : [u'libm4rie-dev', u'libm4rie-0.0.20111203'], # personal packages
    u'libpng' : [u'libpng12-dev', u'libpng12-0'],
    u'linbox' : [u'unsupported', u'liblinbox-dev', u'liblinbox0'], # personal packages, sage needs to upgrade http://trac.sagemath.org/sage_trac/ticket/12883
    u'lrcalc': [u'unsupported'],
    u'matplotlib' : [u'python-matplotlib'],
    u'maxima' : [u'maxima'],
    u'mercurial' : [u'mercurial'],
    u'mpc': [u'libmpc2', u'libmpc-dev'],
    u'mpfi' : [u'libmpfi-dev', u'libmpfi0'],
    u'mpfr' : [u'libmpfr-dev', u'libmpfr4'],
    u'mpir' : [u'unsupported'],
    u'mpmath' : [u'python-mpmath'],
    u'networkx' : [u'python-networkx'],
    u'ntl' : [u'libntl-dev', u'libntl0'],
    u'numpy': [u'python-numpy'],
    u'palp' : [u'palp'], # debian should get it soon
    u'pari' : [u'libpari-dev', u'pari-gp'],
    u'patch' : [u'patch'],
    u'pexpect' : [u'python-pexpect'],
    u'pil' : [u'python-imaging'],
    u'polybori' : [u'unsupported', u'python-polybori', u'libpolybori-dev', u'libpolybori-0.5.0-0'], # too ancient in debian -- worse, if they're installed, they break us!
    u'polytopes_db' : [u'unsupported'],
    u'ppl' : [u'libppl0.11-dev', u'libppl9'],
    u'pycrypto' : [u'python-crypto'],
    u'pygments' : [u'python-pygments'],
    u'pynac' : [u'libpynac4', 'libpynac-dev'],
    u'python' : [u'python2.7-dev', u'python2.7', u'python2.7-minimal'],
    u'r' : [u'r-base-dev', u'r-base-core', u'r-cran-mass', u'r-cran-lattice', u'r-cran-matrix', u'r-cran-nlme', u'r-cran-survival', u'r-cran-boot', u'r-cran-cluster', u'r-cran-codetools', u'r-cran-foreign', u'r-cran-kernsmooth', u'r-cran-rpart', u'r-cran-class', u'r-cran-nnet', u'r-cran-spatial', u'r-cran-mgcv'],
    u'ratpoints' : [u'unsupported'],
    u'readline' : [u'libreadline6-dev', u'libreadline6'],
    u'rpy2' : [u'python-rpy2'],
    u'rubiks' : [u'unsupported'],
    u'sage' : [u'unsupported'],
    u'sagenb' : [u'unsupported'],
    u'sage_root' : [u'unsupported'],
    u'sage_scripts' : [u'unsupported'],
    u'sagetex' : [u'unsupported'],
    u'scipy' : [u'python-scipy'],
    u'scons' : [u'scons'],
    u'setuptools' : [u'python-setuptools', u'python-pkg-resources'],
    u'singular' : [u'unsupported'],
    u'sphinx' : [u'python-sphinx'],
    u'sqlalchemy' : [u'python-sqlalchemy'],
    u'sqlite' : [u'libsqlite3-dev', u'libsqlite3-0'],
    u'symmetrica' : [u'libsymmetrica-dev', u'libsymmetrica-2.0'],
    u'sympow' : [u'sympow'],
    u'sympy' : [u'python-sympy'],
    u'tachyon' : [u'tachyon'],
    u'termcap' : [], # it's unneeded
    u'zlib' : [u'zlib1g-dev', u'zlib1g'],
    u'zn_poly' : [u'libzn-poly-dev', u'libzn-poly-0.9'],
    u'zodb3' : [u'python-zodb'],
}

Reply to: