##// END OF EJS Templates
Add ObjectName and DottedObjectName trait types for referring to Python identifiers.
Thomas Kluyver -
Show More
@@ -28,7 +28,7 b' from StringIO import StringIO'
28 # Our own imports
28 # Our own imports
29 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
30 from IPython.lib import pretty
30 from IPython.lib import pretty
31 from IPython.utils.traitlets import Bool, Dict, Int, Unicode, CUnicode
31 from IPython.utils.traitlets import Bool, Dict, Int, Unicode, CUnicode, ObjectName
32
32
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
@@ -195,7 +195,7 b' class BaseFormatter(Configurable):'
195
195
196 enabled = Bool(True, config=True)
196 enabled = Bool(True, config=True)
197
197
198 print_method = Unicode('__repr__')
198 print_method = ObjectName('__repr__')
199
199
200 # The singleton printers.
200 # The singleton printers.
201 # Maps the IDs of the builtin singleton objects to the format functions.
201 # Maps the IDs of the builtin singleton objects to the format functions.
@@ -344,7 +344,7 b' class PlainTextFormatter(BaseFormatter):'
344 enabled = Bool(True, config=False)
344 enabled = Bool(True, config=False)
345
345
346 # Look for a _repr_pretty_ methods to use for pretty printing.
346 # Look for a _repr_pretty_ methods to use for pretty printing.
347 print_method = Unicode('_repr_pretty_')
347 print_method = ObjectName('_repr_pretty_')
348
348
349 # Whether to pretty-print or not.
349 # Whether to pretty-print or not.
350 pprint = Bool(True, config=True)
350 pprint = Bool(True, config=True)
@@ -456,7 +456,7 b' class HTMLFormatter(BaseFormatter):'
456 """
456 """
457 format_type = Unicode('text/html')
457 format_type = Unicode('text/html')
458
458
459 print_method = Unicode('_repr_html_')
459 print_method = ObjectName('_repr_html_')
460
460
461
461
462 class SVGFormatter(BaseFormatter):
462 class SVGFormatter(BaseFormatter):
@@ -473,7 +473,7 b' class SVGFormatter(BaseFormatter):'
473 """
473 """
474 format_type = Unicode('image/svg+xml')
474 format_type = Unicode('image/svg+xml')
475
475
476 print_method = Unicode('_repr_svg_')
476 print_method = ObjectName('_repr_svg_')
477
477
478
478
479 class PNGFormatter(BaseFormatter):
479 class PNGFormatter(BaseFormatter):
@@ -489,7 +489,7 b' class PNGFormatter(BaseFormatter):'
489 """
489 """
490 format_type = Unicode('image/png')
490 format_type = Unicode('image/png')
491
491
492 print_method = Unicode('_repr_png_')
492 print_method = ObjectName('_repr_png_')
493
493
494
494
495 class LatexFormatter(BaseFormatter):
495 class LatexFormatter(BaseFormatter):
@@ -505,7 +505,7 b' class LatexFormatter(BaseFormatter):'
505 """
505 """
506 format_type = Unicode('text/latex')
506 format_type = Unicode('text/latex')
507
507
508 print_method = Unicode('_repr_latex_')
508 print_method = ObjectName('_repr_latex_')
509
509
510
510
511 class JSONFormatter(BaseFormatter):
511 class JSONFormatter(BaseFormatter):
@@ -520,7 +520,7 b' class JSONFormatter(BaseFormatter):'
520 """
520 """
521 format_type = Unicode('application/json')
521 format_type = Unicode('application/json')
522
522
523 print_method = Unicode('_repr_json_')
523 print_method = ObjectName('_repr_json_')
524
524
525
525
526 class JavascriptFormatter(BaseFormatter):
526 class JavascriptFormatter(BaseFormatter):
@@ -536,7 +536,7 b' class JavascriptFormatter(BaseFormatter):'
536 """
536 """
537 format_type = Unicode('application/javascript')
537 format_type = Unicode('application/javascript')
538
538
539 print_method = Unicode('_repr_javascript_')
539 print_method = ObjectName('_repr_javascript_')
540
540
541 FormatterABC.register(BaseFormatter)
541 FormatterABC.register(BaseFormatter)
542 FormatterABC.register(PlainTextFormatter)
542 FormatterABC.register(PlainTextFormatter)
@@ -22,12 +22,14 b' Authors:'
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 import sys
25 from unittest import TestCase
26 from unittest import TestCase
26
27
27 from IPython.utils.traitlets import (
28 from IPython.utils.traitlets import (
28 HasTraits, MetaHasTraits, TraitType, Any, CBytes,
29 HasTraits, MetaHasTraits, TraitType, Any, CBytes,
29 Int, Long, Float, Complex, Bytes, Unicode, TraitError,
30 Int, Long, Float, Complex, Bytes, Unicode, TraitError,
30 Undefined, Type, This, Instance, TCPAddress, List, Tuple
31 Undefined, Type, This, Instance, TCPAddress, List, Tuple,
32 ObjectName, DottedObjectName
31 )
33 )
32
34
33
35
@@ -725,11 +727,42 b' class TestUnicode(TraitTestBase):'
725
727
726 _default_value = u'unicode'
728 _default_value = u'unicode'
727 _good_values = ['10', '-10', '10L', '-10L', '10.1',
729 _good_values = ['10', '-10', '10L', '-10L', '10.1',
728 '-10.1', '', u'', 'string', u'string', ]
730 '-10.1', '', u'', 'string', u'string', u"€"]
729 _bad_values = [10, -10, 10L, -10L, 10.1, -10.1, 1j,
731 _bad_values = [10, -10, 10L, -10L, 10.1, -10.1, 1j,
730 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
732 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
731
733
732
734
735 class ObjectNameTrait(HasTraits):
736 value = ObjectName("abc")
737
738 class TestObjectName(TraitTestBase):
739 obj = ObjectNameTrait()
740
741 _default_value = "abc"
742 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
743 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
744 object(), object]
745 if sys.version_info[0] < 3:
746 _bad_values.append(u"ΓΎ")
747 else:
748 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
749
750
751 class DottedObjectNameTrait(HasTraits):
752 value = DottedObjectName("a.b")
753
754 class TestDottedObjectName(TraitTestBase):
755 obj = DottedObjectNameTrait()
756
757 _default_value = "a.b"
758 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
759 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc."]
760 if sys.version_info[0] < 3:
761 _bad_values.append(u"t.ΓΎ")
762 else:
763 _good_values.append(u"t.ΓΎ")
764
765
733 class TCPAddressTrait(HasTraits):
766 class TCPAddressTrait(HasTraits):
734
767
735 value = TCPAddress()
768 value = TCPAddress()
@@ -50,6 +50,7 b' Authors:'
50
50
51
51
52 import inspect
52 import inspect
53 import re
53 import sys
54 import sys
54 import types
55 import types
55 from types import (
56 from types import (
@@ -998,6 +999,50 b' class CUnicode(Unicode):'
998 return unicode(value)
999 return unicode(value)
999 except:
1000 except:
1000 self.error(obj, value)
1001 self.error(obj, value)
1002
1003
1004 class ObjectName(TraitType):
1005 """A string holding a valid object name in this version of Python.
1006
1007 This does not check that the name exists in any scope."""
1008 info_text = "a valid object identifier in Python"
1009
1010 if sys.version_info[0] < 3:
1011 # Python 2:
1012 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
1013 def isidentifier(self, s):
1014 return bool(self._name_re.match(s))
1015
1016 def coerce_str(self, obj, value):
1017 "In Python 2, coerce ascii-only unicode to str"
1018 if isinstance(value, unicode):
1019 try:
1020 return str(value)
1021 except UnicodeEncodeError:
1022 self.error(obj, value)
1023 return value
1024
1025 else:
1026 # Python 3:
1027 isidentifier = staticmethod(lambda s: s.isidentifier())
1028 coerce_str = staticmethod(lambda _,s: s)
1029
1030 def validate(self, obj, value):
1031 value = self.coerce_str(obj, value)
1032
1033 if isinstance(value, str) and self.isidentifier(value):
1034 return value
1035 self.error(obj, value)
1036
1037 class DottedObjectName(ObjectName):
1038 """A string holding a valid dotted object name in Python, such as A.b3._c"""
1039 def validate(self, obj, value):
1040 value = self.coerce_str(obj, value)
1041
1042 if isinstance(value, str) and all(self.isidentifier(x) \
1043 for x in value.split('.')):
1044 return value
1045 self.error(obj, value)
1001
1046
1002
1047
1003 class Bool(TraitType):
1048 class Bool(TraitType):
General Comments 0
You need to be logged in to leave comments. Login now