Ticket #13147: trac_13147-rebased-to-13681.patch

File trac_13147-rebased-to-13681.patch, 15.3 KB (added by jhpalmieri, 8 years ago)
  • new file sage/misc/lazy_string.py

    # HG changeset patch
    # User David Roe <roed.math@gmail.com>
    # Date 1342077400 14400
    # Node ID 58bdd1202f35c285724b839becc83aa19c049fed
    # Parent  0bf4c275a8744e72e18d541dbf9daeceae2719e1
    #13147: adds lazy strings and makes SAGE_TMP lazy.
    
    diff --git a/sage/misc/lazy_string.py b/sage/misc/lazy_string.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3Lazy strings.
     4
     5Based on speaklater: https://github.com/mitsuhiko/speaklater.
     6
     7A lazy string is an object that behaves almost exactly like a string
     8but where the value is not computed until needed.  To define a lazy
     9string you specify a function that produces a string together with the
     10appropriate arguments for that function.  Sage uses lazy strings in
     11:mod:`sage.misc.misc` so that the filenames for SAGE_TMP (which
     12depends on the pid of the process running Sage) are not computed when
     13importing the Sage library.  This means that when the doctesting code
     14imports the Sage library and then forks, the variable SAGE_TMP depends
     15on the new pid rather than the old one.
     16
     17EXAMPLES::
     18
     19    sage: from sage.misc.lazy_string import lazy_string
     20    sage: L = []
     21    sage: s = lazy_string(lambda x: str(len(x)), L)
     22    sage: L.append(5)
     23    sage: s
     24    l'1'
     25
     26Note that the function is recomputed each time::
     27
     28    sage: L.append(6)
     29    sage: s
     30    l'2'
     31"""
     32
     33#Copyright (c) 2009 by Armin Ronacher.
     34#
     35#Some rights reserved.
     36#
     37#Redistribution and use in source and binary forms, with or without
     38#modification, are permitted provided that the following conditions are
     39#met:
     40#
     41#    * Redistributions of source code must retain the above copyright
     42#      notice, this list of conditions and the following disclaimer.
     43#
     44#    * Redistributions in binary form must reproduce the above
     45#      copyright notice, this list of conditions and the following
     46#      disclaimer in the documentation and/or other materials provided
     47#      with the distribution.
     48#
     49#    * The names of the contributors may not be used to endorse or
     50#      promote products derived from this software without specific
     51#      prior written permission.
     52#
     53#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     54#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     55#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     56#A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     57#OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     58#SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     59#LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     60#DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     61#THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     62#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     63#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     64
     65import types
     66
     67def is_lazy_string(obj):
     68    """
     69    Checks if the given object is a lazy string.
     70
     71    EXAMPLES::
     72
     73        sage: from sage.misc.lazy_string import lazy_string, is_lazy_string
     74        sage: f = lambda: "laziness"
     75        sage: s = lazy_string(f)
     76        sage: is_lazy_string(s)
     77        True
     78    """
     79    return isinstance(obj, _LazyString)
     80
     81def lazy_string(func, *args, **kwargs):
     82    """
     83    Creates a lazy string by invoking func with args.
     84
     85    EXAMPLES::
     86
     87        sage: from sage.misc.lazy_string import lazy_string
     88        sage: f = lambda: "laziness"
     89        sage: s = lazy_string(f); s
     90        l'laziness'
     91    """
     92    return _LazyString(func, args, kwargs)
     93
     94def _make_lazy_string(ftype, fpickle, args, kwargs):
     95    """
     96    Used for pickling.
     97
     98    EXAMPLES::
     99
     100        sage: from sage.misc.lazy_string import _make_lazy_string
     101        sage: s = _make_lazy_string(None, lambda: "laziness", (), {})
     102        sage: s
     103        l'laziness'
     104    """
     105    if ftype == 'func':
     106        from sage.misc.fpickle import unpickle_function
     107        f = unpickle_function(fpickle)
     108    else:
     109        f = fpickle
     110    return _LazyString(f, args, kwargs)
     111
     112class _LazyString(object):
     113    """
     114    Class for strings created by a function call.
     115
     116    The proxy implementation attempts to be as complete as possible, so that
     117    the lazy objects should mostly work as expected, for example for sorting.
     118
     119    EXAMPLES::
     120
     121        sage: from sage.misc.lazy_string import lazy_string
     122        sage: f = lambda x: "laziness in the " + repr(x)
     123        sage: s = lazy_string(f, ZZ); s
     124        l'laziness in the Integer Ring'
     125    """
     126    __slots__ = ('_func', '_args', '_kwargs')
     127
     128    def __init__(self, func, args, kwargs):
     129        """
     130        EXAMPLES::
     131
     132            sage: from sage.misc.lazy_string import lazy_string
     133            sage: f = lambda x: "laziness" + repr(x)
     134            sage: s = lazy_string(f, 5); s
     135            l'laziness5'
     136        """
     137        self._func = func
     138        self._args = args
     139        self._kwargs = kwargs
     140
     141    value = property(lambda x: x._func(*x._args, **x._kwargs))
     142
     143    def __contains__(self, key):
     144        """
     145        EXAMPLES::
     146
     147            sage: from sage.misc.lazy_string import lazy_string
     148            sage: f = lambda: "laziness"
     149            sage: s = lazy_string(f)
     150            sage: 'zi' in s
     151            True
     152            sage: 'ni' in s
     153            False
     154        """
     155        return key in self.value
     156
     157    def __nonzero__(self):
     158        """
     159        EXAMPLES::
     160
     161            sage: from sage.misc.lazy_string import lazy_string
     162            sage: f = lambda: "laziness"
     163            sage: bool(lazy_string(f))
     164            True
     165            sage: f = lambda: ""
     166            sage: bool(lazy_string(f))
     167            False
     168        """
     169        return bool(self.value)
     170
     171    def __dir__(self):
     172        """
     173        We assume that the underlying value provides the methods of a
     174        unicode string.
     175
     176        EXAMPLES::
     177
     178            sage: from sage.misc.lazy_string import lazy_string
     179            sage: f = lambda: "laziness"
     180            sage: s = lazy_string(f)
     181            sage: "split" in dir(s) # indirect doctest
     182            True
     183        """
     184        return dir(unicode)
     185
     186    def __iter__(self):
     187        """
     188        EXAMPLES::
     189
     190            sage: from sage.misc.lazy_string import lazy_string
     191            sage: f = lambda: "laziness"
     192            sage: s = lazy_string(f)
     193            sage: "".join(list(s)) # indirect doctest
     194            'laziness'
     195        """
     196        return iter(self.value)
     197
     198    def __len__(self):
     199        """
     200        EXAMPLES::
     201
     202            sage: from sage.misc.lazy_string import lazy_string
     203            sage: f = lambda: "laziness"
     204            sage: s = lazy_string(f)
     205            sage: len(s)
     206            8
     207        """
     208        return len(self.value)
     209
     210    def __str__(self):
     211        """
     212        EXAMPLES::
     213
     214            sage: from sage.misc.lazy_string import lazy_string
     215            sage: f = lambda: "laziness"
     216            sage: s = lazy_string(f)
     217            sage: str(s) # indirect doctest
     218            'laziness'
     219        """
     220        return str(self.value)
     221
     222    def __unicode__(self):
     223        """
     224        EXAMPLES::
     225
     226            sage: from sage.misc.lazy_string import lazy_string
     227            sage: f = lambda: "laziness"
     228            sage: s = lazy_string(f)
     229            sage: unicode(s) # indirect doctest
     230            u'laziness'
     231        """
     232        return unicode(self.value)
     233
     234    def __add__(self, other):
     235        """
     236        EXAMPLES::
     237
     238            sage: from sage.misc.lazy_string import lazy_string
     239            sage: f = lambda: "laziness"
     240            sage: s = lazy_string(f)
     241            sage: s + " supreme"
     242            'laziness supreme'
     243        """
     244        return self.value + other
     245
     246    def __radd__(self, other):
     247        """
     248        EXAMPLES::
     249
     250            sage: from sage.misc.lazy_string import lazy_string
     251            sage: f = lambda: "laziness"
     252            sage: s = lazy_string(f)
     253            sage: "no " + s
     254            'no laziness'
     255        """
     256        return other + self.value
     257
     258    def __mod__(self, other):
     259        """
     260        EXAMPLES::
     261
     262            sage: from sage.misc.lazy_string import lazy_string
     263            sage: f = lambda: "laz%sss"
     264            sage: s = lazy_string(f)
     265            sage: s % "ine"
     266            'laziness'
     267        """
     268        return self.value % other
     269
     270    def __rmod__(self, other):
     271        """
     272        EXAMPLES::
     273
     274            sage: from sage.misc.lazy_string import lazy_string
     275            sage: f = lambda: "ine"
     276            sage: s = lazy_string(f)
     277            sage: "laz%sss" % s
     278            'laziness'
     279        """
     280        return other % self.value
     281
     282    def __mul__(self, other):
     283        """
     284        EXAMPLES::
     285
     286            sage: from sage.misc.lazy_string import lazy_string
     287            sage: f = lambda: "laziness"
     288            sage: s = lazy_string(f)
     289            sage: s * 2
     290            'lazinesslaziness'
     291        """
     292        return self.value * other
     293
     294    def __rmul__(self, other):
     295        """
     296        EXAMPLES::
     297
     298            sage: from sage.misc.lazy_string import lazy_string
     299            sage: f = lambda: "laziness"
     300            sage: s = lazy_string(f)
     301            sage: 2 * s
     302            'lazinesslaziness'
     303        """
     304        return other * self.value
     305
     306    def __lt__(self, other):
     307        """
     308        EXAMPLES::
     309
     310            sage: from sage.misc.lazy_string import lazy_string
     311            sage: f = lambda: "laziness"
     312            sage: s = lazy_string(f)
     313            sage: s < 'laziness'
     314            False
     315            sage: s < 'azi'
     316            False
     317            sage: s < s
     318            False
     319        """
     320        return self.value < other
     321
     322    def __le__(self, other):
     323        """
     324        EXAMPLES::
     325
     326            sage: from sage.misc.lazy_string import lazy_string
     327            sage: f = lambda: "laziness"
     328            sage: s = lazy_string(f)
     329            sage: s <= 'laziness'
     330            True
     331            sage: s <= 'azi'
     332            False
     333            sage: s <= s
     334            True
     335        """
     336        return self.value <= other
     337
     338    def __eq__(self, other):
     339        """
     340        EXAMPLES::
     341
     342            sage: from sage.misc.lazy_string import lazy_string
     343            sage: f = lambda: "laziness"
     344            sage: s = lazy_string(f)
     345            sage: s == 'laziness'
     346            True
     347            sage: s == 'azi'
     348            False
     349            sage: s == s
     350            True
     351        """
     352        return self.value == other
     353
     354    def __ne__(self, other):
     355        """
     356        EXAMPLES::
     357
     358            sage: from sage.misc.lazy_string import lazy_string
     359            sage: f = lambda: "laziness"
     360            sage: s = lazy_string(f)
     361            sage: s != 'laziness'
     362            False
     363            sage: s != 'azi'
     364            True
     365            sage: s != s
     366            False
     367        """
     368        return self.value != other
     369
     370    def __gt__(self, other):
     371        """
     372        EXAMPLES::
     373
     374            sage: from sage.misc.lazy_string import lazy_string
     375            sage: f = lambda: "laziness"
     376            sage: s = lazy_string(f)
     377            sage: s > 'laziness'
     378            False
     379            sage: s > 'azi'
     380            True
     381            sage: s > s
     382            False
     383        """
     384        return self.value > other
     385
     386    def __ge__(self, other):
     387        """
     388        EXAMPLES::
     389
     390            sage: from sage.misc.lazy_string import lazy_string
     391            sage: f = lambda: "laziness"
     392            sage: s = lazy_string(f)
     393            sage: s >= 'laziness'
     394            True
     395            sage: s >= 'azi'
     396            True
     397            sage: s >= s
     398            True
     399        """
     400        return self.value >= other
     401
     402    def __getattr__(self, name):
     403        """
     404        We pass attribute lookup through to the underlying value.
     405
     406        EXAMPLES::
     407
     408            sage: from sage.misc.lazy_string import lazy_string
     409            sage: f = lambda: "laziness"
     410            sage: s = lazy_string(f)
     411            sage: s.endswith('ess')
     412            True
     413            sage: s.find('i')
     414            3
     415        """
     416        if name == '__members__':
     417            return self.__dir__()
     418        return getattr(self.value, name)
     419
     420    def __reduce__(self):
     421        """
     422        Pickling.
     423
     424        EXAMPLES::
     425
     426            sage: from sage.misc.lazy_string import lazy_string
     427            sage: f = lambda: "laziness"
     428            sage: s = lazy_string(f)
     429            sage: TestSuite(s).run() # indirect doctest
     430        """
     431        import types
     432        if isinstance(self._func, types.FunctionType):
     433            from sage.misc.fpickle import pickle_function
     434            f = pickle_function(self._func)
     435            ftype = 'func'
     436        else:
     437            f = self.func
     438            ftype = None
     439        return _make_lazy_string, (ftype, f, self._args, self._kwargs)
     440
     441    def __getitem__(self, key):
     442        """
     443        EXAMPLES::
     444
     445            sage: from sage.misc.lazy_string import lazy_string
     446            sage: f = lambda: "laziness"
     447            sage: s = lazy_string(f)
     448            sage: s[4]
     449            'n'
     450        """
     451        return self.value[key]
     452
     453    def __copy__(self):
     454        """
     455        EXAMPLES::
     456
     457            sage: from sage.misc.lazy_string import lazy_string
     458            sage: f = lambda: "laziness"
     459            sage: s = lazy_string(f)
     460            sage: copy(s) is s
     461            True
     462        """
     463        return self
     464
     465    def __repr__(self):
     466        """
     467        EXAMPLES::
     468
     469            sage: from sage.misc.lazy_string import lazy_string
     470            sage: f = lambda: "laziness"
     471            sage: s = lazy_string(f)
     472            sage: s # indirect doctest
     473            l'laziness'
     474        """
     475        try:
     476            return 'l' + repr(self.value)
     477        except Exception:
     478            return '<%s broken>' % self.__class__.__name__
  • sage/misc/misc.py

    diff --git a/sage/misc/misc.py b/sage/misc/misc.py
    a b Check the fix from trac #8323:: 
    3737from warnings import warn
    3838import operator, os, stat, socket, sys, signal, time, weakref, resource, math
    3939import sage.misc.prandom as random
     40from lazy_string import lazy_string
    4041
    4142from sage.misc.temporary_file import tmp_dir, tmp_filename, delete_tmpfiles
    4243
    if _mode != _desired_mode: 
    137138# Next we create the Sage temporary directory.
    138139#################################################
    139140
    140 SAGE_TMP = os.path.join(DOT_SAGE, 'tmp', HOSTNAME, str(os.getpid()))
    141 sage_makedirs(SAGE_TMP)
     141@lazy_string
     142def SAGE_TMP():
     143    """
     144    EXAMPLES::
    142145
    143 SPYX_TMP = os.path.join(SAGE_TMP, 'spyx')
     146        sage: from sage.misc.misc import SAGE_TMP
     147        sage: SAGE_TMP
     148        l'.../temp/...'
     149    """
     150    d = os.path.join(DOT_SAGE, 'temp', HOSTNAME, str(os.getpid()))
     151    sage_makedirs(d)
     152    return d
    144153
    145 SAGE_TMP_INTERFACE = os.path.join(SAGE_TMP, 'interface')
    146 sage_makedirs(SAGE_TMP_INTERFACE)
     154@lazy_string
     155def SPYX_TMP():
     156    """
     157    EXAMPLES::
     158        sage: from sage.misc.misc import SPYX_TMP
     159        sage: SPYX_TMP
     160        l'.../temp/.../spyx'
     161    """
     162    return os.path.join(SAGE_TMP, 'spyx')
     163
     164@lazy_string
     165def SAGE_TMP_INTERFACE():
     166    """
     167    EXAMPLES::
     168
     169        sage: from sage.misc.misc import SAGE_TMP_INTERFACE
     170        sage: SAGE_TMP_INTERFACE
     171        l'.../temp/.../interface'
     172    """
     173    d = os.path.join(SAGE_TMP, 'interface')
     174    sage_makedirs(d)
     175    return d
    147176
    148177SAGE_DB = os.path.join(DOT_SAGE, 'db')
    149178sage_makedirs(SAGE_DB)