def target(result_queue, precision_changed, continue_event): # Change the context in a background thread. Put computed # precisions on a results queue for testing in the main thread. # We use events to pause execution of the background thread # so that we can effectively test that the main thread is # unaffected at that point. try: result_queue.put(("PREC", getcontext().precision)) with precision(20): result_queue.put(("PREC", getcontext().precision)) precision_changed.set() if not continue_event.wait(timeout=SAFETY_TIMEOUT): raise RuntimeError("continue_event not received") result_queue.put(("PREC", getcontext().precision)) except BaseException as e: result_queue.put(("EXC", str(e))) result_queue.put(("DONE", ))
def test_with(self): # check use of contexts in with statements c = Context(emin=-123, emax=456, precision=1729, subnormalize=True, rounding=mpfr.MPFR_RNDU) d = Context(emin=0, emax=10585, precision=20, subnormalize=False, rounding=mpfr.MPFR_RNDD) with c: # check nested with with d: self.assertEqual(getcontext().precision, d.precision) self.assertEqual(getcontext().emin, d.emin) self.assertEqual(getcontext().emax, d.emax) self.assertEqual(getcontext().subnormalize, d.subnormalize) self.assertEqual(getcontext().rounding, d.rounding) # check context is restored on normal exit self.assertEqual(getcontext().precision, c.precision) self.assertEqual(getcontext().emin, c.emin) self.assertEqual(getcontext().emax, c.emax) self.assertEqual(getcontext().subnormalize, c.subnormalize) self.assertEqual(getcontext().rounding, c.rounding) # check context is restored on abnormal exit, and that exceptions # raised within the with block are propagated try: with d: raise ValueError except ValueError: pass else: self.fail('ValueError not propagated from with block') self.assertEqual(getcontext().precision, c.precision) self.assertEqual(getcontext().emin, c.emin) self.assertEqual(getcontext().emax, c.emax) self.assertEqual(getcontext().subnormalize, c.subnormalize) self.assertEqual(getcontext().rounding, c.rounding)
def test_rounding_contexts(self): with RoundTiesToEven: self.assertEqual(getcontext().rounding, ROUND_TIES_TO_EVEN) with RoundTowardPositive: self.assertEqual(getcontext().rounding, ROUND_TOWARD_POSITIVE) with RoundTowardNegative: self.assertEqual(getcontext().rounding, ROUND_TOWARD_NEGATIVE) with RoundTiesToEven: self.assertEqual(getcontext().rounding, ROUND_TIES_TO_EVEN) with RoundAwayFromZero: self.assertEqual(getcontext().rounding, ROUND_AWAY_FROM_ZERO) # Rounding contexts should not affect existing settings for # precision, exponents, etc. original_contexts = [ Context( precision=234, emin=-9999, emax=9999, subnormalize=True, rounding=ROUND_TOWARD_NEGATIVE, ), Context( precision=5, emin=-10, emax=10, subnormalize=False, rounding=ROUND_AWAY_FROM_ZERO, ), ] rounding_contexts = [ RoundTiesToEven, RoundTowardPositive, RoundTowardNegative, RoundTowardZero, RoundAwayFromZero, ] for original_context in original_contexts: for rounding_context in rounding_contexts: with original_context: with rounding_context: self.assertEqual( getcontext().precision, original_context.precision, ) self.assertEqual( getcontext().emin, original_context.emin, ) self.assertEqual( getcontext().emax, original_context.emax, ) self.assertEqual( getcontext().subnormalize, original_context.subnormalize, ) self.assertEqual( getcontext().rounding, rounding_context.rounding, )
def test_context_initialised_in_background_thread(self): # Regression test for mdickinson/bigfloat#78. # Timeout for blocking waits, so that a badly written test or # an unexpected failure mode doesn't cause the whole test suite # to block. SAFETY_TIMEOUT = 10.0 def target(result_queue, precision_changed, continue_event): # Change the context in a background thread. Put computed # precisions on a results queue for testing in the main thread. # We use events to pause execution of the background thread # so that we can effectively test that the main thread is # unaffected at that point. try: result_queue.put(("PREC", getcontext().precision)) with precision(20): result_queue.put(("PREC", getcontext().precision)) precision_changed.set() if not continue_event.wait(timeout=SAFETY_TIMEOUT): raise RuntimeError("continue_event not received") result_queue.put(("PREC", getcontext().precision)) except BaseException as e: result_queue.put(("EXC", str(e))) result_queue.put(("DONE", )) result_queue = queue.Queue() precision_changed = threading.Event() continue_event = threading.Event() default_precision = DefaultContext.precision self.assertEqual(getcontext().precision, default_precision) thread = threading.Thread( target=target, args=(result_queue, precision_changed, continue_event), ) thread.start() try: precision_changed.wait(timeout=SAFETY_TIMEOUT) # At this point, the precision in the background thread has # been changed, but our precision should be unaltered. self.assertEqual(getcontext().precision, default_precision) continue_event.set() finally: thread.join() # Collect messages from the background thread. messages = [] while True: message = result_queue.get(timeout=SAFETY_TIMEOUT) if message[0] == "DONE": break messages.append(message) self.assertEqual( messages, [ ("PREC", DefaultContext.precision), ("PREC", 20), ("PREC", DefaultContext.precision), ], )