def test_check_unused_args(self):
class CheckAllUsedFormatter(string.Formatter):
def check_unused_args(self, used_args, args, kwargs):
# Track which arguments actually got used
unused_args = set(kwargs.keys())
unused_args.update(range(0, len(args)))
for arg in used_args:
unused_args.remove(arg)
if unused_args:
raise ValueError("unused arguments")
fmt = CheckAllUsedFormatter()
self.assertEqual(fmt.format("{0}", 10), "10")
self.assertEqual(fmt.format("{0}{i}", 10, i=100), "10100")
self.assertEqual(fmt.format("{0}{i}{1}", 10, 20, i=100), "1010020")
self.assertRaises(ValueError, fmt.format, "{0}{i}{1}", 10, 20, i=100, j=0)
self.assertRaises(ValueError, fmt.format, "{0}", 10, 20)
self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
python类Formatter()的实例源码
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
# We need to make sure the format spec is unicode here as
# otherwise the wrong callback methods are invoked. For
# instance a byte string there would invoke __str__ and
# not __unicode__.
rv = string.Formatter.format_field(
self, value, text_type(format_spec))
return text_type(self.escape(rv))
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
# We need to make sure the format spec is unicode here as
# otherwise the wrong callback methods are invoked. For
# instance a byte string there would invoke __str__ and
# not __unicode__.
rv = string.Formatter.format_field(
self, value, text_type(format_spec))
return text_type(self.escape(rv))
def collect_string_fields(format_string):
""" Given a format string, return an iterator
of all the valid format fields. It handles nested fields
as well.
"""
formatter = string.Formatter()
try:
parseiterator = formatter.parse(format_string)
for result in parseiterator:
if all(item is None for item in result[1:]):
# not a replacement format
continue
name = result[1]
nested = result[2]
yield name
if nested:
for field in collect_string_fields(nested):
yield field
except ValueError:
# probably the format string is invalid
# should we check the argument of the ValueError?
raise utils.IncompleteFormatString(format_string)
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
# We need to make sure the format spec is unicode here as
# otherwise the wrong callback methods are invoked. For
# instance a byte string there would invoke __str__ and
# not __unicode__.
rv = string.Formatter.format_field(
self, value, text_type(format_spec))
return text_type(self.escape(rv))
def collect_string_fields(format_string):
""" Given a format string, return an iterator
of all the valid format fields. It handles nested fields
as well.
"""
formatter = string.Formatter()
try:
parseiterator = formatter.parse(format_string)
for result in parseiterator:
if all(item is None for item in result[1:]):
# not a replacement format
continue
name = result[1]
nested = result[2]
yield name
if nested:
for field in collect_string_fields(nested):
yield field
except ValueError:
# probably the format string is invalid
# should we check the argument of the ValueError?
raise utils.IncompleteFormatString(format_string)
def _process_format( self, format_string ):
out = []
args = dict( self.__dict__ )
args["peer_info"] = ( "{peers_connected}/{peers_total}" if args["progress"] == 100 else "{seeds_connected}/{seeds_total}" ).format( **args )
args["label"] = "({label})".format( **args ) if args["label"] != "" else ""
if args["dl_speed"] < 1024:
args["dl_speed_h"] = ""
if args["ul_speed"] < 1024:
args["ul_speed_h"] = ""
if args["dl_remain"] == 0:
args["dl_remain_h"] = ""
formatter = string.Formatter( )
for literal_text, field_name, format_spec, conversion in formatter.parse( format_string ):
elem = { "before": literal_text, "value": "" }
if field_name is not None:
def_field_name, def_format_spec, def_conversion = None, " <20", None
if field_name in self._default_format_specs:
def_field_name, def_format_spec, def_conversion = next( formatter.parse( self._default_format_specs[field_name] ) )[1:4]
val = formatter.get_field( field_name if def_field_name is None else def_field_name, None, args )[0]
val = formatter.convert_field( val, conversion if conversion is not None else def_conversion )
val = formatter.format_field( val, format_spec if format_spec != "" else def_format_spec )
elem["value"] = val
out.append( elem )
return out
def valid_format_string(valid_fields):
"""
Ensure that the provided string can be parsed as a python format string, and contains only `valid_fields`
:param valid_fields: set or sequence of valid field names
"""
f = Formatter()
valid_fields = set(valid_fields)
def validate_string(format_string):
fields = set(field_name for _, field_name, _, _ in f.parse(format_string) if field_name)
if fields < valid_fields:
return format_string
else:
raise Invalid('format string specifies invalid field(s): %s' % (fields - valid_fields))
return validate_string
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
rv = string.Formatter.format_field(self, value, format_spec)
return text_type(self.escape(rv))
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
rv = string.Formatter.format_field(self, value, format_spec)
return text_type(self.escape(rv))
def to_str(self, item):
formatter = string.Formatter()
values = {}
for i in formatter.parse(self.template):
values[i[1]] = getattr(item, i[1])
return "%s" %(formatter.format(self.template, **values))
def __init__(self, string_format):
"""
The format string must be a unicode or ascii string: see notes above about being careful in Py2!
"""
if string_format is None:
attribute_names = []
else:
string_format = six.text_type(string_format) # force unicode so attribute values are unicode
formatter = string.Formatter()
attribute_names = [six.text_type(item[1]) for item in formatter.parse(string_format) if item[1]]
self.string_format = string_format
self.attribute_names = attribute_names
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
rv = string.Formatter.format_field(self, value, format_spec)
return text_type(self.escape(rv))
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
rv = string.Formatter.format_field(self, value, format_spec)
return text_type(self.escape(rv))
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
rv = string.Formatter.format_field(self, value, format_spec)
return text_type(self.escape(rv))
def _expand_pattern_lists(pattern, **mappings):
'''
Expands the pattern for any list-valued mappings, such that for any list of
length N in the mappings present in the pattern, N copies of the pattern are
returned, each with an element of the list substituted.
pattern:
A pattern to expand, for example 'by-role/{grains[roles]}'
mappings:
A dictionary of variables that can be expanded into the pattern.
Example: Given the pattern 'by-role/{grains[roles]}' and the below grains
.. code-block:: yaml
grains:
roles:
- web
- database
This function will expand that into '[by-role/web, by-role/database]'.
Note that this method does not expand any non-list patterns.
'''
expanded_patterns = []
f = string.Formatter()
for (_, field_name, _, _) in f.parse(pattern):
if field_name is None:
continue
(value, _) = f.get_field(field_name, None, mappings)
if isinstance(value, list):
token = '{{{0}}}'.format(field_name)
expanded = map(lambda x: pattern.replace(token, str(x)), value)
for expanded_item in expanded:
result = _expand_pattern_lists(expanded_item, **mappings)
expanded_patterns += result
return expanded_patterns
return [pattern]
def build_params(self):
formatter = string.Formatter()
param_names = [part[1] for part in formatter.parse(self.base_URL) if part[1] is not None]
return [{
'name': param_name,
'in': 'path',
'type': 'string',
'required': True
} for param_name in param_names]
def validate_permalink_template_template(self, node, key, template):
formatter = string.Formatter()
try:
parsed_format = list(formatter.parse(template))
except Exception as e:
return self.error('error parsing query path segment string: %s' % e, key)
leading_parts = [part for part in parsed_format if part[1] is not None]
if len(leading_parts) != 1:
self.error('permalinkTemplate template %s must include exactly one {name} element after ;' % query_path_segment_string)
else:
part = leading_parts[0]
if part[1] == '':
self.error('property name required between {} characters after %s in permalinkTemplate template %s' %(leading_parts[0] ,query_path_segment_string))
def __init__(self, setting, link, pattern):
self.setting = setting
self.link = link.upper()
self.pattern = pattern
# Determine the settings that need to be present
formatter = string.Formatter()
self.placeholders = [field
for _, field, _, _ in formatter.parse(pattern)
if field is not None]
def format_field(self, value, format_spec):
if hasattr(value, '__html_format__'):
rv = value.__html_format__(format_spec)
elif hasattr(value, '__html__'):
if format_spec:
raise ValueError('No format specification allowed '
'when formatting an object with '
'its __html__ method.')
rv = value.__html__()
else:
rv = string.Formatter.format_field(self, value, format_spec)
return text_type(self.escape(rv))