Ticket #11602: trac_11602-install-scripts.v3.patch

File trac_11602-install-scripts.v3.patch, 9.7 KB (added by John Palmieri, 11 years ago)
  • sage/misc/dist.py

    # HG changeset patch
    # User J. H. Palmieri <palmieri@math.washington.edu>
    # Date 1310765037 25200
    # Node ID 54f570fbf9d139a9bdd0b02b0af48f4cde59d4e0
    # Parent  9dca3876f46be512d86d82dc0b43468f0ad2c8a4
    #11602: install_scripts should use "$@" instead of $*.
    Also generally clean up this function, including fixing a bug or two.
    
    diff --git a/sage/misc/dist.py b/sage/misc/dist.py
    a b Installing shortcut scripts 
    44
    55import os
    66
    7 from subprocess import Popen, PIPE
     7def install_scripts(directory=None, ignore_existing=False):
     8    r"""
     9    Running ``install_scripts(directory)`` creates scripts in the
     10    given directory that run various software components included with
     11    Sage.  Each of these scripts essentially just runs ``sage --CMD``
     12    where ``CMD`` is also the name of the script:
    813
    9 def install_scripts(bin_directory=None):
    10     r"""
    11     Run this command as
    12     ``install_scripts(bin_directory)`` to create scripts
    13     in the given bin directory that, independently of Sage, run various
    14     software components included with Sage: ['gap', 'gp', 'singular',
    15     'maxima', 'M2', 'kash', 'mwrank', 'ipython', 'hg', 'R']
     14    - 'gap' runs GAP
     15    - 'gp' runs the PARI/GP interpreter
     16    - 'hg' runs Mercurial
     17    - 'ipython' runs IPython
     18    - 'maxima' runs Maxima
     19    - 'mwrank' runs mwrank
     20    - 'R' runs R
     21    - 'singular' runs Singular
     22    - 'kash' runs Kash if it is installed (Kash is an optional Sage
     23      package)
     24    - 'M2' runs Macaulay2 if it is installed (Macaulay2 is an
     25      experimental Sage package)
    1626   
    1727    This command:
    1828   
    19     -  verbosely tell you which scripts it adds, and
     29    -  verbosely tells you which scripts it adds, and
    2030   
    2131    -  will *not* overwrite any scripts you already have in the given
    22        bin directory.
     32       directory.
    2333   
    2434    INPUT:
    25    
    26     -  ``bin_directory`` - string; the directory into
    27        which to put the scripts
    28    
     35
     36    - ``directory`` - string; the directory into which to put the
     37      scripts.  This directory must exist and the user must have write
     38      and execute permissions.
     39
     40    - ``ignore_existing`` - bool (optional, default False): if True,
     41      install script even if another version of the program is in your
     42      path.
     43
    2944    OUTPUT: Verbosely prints what it is doing and creates files in
    30     bin_directory that are world executable and readable.
     45    ``directory`` that are world executable and readable.
    3146   
    3247    .. note::
    3348
    34        You may need to run Sage as root in order to run
    35        ``install_scripts`` successfully, since the user running Sage
    36        will need write permissions on ``bin_directory``.
    37    
     49       You may need to run ``sage`` as ``root`` in order to run
     50       ``install_scripts`` successfully, since the user running
     51       ``sage`` needs write permissions on ``directory``.  Note
     52       that one good candidate for ``directory`` is
     53       ``'/usr/local/bin'``, so from the shell prompt, you could run ::
     54
     55           sudo sage -c "install_scripts('/usr/local/bin')"
     56
     57    .. note::
     58
     59       Running ``install_scripts(directory)`` will be most helpful if
     60       ``directory`` is in your path.
     61
    3862    AUTHORS:
    3963
    4064    - William Stein: code / design
    4165
    4266    - Arthur Gaer: design
    4367
     68    - John Palmieri: revision, 2011-07 (trac ticket #11602)
     69
    4470    EXAMPLES::
    4571
    46         sage: install_scripts(SAGE_TMP)
     72        sage: install_scripts(SAGE_TMP, ignore_existing=True)
    4773        Checking that Sage has the command 'gap' installed
    48         Created script ...
     74        ...
    4975    """
    50     if bin_directory is None:
     76    if directory is None:
    5177        # We do this since the intended user of install_scripts
    5278        # will likely be pretty clueless about how to use Sage or
    5379        # its help system.
    5480        import sagedoc
    5581        print sagedoc.format(install_scripts.__doc__)
    56         print "USAGE: install_scripts('bin directory name')"
     82        print "USAGE: install_scripts('directory')"
    5783        return
    5884   
    59     if not (os.path.exists(bin_directory) and os.path.isdir(bin_directory)):
    60         raise RuntimeError, "'%s' must exist and be a directory"%bin_directory
     85    if not os.path.exists(directory):
     86        print "Error: '%s' does not exist." % directory
     87        return
    6188
    62     for c in ['gap', 'gp', 'singular', 'maxima', 'M2', 'kash', \
    63               'mwrank', 'ipython', 'hg', 'R']:
    64         print "Checking that Sage has the command '%s' installed"%c
    65         p = Popen(['which', c], stdout=PIPE, stderr=PIPE)
    66         path = os.path.realpath(p.communicate()[0].rstrip("\n"))
    67         error = p.wait()
    68         if error:
    69             # the 'which' command came up empty:
    70             print "The command '%s' is not available; not adding shortcut"%c
    71         elif not path.startswith(os.path.realpath(os.environ['SAGE_ROOT'])):
    72             # 'which' returned a path outside of the Sage directory:
    73             # then the command is already installed, and we shouldn't
    74             # install the Sage version:
    75             print "The command '%s' is installed outside of Sage; not adding shortcut"%c
     89    if not os.path.isdir(directory):
     90        print "Error: '%s' is not a directory." % directory
     91        return
     92
     93    if not (os.access(directory, os.W_OK) and os.access(directory, os.X_OK)):
     94        print "Error: you do not have write permission for '%s'." % directory
     95        return
     96
     97    from sage.misc.sage_ostools import have_program
     98    script_created = False
     99    SAGE_ROOT = os.environ['SAGE_ROOT']
     100    SAGE_BIN = os.path.join(SAGE_ROOT, 'local', 'bin')
     101    # See if 'directory' is already in PATH, and then remove
     102    # SAGE_ROOT/local/bin from PATH so that we can later check whether
     103    # cmd is available outside of Sage.
     104    PATH = os.environ['PATH'].split(os.pathsep)
     105    PATH = [d for d in PATH if os.path.exists(d)]
     106    dir_in_path = any([os.path.samefile(directory, d) for d in PATH])
     107    PATH = os.pathsep.join([d for d in PATH if not
     108                            os.path.samefile(d, SAGE_BIN)])
     109    for cmd in ['gap', 'gp', 'hg', 'ipython', 'maxima',
     110              'mwrank', 'R', 'singular', 'M2', 'kash']:
     111        print "Checking that Sage has the command '%s' installed" % cmd
     112        # Check to see if Sage includes cmd.
     113        cmd_inside_sage = have_program(cmd, path=SAGE_BIN)
     114        cmd_outside_sage = have_program(cmd, path=PATH)
     115        if not cmd_inside_sage:
     116            print ("The command '%s' is not available as part " %cmd
     117                   + "of Sage; not creating script.")
     118            print
     119            continue
     120        if cmd_outside_sage:
     121            print "The command '%s' is installed outside of Sage;" % cmd,
     122            if not ignore_existing:
     123                print "not creating script."
     124                print
     125                continue
     126            print "trying to create script anyway..."
    76127        else:
    77             # 'which' returned SAGE_ROOT/local/bin/...: create the
    78             # shortcut if it doesn't exist already:
    79             target = os.path.join(bin_directory, c)
    80             if os.path.exists(target):
    81                 print "The file '%s' already exists; not adding shortcut"%(target)
    82             else:
    83                 o = open(target,'w')
    84                 o.write('#!/bin/sh\n')
    85                 o.write('sage -%s $*\n'%c)
    86                 print "Created script '%s'"%target
    87                 os.system('chmod a+rx %s'%target)
     128            print "Creating script for '%s'..." % cmd
     129        # Install shortcut.
     130        target = os.path.join(directory, cmd)
     131        if os.path.exists(target):
     132            print "The file '%s' already exists; not adding script."%(target)
     133        else:
     134            o = open(target,'w')
     135            o.write('#!/bin/sh\n')
     136            o.write('sage -%s "$@"\n'%cmd)
     137            o.close()
     138            print "Created script '%s'"%target
     139            os.system('chmod a+rx %s'%target)
     140            script_created = True
    88141        print
    89            
    90     print "Finished creating scripts."
    91     print "You need not do this again even if you upgrade or move Sage."
    92     print "The only requirement is that the command 'sage' is in the PATH."
     142
     143    if script_created:
     144        print "Finished creating scripts."
     145        print
     146        print "You need not do this again even if you upgrade or move Sage."
     147        print "The only requirement is that your PATH contains both"
     148        print "'%s' and the directory containing the command 'sage'." % directory
     149        if not dir_in_path:
     150            print
     151            print "Warning: '%s' is not currently in your PATH." % directory
     152            print
     153    else:
     154        print "No scripts created."
  • sage/misc/sage_ostools.py

    diff --git a/sage/misc/sage_ostools.py b/sage/misc/sage_ostools.py
    a b  
    22Miscellaneous operating system functions
    33"""
    44
    5 def have_program(program):
     5def have_program(program, path=None):
    66    """
    77    Return ``True`` if ``program`` is found in the path.
    88
    99    INPUT:
    1010
    11     - ``program`` - a string, the name of the program to check
     11    - ``program`` - a string, the name of the program to check.
     12    - ``path`` - string or None.  If a nonempty string, use this as
     13      the setting for the PATH environment variable.
    1214
    1315    OUTPUT: bool
    1416
    def have_program(program): 
    2931        False
    3032    """
    3133    from subprocess import call, PIPE
     34    import os
    3235    try:
    33         return not call('command -v ' + program, shell=True, stdout=PIPE, stderr=PIPE)
     36        if path:
     37            return not call('command -v %s' % program, shell=True,
     38                            stdout=PIPE, env = {'PATH': path})
     39        else:
     40            return not call('command -v %s' % program, shell=True,
     41                            stdout=PIPE)
    3442    except OSError:
    3543        return False
    36