7 """This class serves as a placeholder for keys in not found during lookup into
8 keyword or positional arguments during a call to TolerateMissingKeyFormatter.
10 It records potential item and attribute lookups, conversion and format_spec to
11 reproduce original replacement_field entry into the formatted string.
16 field_name part of the replacement_field specifier
18 conversion part of the replacement_field specifier
20 format_spec part of the replacement_field specifier
24 replacement_field, field_name, conversion and format_spec have the meaning as outlined in
25 https://docs.python.org/2/library/string.html#format-string-syntax
28 def __init__(self, field_name, conversion=None, format_spec=None):
39 """Record attribute lookup"""
43 """Record item lookup"""
47 """Compose a replacement_field string equivalent to the original replacement_field in the string formatting."""
56 replacement_field =
"{" + text_in_brackets +
"}"
57 return replacement_field
62 """A string formatter that implements format most equivalent to the str.format, but does not replace keys,
63 that are not present in the replacements dictionary
67 >>> formatter = TolerateMissingKeyFormatter()
68 >>> template = "{present}_{missing}"
69 >>> partially_substituted = formatter.format(template, present="replaced")
70 >>> print partially_substituted
76 """Retrieves the value that corresponds to the key from either the postional or
77 the keyword arguments given to format
79 Overrides the standard lookup such that missing keys in the keyword arguments or
80 transformed in a NoReplacementField signal object.
83 if isinstance(key, str):
89 return super(TolerateMissingKeyFormatter, self).
get_value(key, args, kwds)
92 """Applies the conversion to the value.
94 Overrides the standard method such that a potential conversion is attached to the NoReplacementField
97 if isinstance(value, NoReplacementField):
98 conversion = conversion
or None
99 value.conversion = conversion
102 return super(TolerateMissingKeyFormatter, self).
convert_field(value, conversion)
105 """Applies the conversion to the value.
107 Overrides the standard method such that a potential format_spec is attached to the NoReplacementField.
108 Than composes the replacement_field specification to be inserted in the formatted string.
109 The outcome should be equivalent to the unformatted string for missing keys.
112 if isinstance(value, NoReplacementField):
113 format_spec = format_spec
or None
114 value.format_spec = format_spec
115 return value.compose()
117 return super(TolerateMissingKeyFormatter, self).
format_field(value, format_spec)
121 """Test the string formatter for cases where the keys are missing"""
124 """Prepare for the string-formatter test"""
129 """Test for a missing key"""
130 template =
"{present}_{missing}"
131 replaced = self.
formatter.format(template, present=
"replaced")
132 self.assertEqual(
"replaced_{missing}", replaced)
135 """Test for a missing key attribute"""
136 template =
"{present}_{missing.field}"
137 replaced = self.
formatter.format(template, present=
"replaced")
138 self.assertEqual(
"replaced_{missing.field}", replaced)
141 """Test for a missing key item"""
142 template =
"{present}_{missing[0]}"
143 replaced = self.
formatter.format(template, present=
"replaced")
144 self.assertEqual(
"replaced_{missing[0]}", replaced)
147 """Test for a missing key item"""
148 template =
"{present}_{missing!s}"
149 replaced = self.
formatter.format(template, present=
"replaced")
150 self.assertEqual(
"replaced_{missing!s}", replaced)
153 """Test for a missing key item"""
154 template =
"{present}_{missing!r}"
155 replaced = self.
formatter.format(template, present=
"replaced")
156 self.assertEqual(
"replaced_{missing!r}", replaced)
159 """Test for a missing key item"""
160 template =
"{present}_{missing!r:^10s}"
161 replaced = self.
formatter.format(template, present=
"replaced")
162 self.assertEqual(
"replaced_{missing!r:^10s}", replaced)
165 """Test for a missing key item"""
166 template =
"{present}_{missing:^10s}"
167 replaced = self.
formatter.format(template, present=
"replaced")
168 self.assertEqual(
"replaced_{missing:^10s}", replaced)
171 if __name__ ==
'__main__':