Utility functions¶
This module contains various utility functions and classes used in doctesting.
AUTHORS:
- David Roe (2012-03-27) – initial version, based on Robert Bradshaw’s code. 
- class sage.doctest.util.NestedName(base)[source]¶
- Bases: - object- Class used to construct fully qualified names based on indentation level. - EXAMPLES: - sage: from sage.doctest.util import NestedName sage: qname = NestedName('sage.categories.algebras') sage: qname[0] = 'Algebras'; qname sage.categories.algebras.Algebras sage: qname[4] = '__contains__'; qname sage.categories.algebras.Algebras.__contains__ sage: qname[4] = 'ParentMethods' sage: qname[8] = 'from_base_ring'; qname sage.categories.algebras.Algebras.ParentMethods.from_base_ring - >>> from sage.all import * >>> from sage.doctest.util import NestedName >>> qname = NestedName('sage.categories.algebras') >>> qname[Integer(0)] = 'Algebras'; qname sage.categories.algebras.Algebras >>> qname[Integer(4)] = '__contains__'; qname sage.categories.algebras.Algebras.__contains__ >>> qname[Integer(4)] = 'ParentMethods' >>> qname[Integer(8)] = 'from_base_ring'; qname sage.categories.algebras.Algebras.ParentMethods.from_base_ring 
- class sage.doctest.util.RecordingDict(*args, **kwds)[source]¶
- Bases: - dict- This dictionary is used for tracking the dependencies of an example. - This feature allows examples in different doctests to be grouped for better timing data. It’s obtained by recording whenever anything is set or retrieved from this dictionary. - EXAMPLES: - sage: from sage.doctest.util import RecordingDict sage: D = RecordingDict(test=17) sage: D.got set() sage: D['test'] 17 sage: D.got {'test'} sage: D.set set() sage: D['a'] = 1 sage: D['a'] 1 sage: D.set {'a'} sage: D.got {'test'} - >>> from sage.all import * >>> from sage.doctest.util import RecordingDict >>> D = RecordingDict(test=Integer(17)) >>> D.got set() >>> D['test'] 17 >>> D.got {'test'} >>> D.set set() >>> D['a'] = Integer(1) >>> D['a'] 1 >>> D.set {'a'} >>> D.got {'test'} - copy()[source]¶
- Note that set and got are not copied. - EXAMPLES: - sage: from sage.doctest.util import RecordingDict sage: D = RecordingDict(d = 42) sage: D['a'] = 4 sage: D.set {'a'} sage: E = D.copy() sage: E.set set() sage: sorted(E.keys()) ['a', 'd'] - >>> from sage.all import * >>> from sage.doctest.util import RecordingDict >>> D = RecordingDict(d = Integer(42)) >>> D['a'] = Integer(4) >>> D.set {'a'} >>> E = D.copy() >>> E.set set() >>> sorted(E.keys()) ['a', 'd'] 
 - get(name, default=None)[source]¶
- EXAMPLES: - sage: from sage.doctest.util import RecordingDict sage: D = RecordingDict(d = 42) sage: D.get('d') 42 sage: D.got {'d'} sage: D.get('not_here') sage: sorted(list(D.got)) ['d', 'not_here'] - >>> from sage.all import * >>> from sage.doctest.util import RecordingDict >>> D = RecordingDict(d = Integer(42)) >>> D.get('d') 42 >>> D.got {'d'} >>> D.get('not_here') >>> sorted(list(D.got)) ['d', 'not_here'] 
 - start()[source]¶
- We track which variables have been set or retrieved. This function initializes these lists to be empty. - EXAMPLES: - sage: from sage.doctest.util import RecordingDict sage: D = RecordingDict(d = 42) sage: D.set set() sage: D['a'] = 4 sage: D.set {'a'} sage: D.start(); D.set set() - >>> from sage.all import * >>> from sage.doctest.util import RecordingDict >>> D = RecordingDict(d = Integer(42)) >>> D.set set() >>> D['a'] = Integer(4) >>> D.set {'a'} >>> D.start(); D.set set() 
 
