Ticket #13147: 13147_lazy.patch

File 13147_lazy.patch, 7.5 KB (added by roed, 9 years ago)

Mike Hansen's solution

  • sage/interfaces/cleaner.py

    # HG changeset patch
    # User Mike Hansen <mhansen@gmail.com>
    # Date 1338284389 25200
    # Node ID bb37f43b5feaf166b5835cfccf17235fe6fbd94c
    # Parent  87014ea4c9ead601f74e4d4cb5770111d27093c9
    #12415: Make sage.misc.misc.SAGE_TMP a lazy string
    
    The purpose of this is so that the SAGE_TMP can still reflect the PID
    even after Sage forks.
    
    diff --git a/sage/interfaces/cleaner.py b/sage/interfaces/cleaner.py
    a b  
    1515import os
    1616
    1717import sage.misc.misc as misc
    18 F = '%s/spawned_processes'%misc.SAGE_TMP
    1918
    2019def cleaner(pid, cmd=''):
    2120    if cmd != '':
    2221        cmd = cmd.strip().split()[0]
    2322    # This is safe, since only this process writes to this file.
     23    F = '%s/spawned_processes'%misc.SAGE_TMP
    2424    if os.path.exists(F):
    2525        o = open(F,'a')
    2626    else:
    27         if not os.path.exists(misc.SAGE_TMP):
     27        if not os.path.exists(str(misc.SAGE_TMP)):
    2828            return
    2929        o = open(F,'w')
    3030    o.write('%s %s\n'%(pid, cmd))
  • sage/interfaces/quit.py

    diff --git a/sage/interfaces/quit.py b/sage/interfaces/quit.py
    a b  
    1313################################################################################
    1414
    1515import os
     16from sage.misc.misc import SAGE_TMP
    1617
    1718expect_objects = []
    1819
     
    6364
    6465        sage: sage.interfaces.quit.expect_quitall()
    6566    """
    66     from sage.misc.misc import SAGE_TMP
    67     file = os.path.join(SAGE_TMP, 'spawned_processes')
     67    file = os.path.join(str(SAGE_TMP), 'spawned_processes')
    6868    if not os.path.exists(file):
    6969        return
    7070    for L in open(file).readlines():
  • sage/misc/dist.py

    diff --git a/sage/misc/dist.py b/sage/misc/dist.py
    a b  
    7070
    7171    EXAMPLES::
    7272
    73         sage: install_scripts(SAGE_TMP, ignore_existing=True)
     73        sage: install_scripts(str(SAGE_TMP), ignore_existing=True) # SAGE_TMP is lazy
    7474        Checking that Sage has the command 'gap' installed
    7575        ...
    7676    """
  • sage/misc/misc.py

    diff --git a/sage/misc/misc.py b/sage/misc/misc.py
    a b  
    133133# It is called temp instead of tmp mainly for
    134134# "historical reasons"...
    135135
    136 SAGE_TMP='%s/temp/%s/%s/'%(DOT_SAGE, HOSTNAME, os.getpid())
     136def lazy_string(func):
     137    """
     138    Creates a lazy string that gets its values by evaluating a
     139    function that takes no parameters.
    137140
    138 sage_makedirs(SAGE_TMP)
     141    EXAMPLES::
     142
     143        sage: from sage.misc.misc import lazy_string
     144        sage: def foo(): return 'sage'
     145        sage: s = lazy_string(foo); s
     146        l'sage'
     147        sage: s + 'math'
     148        'sagemath'
     149    """
     150    from .speaklater import make_lazy_string
     151    return make_lazy_string(func)
     152
     153@lazy_string
     154def SAGE_TMP():
     155    d = '%s/temp/%s/%s/'%(DOT_SAGE, HOSTNAME, os.getpid())
     156    sage_makedirs(d)
     157    return d
     158
     159@lazy_string
     160def SPYX_TMP():
     161    return '%s/spyx/'%SAGE_TMP
    139162
    140163SAGE_DATA = '%s/data/'%SAGE_ROOT
    141164SAGE_EXTCODE = '%s/data/extcode/'%SAGE_ROOT
    142 SPYX_TMP = '%s/spyx/'%SAGE_TMP
    143 
    144165
    145166def delete_tmpfiles():
    146167    # !!!If you change this, see also SAGE_ROOT/local/bin/sage-doctest!!!
    147168    import shutil
    148169    try:
    149         if os.path.exists(SAGE_TMP):
    150             shutil.rmtree(SAGE_TMP)
     170        if os.path.exists(str(SAGE_TMP)):
     171            shutil.rmtree(str(SAGE_TMP))
    151172    except OSError, msg:
    152173        print msg
    153174        pass
    154175
    155 SAGE_TMP_INTERFACE='%s/interface/'%SAGE_TMP
    156 sage_makedirs(SAGE_TMP_INTERFACE)
     176@lazy_string
     177def SAGE_TMP_INTERFACE():
     178    d = '%s/interface/'%SAGE_TMP
     179    sage_makedirs(d)
     180    return d
    157181
    158182SAGE_DB = '%s/db'%DOT_SAGE
    159183sage_makedirs(SAGE_DB)
  • new file sage/misc/speaklater.py

    diff --git a/sage/misc/speaklater.py b/sage/misc/speaklater.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2
     3def is_lazy_string(obj):
     4    """Checks if the given object is a lazy string."""
     5    return isinstance(obj, _LazyString)
     6
     7
     8def make_lazy_string(__func, *args, **kwargs):
     9    """Creates a lazy string by invoking func with args."""
     10    return _LazyString(__func, args, kwargs)
     11
     12
     13def make_lazy_gettext(lookup_func):
     14    """Creates a lazy gettext function dispatches to a gettext
     15    function as returned by `lookup_func`.
     16    """
     17    def lazy_gettext(string):
     18        if is_lazy_string(string):
     19            return string
     20        return make_lazy_string(lookup_func(), string)
     21    return lazy_gettext
     22
     23
     24class _LazyString(object):
     25    """Class for strings created by a function call.
     26
     27    The proxy implementation attempts to be as complete as possible, so that
     28    the lazy objects should mostly work as expected, for example for sorting.
     29    """
     30    __slots__ = ('_func', '_args', '_kwargs')
     31
     32    def __init__(self, func, args, kwargs):
     33        self._func = func
     34        self._args = args
     35        self._kwargs = kwargs
     36
     37    value = property(lambda x: x._func(*x._args, **x._kwargs))
     38
     39    def __contains__(self, key):
     40        return key in self.value
     41
     42    def __nonzero__(self):
     43        return bool(self.value)
     44
     45    def __dir__(self):
     46        return dir(unicode)
     47
     48    def __iter__(self):
     49        return iter(self.value)
     50
     51    def __len__(self):
     52        return len(self.value)
     53
     54    def __str__(self):
     55        return str(self.value)
     56
     57    def __unicode__(self):
     58        return unicode(self.value)
     59
     60    def __add__(self, other):
     61        return self.value + other
     62
     63    def __radd__(self, other):
     64        return other + self.value
     65
     66    def __mod__(self, other):
     67        return self.value % other
     68
     69    def __rmod__(self, other):
     70        return other % self.value
     71
     72    def __mul__(self, other):
     73        return self.value * other
     74
     75    def __rmul__(self, other):
     76        return other * self.value
     77
     78    def __lt__(self, other):
     79        return self.value < other
     80
     81    def __le__(self, other):
     82        return self.value <= other
     83
     84    def __eq__(self, other):
     85        return self.value
     86
     87    def __ne__(self, other):
     88        return self.value != other
     89
     90    def __gt__(self, other):
     91        return self.value > other
     92
     93    def __ge__(self, other):
     94        return self.value >= other
     95
     96    def __getattr__(self, name):
     97        if name == '__members__':
     98            return self.__dir__()
     99        return getattr(self.value, name)
     100
     101    def __getstate__(self):
     102        return self._func, self._args, self._kwargs
     103
     104    def __setstate__(self, tup):
     105        self._func, self._args, self._kwargs = tup
     106
     107    def __getitem__(self, key):
     108        return self.value[key]
     109
     110    def __copy__(self):
     111        return self
     112
     113    def __repr__(self):
     114        try:
     115            return 'l' + repr(self.value)
     116        except Exception:
     117            return '<%s broken>' % self.__class__.__name__
     118
     119
     120if __name__ == '__main__':
     121    import doctest
     122    doctest.testmod()
  • sage/tests/cmdline.py

    diff --git a/sage/tests/cmdline.py b/sage/tests/cmdline.py
    a b  
    257257        sage: F = open(script, 'w')
    258258        sage: F.write(s)
    259259        sage: F.close()
    260         sage: os.chdir(SAGE_TMP)
     260        sage: os.chdir(str(SAGE_TMP)) # SAGE_TMP is lazy
    261261        sage: (out, err, ret) = test_executable(["sage", "--preparse", script])
    262262        sage: ret
    263263        0
     
    286286        sage: F.write(s)
    287287        sage: F.close()
    288288        sage: OLD_TESTDIR = os.environ['SAGE_TESTDIR']
    289         sage: os.environ['SAGE_TESTDIR'] = SAGE_TMP
     289        sage: os.environ['SAGE_TESTDIR'] = str(SAGE_TMP) # SAGE_TMP is lazy
    290290        sage: (out, err, ret) = test_executable(["sage", "-t", script])
    291291        sage: ret
    292292        128