##// END OF EJS Templates
add `float_precision` trait to PlainTextFormatter...
MinRK -
Show More
@@ -20,6 +20,7 b' Authors:'
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 # Stdlib imports
22 # Stdlib imports
23 import sys
23 import abc
24 import abc
24 # We must use StringIO, as cStringIO doesn't handle unicode properly.
25 # We must use StringIO, as cStringIO doesn't handle unicode properly.
25 from StringIO import StringIO
26 from StringIO import StringIO
@@ -27,7 +28,7 b' from StringIO import StringIO'
27 # Our own imports
28 # Our own imports
28 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
29 from IPython.external import pretty
30 from IPython.external import pretty
30 from IPython.utils.traitlets import Bool, Dict, Int, Str
31 from IPython.utils.traitlets import Bool, Dict, Int, Str, CStr
31
32
32
33
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
@@ -353,12 +354,64 b' class PlainTextFormatter(BaseFormatter):'
353 # The newline character.
354 # The newline character.
354 newline = Str('\n', config=True)
355 newline = Str('\n', config=True)
355
356
357 # format-string for pprinting floats
358 float_format = Str('%r')
359 # setter for float precision, either int or direct format-string
360 float_precision = CStr('', config=True)
361
362 def _float_precision_changed(self, name, old, new):
363 """float_precision changed, set float_format accordingly.
364
365 float_precision can be set by int or str.
366 This will set float_format, after interpreting input.
367 If numpy has been imported, numpy print precision will also be set.
368
369 integer `n` sets format to '%.nf', otherwise, format set directly.
370
371 An empty string returns to defaults (repr for float, 8 for numpy).
372
373 This parameter can be set via the '%precision' magic.
374 """
375
376 if '%' in new:
377 # got explicit format string
378 fmt = new
379 try:
380 fmt%3.14159
381 except Exception:
382 raise ValueError("Precision must be int or format string, not %r"%new)
383 elif new:
384 # otherwise, should be an int
385 try:
386 i = int(new)
387 assert i >= 0
388 except ValueError:
389 raise ValueError("Precision must be int or format string, not %r"%new)
390 except AssertionError:
391 raise ValueError("int precision must be non-negative, not %r"%i)
392
393 fmt = '%%.%if'%i
394 if 'numpy' in sys.modules:
395 # set numpy precision if it has been imported
396 import numpy
397 numpy.set_printoptions(precision=i)
398 else:
399 # default back to repr
400 fmt = '%r'
401 if 'numpy' in sys.modules:
402 import numpy
403 # numpy default is 8
404 numpy.set_printoptions(precision=8)
405 self.float_format = fmt
406
356 # Use the default pretty printers from IPython.external.pretty.
407 # Use the default pretty printers from IPython.external.pretty.
357 def _singleton_printers_default(self):
408 def _singleton_printers_default(self):
358 return pretty._singleton_pprinters.copy()
409 return pretty._singleton_pprinters.copy()
359
410
360 def _type_printers_default(self):
411 def _type_printers_default(self):
361 return pretty._type_pprinters.copy()
412 d = pretty._type_pprinters.copy()
413 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
414 return d
362
415
363 def _deferred_printers_default(self):
416 def _deferred_printers_default(self):
364 return pretty._deferred_type_pprinters.copy()
417 return pretty._deferred_type_pprinters.copy()
@@ -3478,58 +3478,33 b' Defaulting color scheme to \'NoColor\'"""'
3478 In [1]: from math import pi
3478 In [1]: from math import pi
3479
3479
3480 In [2]: %precision 3
3480 In [2]: %precision 3
3481 Out[2]: '%.3f'
3481
3482
3482 In [3]: pi
3483 In [3]: pi
3483 Out[3]: 3.142
3484 Out[3]: 3.142
3484
3485
3485 In [4]: %precision %i
3486 In [4]: %precision %i
3487 Out[4]: '%i'
3486
3488
3487 In [5]: pi
3489 In [5]: pi
3488 Out[5]: 3
3490 Out[5]: 3
3489
3491
3490 In [6]: %precision %e
3492 In [6]: %precision %e
3493 Out[6]: '%e'
3491
3494
3492 In [7]: pi**10
3495 In [7]: pi**10
3493 Out[7]: 9.364805e+04
3496 Out[7]: 9.364805e+04
3494
3497
3495 In [8]: %precision
3498 In [8]: %precision
3499 Out[8]: '%r'
3496
3500
3497 In [9]: pi**10
3501 In [9]: pi**10
3498 Out[9]: 93648.047476082982
3502 Out[9]: 93648.047476082982
3499
3503
3500 """
3504 """
3501
3505
3502 if '%' in s:
3503 # got explicit format string
3504 fmt = s
3505 try:
3506 fmt%3.14159
3507 except Exception:
3508 raise ValueError("Precision must be int or format string, not %r"%s)
3509 elif s:
3510 # otherwise, should be an int
3511 try:
3512 i = int(s)
3513 assert i >= 0
3514 except (ValueError, AssertionError):
3515 raise ValueError("Precision must be non-negative int or format string, not %r"%s)
3516
3517 fmt = '%%.%if'%i
3518 if 'numpy' in sys.modules:
3519 import numpy
3520 numpy.set_printoptions(precision=i)
3521 else:
3522 # default back to repr
3523 fmt = '%r'
3524 if 'numpy' in sys.modules:
3525 import numpy
3526 # numpy default is 8
3527 numpy.set_printoptions(precision=8)
3528
3529 def _pretty_float(obj,p,cycle):
3530 p.text(fmt%obj)
3531
3532 ptformatter = self.shell.display_formatter.formatters['text/plain']
3506 ptformatter = self.shell.display_formatter.formatters['text/plain']
3533 ptformatter.for_type(float, _pretty_float)
3507 ptformatter.float_precision = s
3508 return ptformatter.float_format
3534
3509
3535 # end Magic
3510 # end Magic
@@ -1,9 +1,15 b''
1 """Tests for the Formatters.
1 """Tests for the Formatters.
2 """
2 """
3
3
4 from math import pi
5
6 try:
7 import numpy
8 except:
9 numpy = None
4 import nose.tools as nt
10 import nose.tools as nt
5
11
6 from IPython.core.formatters import FormatterABC, DefaultFormatter
12 from IPython.core.formatters import FormatterABC, PlainTextFormatter
7
13
8 class A(object):
14 class A(object):
9 def __repr__(self):
15 def __repr__(self):
@@ -17,7 +23,7 b' def foo_printer(obj, pp, cycle):'
17 pp.text('foo')
23 pp.text('foo')
18
24
19 def test_pretty():
25 def test_pretty():
20 f = DefaultFormatter()
26 f = PlainTextFormatter()
21 f.for_type(A, foo_printer)
27 f.for_type(A, foo_printer)
22 nt.assert_equals(f(A()), 'foo')
28 nt.assert_equals(f(A()), 'foo')
23 nt.assert_equals(f(B()), 'foo')
29 nt.assert_equals(f(B()), 'foo')
@@ -26,5 +32,43 b' def test_pretty():'
26 nt.assert_equals(f(B()), 'B()')
32 nt.assert_equals(f(B()), 'B()')
27
33
28 def test_deferred():
34 def test_deferred():
29 f = DefaultFormatter()
35 f = PlainTextFormatter()
36
37 def test_precision():
38 """test various values for float_precision."""
39 f = PlainTextFormatter()
40 nt.assert_equals(f(pi), repr(pi))
41 f.float_precision = 0
42 if numpy:
43 po = numpy.get_printoptions()
44 nt.assert_equals(po['precision'], 0)
45 nt.assert_equals(f(pi), '3')
46 f.float_precision = 2
47 if numpy:
48 po = numpy.get_printoptions()
49 nt.assert_equals(po['precision'], 2)
50 nt.assert_equals(f(pi), '3.14')
51 f.float_precision = '%g'
52 if numpy:
53 po = numpy.get_printoptions()
54 nt.assert_equals(po['precision'], 2)
55 nt.assert_equals(f(pi), '3.14159')
56 f.float_precision = '%e'
57 nt.assert_equals(f(pi), '3.141593e+00')
58 f.float_precision = ''
59 if numpy:
60 po = numpy.get_printoptions()
61 nt.assert_equals(po['precision'], 8)
62 nt.assert_equals(f(pi), repr(pi))
63
64 def test_bad_precision():
65 """test various invalid values for float_precision."""
66 f = PlainTextFormatter()
67 def set_fp(p):
68 f.float_precision=p
69 nt.assert_raises(ValueError, set_fp, '%')
70 nt.assert_raises(ValueError, set_fp, '%.3f%i')
71 nt.assert_raises(ValueError, set_fp, 'foo')
72 nt.assert_raises(ValueError, set_fp, -1)
73
30
74
@@ -387,3 +387,22 b' def doctest_who():'
387 In [7]: %who_ls
387 In [7]: %who_ls
388 Out[7]: ['alpha', 'beta']
388 Out[7]: ['alpha', 'beta']
389 """
389 """
390
391 def doctest_precision():
392 """doctest for %precision
393
394 In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain']
395
396 In [2]: %precision 5
397 Out[2]: '%.5f'
398
399 In [3]: f.float_format
400 Out[3]: '%.5f'
401
402 In [4]: %precision %e
403 Out[4]: '%e'
404
405 In [5]: f(3.1415927)
406 Out[5]: '3.141593e+00'
407 """
408
General Comments 0
You need to be logged in to leave comments. Login now