- class sage.doctest.util.Timer[source]¶
- Bases: - object- A simple timer. - EXAMPLES: - sage: from sage.doctest.util import Timer sage: Timer() {} sage: TestSuite(Timer()).run() - >>> from sage.all import * >>> from sage.doctest.util import Timer >>> Timer() {} >>> TestSuite(Timer()).run() - annotate(object)[source]¶
- Annotates the given object with the cputime and walltime stored in this timer. - EXAMPLES: - sage: from sage.doctest.util import Timer sage: Timer().start().annotate(EllipticCurve) sage: EllipticCurve.cputime # random 2.817255 sage: EllipticCurve.walltime # random 1332649288.410404 - >>> from sage.all import * >>> from sage.doctest.util import Timer >>> Timer().start().annotate(EllipticCurve) >>> EllipticCurve.cputime # random 2.817255 >>> EllipticCurve.walltime # random 1332649288.410404 
 - start()[source]¶
- Start the timer. - Can be called multiple times to reset the timer. - EXAMPLES: - sage: from sage.doctest.util import Timer sage: Timer().start() {'cputime': ..., 'walltime': ...} - >>> from sage.all import * >>> from sage.doctest.util import Timer >>> Timer().start() {'cputime': ..., 'walltime': ...} 
 - stop()[source]¶
- Stops the timer, recording the time that has passed since it was started. - EXAMPLES: - sage: from sage.doctest.util import Timer sage: import time sage: timer = Timer().start() sage: time.sleep(float(0.5)) sage: timer.stop() {'cputime': ..., 'walltime': ...} - >>> from sage.all import * >>> from sage.doctest.util import Timer >>> import time >>> timer = Timer().start() >>> time.sleep(float(RealNumber('0.5'))) >>> timer.stop() {'cputime': ..., 'walltime': ...} 
 
- sage.doctest.util.count_noun(number, noun, plural=None, pad_number=False, pad_noun=False)[source]¶
- EXAMPLES: - sage: from sage.doctest.util import count_noun sage: count_noun(1, "apple") '1 apple' sage: count_noun(1, "apple", pad_noun=True) '1 apple ' sage: count_noun(1, "apple", pad_number=3) ' 1 apple' sage: count_noun(2, "orange") '2 oranges' sage: count_noun(3, "peach", "peaches") '3 peaches' sage: count_noun(1, "peach", plural='peaches', pad_noun=True) '1 peach ' - >>> from sage.all import * >>> from sage.doctest.util import count_noun >>> count_noun(Integer(1), "apple") '1 apple' >>> count_noun(Integer(1), "apple", pad_noun=True) '1 apple ' >>> count_noun(Integer(1), "apple", pad_number=Integer(3)) ' 1 apple' >>> count_noun(Integer(2), "orange") '2 oranges' >>> count_noun(Integer(3), "peach", "peaches") '3 peaches' >>> count_noun(Integer(1), "peach", plural='peaches', pad_noun=True) '1 peach ' 
- sage.doctest.util.dict_difference(self, other)[source]¶
- Return a dict with all key-value pairs occurring in - selfbut not in- other.- EXAMPLES: - sage: from sage.doctest.util import dict_difference sage: d1 = {1: 'a', 2: 'b', 3: 'c'} sage: d2 = {1: 'a', 2: 'x', 4: 'c'} sage: dict_difference(d2, d1) {2: 'x', 4: 'c'} - >>> from sage.all import * >>> from sage.doctest.util import dict_difference >>> d1 = {Integer(1): 'a', Integer(2): 'b', Integer(3): 'c'} >>> d2 = {Integer(1): 'a', Integer(2): 'x', Integer(4): 'c'} >>> dict_difference(d2, d1) {2: 'x', 4: 'c'} - sage: from sage.doctest.control import DocTestDefaults sage: D1 = DocTestDefaults() sage: D2 = DocTestDefaults(foobar='hello', timeout=100) sage: dict_difference(D2.__dict__, D1.__dict__) {'foobar': 'hello', 'timeout': 100} - >>> from sage.all import * >>> from sage.doctest.control import DocTestDefaults >>> D1 = DocTestDefaults() >>> D2 = DocTestDefaults(foobar='hello', timeout=Integer(100)) >>> dict_difference(D2.__dict__, D1.__dict__) {'foobar': 'hello', 'timeout': 100} 
- sage.doctest.util.ensure_interruptible_after(*args, **kwds)[source]¶
- Helper function for doctesting to ensure that the code is interruptible after a certain amount of time. This should only be used for internal doctesting purposes. - EXAMPLES: - sage: from sage.doctest.util import ensure_interruptible_after sage: with ensure_interruptible_after(1) as data: sleep(3) - >>> from sage.all import * >>> from sage.doctest.util import ensure_interruptible_after >>> with ensure_interruptible_after(Integer(1)) as data: sleep(Integer(3)) - as datais optional, but if it is used, it will contain a few useful values:- sage: data # abs tol 1 {'alarm_raised': True, 'elapsed': 1.0} - >>> from sage.all import * >>> data # abs tol 1 {'alarm_raised': True, 'elapsed': 1.0} - max_wait_after_interruptcan be passed if the function may take longer than usual to be interrupted:- sage: # needs sage.misc.cython sage: cython(r''' ....: from posix.time cimport clock_gettime, CLOCK_REALTIME, timespec, time_t ....: from cysignals.signals cimport sig_check ....: ....: cpdef void uninterruptible_sleep(double seconds): ....: cdef timespec start_time, target_time ....: clock_gettime(CLOCK_REALTIME, &start_time) ....: ....: cdef time_t floor_seconds = <time_t>seconds ....: target_time.tv_sec = start_time.tv_sec + floor_seconds ....: target_time.tv_nsec = start_time.tv_nsec + <long>((seconds - floor_seconds) * 1e9) ....: if target_time.tv_nsec >= 1000000000: ....: target_time.tv_nsec -= 1000000000 ....: target_time.tv_sec += 1 ....: ....: while True: ....: clock_gettime(CLOCK_REALTIME, &start_time) ....: if start_time.tv_sec > target_time.tv_sec or (start_time.tv_sec == target_time.tv_sec and start_time.tv_nsec >= target_time.tv_nsec): ....: break ....: ....: cpdef void check_interrupt_only_occasionally(): ....: for i in range(10): ....: uninterruptible_sleep(0.8) ....: sig_check() ....: ''') sage: with ensure_interruptible_after(1): # not passing max_wait_after_interrupt will raise an error ....: check_interrupt_only_occasionally() Traceback (most recent call last): ... RuntimeError: Function is not interruptible within 1.0000 seconds, only after 1.60... seconds sage: with ensure_interruptible_after(1, max_wait_after_interrupt=0.9): ....: check_interrupt_only_occasionally() - >>> from sage.all import * >>> # needs sage.misc.cython >>> cython(r''' ... from posix.time cimport clock_gettime, CLOCK_REALTIME, timespec, time_t ... from cysignals.signals cimport sig_check ....: >>> cpdef void uninterruptible_sleep(double seconds): ... cdef timespec start_time, target_time ... clock_gettime(CLOCK_REALTIME, &start_time) ....: >>> cdef time_t floor_seconds = <time_t>seconds ... target_time.tv_sec = start_time.tv_sec + floor_seconds ... target_time.tv_nsec = start_time.tv_nsec + <long>((seconds - floor_seconds) * RealNumber('1e9')) ... if target_time.tv_nsec >= Integer(1000000000): ... target_time.tv_nsec -= Integer(1000000000) ... target_time.tv_sec += Integer(1) ....: >>> while True: ... clock_gettime(CLOCK_REALTIME, &start_time) ... if start_time.tv_sec > target_time.tv_sec or (start_time.tv_sec == target_time.tv_sec and start_time.tv_nsec >= target_time.tv_nsec): ... break ....: >>> cpdef void check_interrupt_only_occasionally(): ... for i in range(Integer(10)): ... uninterruptible_sleep(RealNumber('0.8')) ... sig_check() ... ''') >>> with ensure_interruptible_after(Integer(1)): # not passing max_wait_after_interrupt will raise an error ... check_interrupt_only_occasionally() Traceback (most recent call last): ... RuntimeError: Function is not interruptible within 1.0000 seconds, only after 1.60... seconds >>> with ensure_interruptible_after(Integer(1), max_wait_after_interrupt=RealNumber('0.9')): ... check_interrupt_only_occasionally() 
- sage.doctest.util.make_recording_dict(D, st, gt)[source]¶
- Auxiliary function for pickling. - EXAMPLES: - sage: from sage.doctest.util import make_recording_dict sage: D = make_recording_dict({'a':4,'d':42},set(),set(['not_here'])) sage: sorted(D.items()) [('a', 4), ('d', 42)] sage: D.got {'not_here'} - >>> from sage.all import * >>> from sage.doctest.util import make_recording_dict >>> D = make_recording_dict({'a':Integer(4),'d':Integer(42)},set(),set(['not_here'])) >>> sorted(D.items()) [('a', 4), ('d', 42)] >>> D.got {'not_here'}