From adf47f0f021780ad70f9dd770eb819193075c075 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 10 Sep 2017 09:28:44 -0400 Subject: [PATCH] CLN: replace %s syntax with .format in io Progress toward issue #16130. Converted old string formatting to new string formatting in io/html.py, io/excel.py, msgpack/_packer.pyx, msgpack/_unpacker.pyx, clipboard/exceptions.py, json/json.py, json/normalize.py, sas/sas.pyx --- pandas/io/clipboard/exceptions.py | 2 +- pandas/io/excel.py | 72 ++++++++++++++++++------------- pandas/io/html.py | 46 +++++++++++--------- pandas/io/json/json.py | 23 +++++----- pandas/io/json/normalize.py | 7 +-- pandas/io/msgpack/_packer.pyx | 2 +- pandas/io/msgpack/_unpacker.pyx | 7 +-- pandas/io/sas/sas.pyx | 16 ++++--- 8 files changed, 101 insertions(+), 74 deletions(-) diff --git a/pandas/io/clipboard/exceptions.py b/pandas/io/clipboard/exceptions.py index 413518e53660a..d948ad414327c 100644 --- a/pandas/io/clipboard/exceptions.py +++ b/pandas/io/clipboard/exceptions.py @@ -8,5 +8,5 @@ class PyperclipException(RuntimeError): class PyperclipWindowsException(PyperclipException): def __init__(self, message): - message += " (%s)" % ctypes.WinError() + message += " ({err})".format(err=ctypes.WinError()) super(PyperclipWindowsException, self).__init__(message) diff --git a/pandas/io/excel.py b/pandas/io/excel.py index faafdba435ff2..afecd76c498ef 100644 --- a/pandas/io/excel.py +++ b/pandas/io/excel.py @@ -165,7 +165,7 @@ def register_writer(klass): if ext.startswith('.'): ext = ext[1:] if ext not in _writer_extensions: - config.register_option("io.excel.%s.writer" % ext, + config.register_option("io.excel.{ext}.writer".format(ext=ext), engine_name, validator=str) _writer_extensions.append(ext) @@ -190,7 +190,8 @@ def get_writer(engine_name): try: return _writers[engine_name] except KeyError: - raise ValueError("No Excel writer '%s'" % engine_name) + raise ValueError("No Excel writer '{engine}'" + .format(engine=engine_name)) @Appender(_read_excel_doc) @@ -259,7 +260,7 @@ def __init__(self, io, **kwds): engine = kwds.pop('engine', None) if engine is not None and engine != 'xlrd': - raise ValueError("Unknown engine: %s" % engine) + raise ValueError("Unknown engine: {engine}".format(engine=engine)) # If io is a url, want to keep the data as bytes so can't pass # to get_filepath_or_buffer() @@ -445,7 +446,7 @@ def _parse_cell(cell_contents, cell_typ): for asheetname in sheets: if verbose: - print("Reading sheet %s" % asheetname) + print("Reading sheet {sheet}".format(sheet=asheetname)) if isinstance(asheetname, compat.string_types): sheet = self.book.sheet_by_name(asheetname) @@ -634,7 +635,7 @@ def _conv_value(val): elif is_bool(val): val = bool(val) elif isinstance(val, Period): - val = "%s" % val + val = "{val}".format(val=val) elif is_list_like(val): val = str(val) @@ -697,9 +698,11 @@ def __new__(cls, path, engine=None, **kwargs): ext = 'xlsx' try: - engine = config.get_option('io.excel.%s.writer' % ext) + engine = config.get_option('io.excel.{ext}.writer' + .format(ext=ext)) except KeyError: - error = ValueError("No engine for filetype: '%s'" % ext) + error = ValueError("No engine for filetype: '{ext}'" + .format(ext=ext)) raise error cls = get_writer(engine) @@ -787,8 +790,9 @@ def check_extension(cls, ext): if ext.startswith('.'): ext = ext[1:] if not any(ext in extension for extension in cls.supported_extensions): - msg = (u("Invalid extension for engine '%s': '%s'") % - (pprint_thing(cls.engine), pprint_thing(ext))) + msg = (u("Invalid extension for engine '{engine}': '{ext}'") + .format(engine=pprint_thing(cls.engine), + ext=pprint_thing(ext))) raise ValueError(msg) else: return True @@ -813,8 +817,8 @@ class _Openpyxl1Writer(ExcelWriter): def __init__(self, path, engine=None, **engine_kwargs): if not openpyxl_compat.is_compat(major_ver=self.openpyxl_majorver): raise ValueError('Installed openpyxl is not supported at this ' - 'time. Use {0}.x.y.' - .format(self.openpyxl_majorver)) + 'time. Use {majorver}.x.y.' + .format(majorver=self.openpyxl_majorver)) # Use the openpyxl module as the Excel writer. from openpyxl.workbook import Workbook @@ -854,7 +858,8 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, for cell in cells: colletter = get_column_letter(startcol + cell.col + 1) - xcell = wks.cell("%s%s" % (colletter, startrow + cell.row + 1)) + xcell = wks.cell("{col}{row}".format(col=colletter, + row=startrow + cell.row + 1)) if (isinstance(cell.val, compat.string_types) and xcell.data_type_for_value(cell.val) != xcell.TYPE_STRING): xcell.set_value_explicit(cell.val) @@ -876,10 +881,12 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, cletterstart = get_column_letter(startcol + cell.col + 1) cletterend = get_column_letter(startcol + cell.mergeend + 1) - wks.merge_cells('%s%s:%s%s' % (cletterstart, - startrow + cell.row + 1, - cletterend, - startrow + cell.mergestart + 1)) + wks.merge_cells('{start}{row}:{end}{mergestart}' + .format(start=cletterstart, + row=startrow + cell.row + 1, + end=cletterend, + mergestart=startrow + + cell.mergestart + 1)) # Excel requires that the format of the first cell in a merged # range is repeated in the rest of the merged range. @@ -895,7 +902,8 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, # Ignore first cell. It is already handled. continue colletter = get_column_letter(col) - xcell = wks.cell("%s%s" % (colletter, row)) + xcell = wks.cell("{col}{row}" + .format(col=colletter, row=row)) for field in style.__fields__: xcell.style.__setattr__( field, style.__getattribute__(field)) @@ -955,7 +963,8 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, for cell in cells: colletter = get_column_letter(startcol + cell.col + 1) - xcell = wks["%s%s" % (colletter, startrow + cell.row + 1)] + xcell = wks["{col}{row}" + .format(col=colletter, row=startrow + cell.row + 1)] xcell.value = _conv_value(cell.val) style_kwargs = {} @@ -977,10 +986,12 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, cletterstart = get_column_letter(startcol + cell.col + 1) cletterend = get_column_letter(startcol + cell.mergeend + 1) - wks.merge_cells('%s%s:%s%s' % (cletterstart, - startrow + cell.row + 1, - cletterend, - startrow + cell.mergestart + 1)) + wks.merge_cells('{start}{row}:{end}{mergestart}' + .format(start=cletterstart, + row=startrow + cell.row + 1, + end=cletterend, + mergestart=startrow + + cell.mergestart + 1)) # Excel requires that the format of the first cell in a merged # range is repeated in the rest of the merged range. @@ -996,7 +1007,8 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, # Ignore first cell. It is already handled. continue colletter = get_column_letter(col) - xcell = wks["%s%s" % (colletter, row)] + xcell = wks["{col}{row}" + .format(col=colletter, row=row)] xcell.style = xcell.style.copy(**style_kwargs) @classmethod @@ -1030,7 +1042,7 @@ def _convert_to_style_kwargs(cls, style_dict): for k, v in style_dict.items(): if k in _style_key_map: k = _style_key_map[k] - _conv_to_x = getattr(cls, '_convert_to_{0}'.format(k), + _conv_to_x = getattr(cls, '_convert_to_{k}'.format(k=k), lambda x: None) new_v = _conv_to_x(v) if new_v: @@ -1505,17 +1517,19 @@ def _style_to_xlwt(cls, item, firstlevel=True, field_sep=',', """ if hasattr(item, 'items'): if firstlevel: - it = ["%s: %s" % (key, cls._style_to_xlwt(value, False)) + it = ["{key}: {val}" + .format(key=key, val=cls._style_to_xlwt(value, False)) for key, value in item.items()] - out = "%s " % (line_sep).join(it) + out = "{sep} ".format(sep=(line_sep).join(it)) return out else: - it = ["%s %s" % (key, cls._style_to_xlwt(value, False)) + it = ["{key} {val}" + .format(key=key, val=cls._style_to_xlwt(value, False)) for key, value in item.items()] - out = "%s " % (field_sep).join(it) + out = "{sep} ".format(sep=(field_sep).join(it)) return out else: - item = "%s" % item + item = "{item}".format(item=item) item = item.replace("True", "on") item = item.replace("False", "off") return item diff --git a/pandas/io/html.py b/pandas/io/html.py index a4acb26af5259..b5aaffcf710c2 100644 --- a/pandas/io/html.py +++ b/pandas/io/html.py @@ -439,14 +439,15 @@ def _parse_tables(self, doc, match, attrs): unique_tables.add(table) if not result: - raise ValueError("No tables found matching pattern %r" % - match.pattern) + raise ValueError("No tables found matching pattern {patt!r}" + .format(patt=match.pattern)) return result def _setup_build_doc(self): raw_text = _read(self.io) if not raw_text: - raise ValueError('No text parsed from document: %s' % self.io) + raise ValueError('No text parsed from document: {doc}' + .format(doc=self.io)) return raw_text def _build_doc(self): @@ -473,8 +474,8 @@ def _build_xpath_expr(attrs): if 'class_' in attrs: attrs['class'] = attrs.pop('class_') - s = [u("@%s=%r") % (k, v) for k, v in iteritems(attrs)] - return u('[%s]') % ' and '.join(s) + s = [u("@{key}={val!r}").format(key=k, val=v) for k, v in iteritems(attrs)] + return u('[{expr}]').format(expr=' and '.join(s)) _re_namespace = {'re': 'http://exslt.org/regular-expressions'} @@ -517,8 +518,8 @@ def _parse_tables(self, doc, match, kwargs): # 1. check all descendants for the given pattern and only search tables # 2. go up the tree until we find a table - query = '//table//*[re:test(text(), %r)]/ancestor::table' - xpath_expr = u(query) % pattern + query = '//table//*[re:test(text(), {patt!r})]/ancestor::table' + xpath_expr = u(query).format(patt=pattern) # if any table attributes were given build an xpath expression to # search for them @@ -528,7 +529,8 @@ def _parse_tables(self, doc, match, kwargs): tables = doc.xpath(xpath_expr, namespaces=_re_namespace) if not tables: - raise ValueError("No tables found matching regex %r" % pattern) + raise ValueError("No tables found matching regex {patt!r}" + .format(patt=pattern)) return tables def _build_doc(self): @@ -574,8 +576,9 @@ def _build_doc(self): scheme = parse_url(self.io).scheme if scheme not in _valid_schemes: # lxml can't parse it - msg = ('%r is not a valid url scheme, valid schemes are ' - '%s') % (scheme, _valid_schemes) + msg = (('{invalid!r} is not a valid url scheme, valid ' + 'schemes are {valid}') + .format(invalid=scheme, valid=_valid_schemes)) raise ValueError(msg) else: # something else happened: maybe a faulty connection @@ -670,8 +673,9 @@ def _parser_dispatch(flavor): """ valid_parsers = list(_valid_parsers.keys()) if flavor not in valid_parsers: - raise ValueError('%r is not a valid flavor, valid flavors are %s' % - (flavor, valid_parsers)) + raise ValueError('{invalid!r} is not a valid flavor, valid flavors ' + 'are {valid}' + .format(invalid=flavor, valid=valid_parsers)) if flavor in ('bs4', 'html5lib'): if not _HAS_HTML5LIB: @@ -695,7 +699,7 @@ def _parser_dispatch(flavor): def _print_as_set(s): - return '{%s}' % ', '.join([pprint_thing(el) for el in s]) + return '{{arg}}'.format(arg=', '.join([pprint_thing(el) for el in s])) def _validate_flavor(flavor): @@ -705,21 +709,23 @@ def _validate_flavor(flavor): flavor = flavor, elif isinstance(flavor, collections.Iterable): if not all(isinstance(flav, string_types) for flav in flavor): - raise TypeError('Object of type %r is not an iterable of strings' % - type(flavor).__name__) + raise TypeError('Object of type {typ!r} is not an iterable of ' + 'strings' + .format(typ=type(flavor).__name__)) else: - fmt = '{0!r}' if isinstance(flavor, string_types) else '{0}' + fmt = '{flavor!r}' if isinstance(flavor, string_types) else '{flavor}' fmt += ' is not a valid flavor' - raise ValueError(fmt.format(flavor)) + raise ValueError(fmt.format(flavor=flavor)) flavor = tuple(flavor) valid_flavors = set(_valid_parsers) flavor_set = set(flavor) if not flavor_set & valid_flavors: - raise ValueError('%s is not a valid set of flavors, valid flavors are ' - '%s' % (_print_as_set(flavor_set), - _print_as_set(valid_flavors))) + raise ValueError('{invalid} is not a valid set of flavors, valid ' + 'flavors are {valid}' + .format(invalid=_print_as_set(flavor_set), + valid=_print_as_set(valid_flavors))) return flavor diff --git a/pandas/io/json/json.py b/pandas/io/json/json.py index a1d48719ba9c0..5dae6099446d0 100644 --- a/pandas/io/json/json.py +++ b/pandas/io/json/json.py @@ -99,7 +99,7 @@ class SeriesWriter(Writer): def _format_axes(self): if not self.obj.index.is_unique and self.orient == 'index': raise ValueError("Series index must be unique for orient=" - "'%s'" % self.orient) + "'{orient}'".format(orient=self.orient)) class FrameWriter(Writer): @@ -110,11 +110,11 @@ def _format_axes(self): if not self.obj.index.is_unique and self.orient in ( 'index', 'columns'): raise ValueError("DataFrame index must be unique for orient=" - "'%s'." % self.orient) + "'{orient}'.".format(orient=self.orient)) if not self.obj.columns.is_unique and self.orient in ( 'index', 'columns', 'records'): raise ValueError("DataFrame columns must be unique for orient=" - "'%s'." % self.orient) + "'{orient}'.".format(orient=self.orient)) class JSONTableWriter(FrameWriter): @@ -134,8 +134,9 @@ def __init__(self, obj, orient, date_format, double_precision, if date_format != 'iso': msg = ("Trying to write with `orient='table'` and " - "`date_format='%s'`. Table Schema requires dates " - "to be formatted with `date_format='iso'`" % date_format) + "`date_format='{fmt}'`. Table Schema requires dates " + "to be formatted with `date_format='iso'`" + .format(fmt=date_format)) raise ValueError(msg) self.schema = build_table_schema(obj) @@ -166,8 +167,8 @@ def __init__(self, obj, orient, date_format, double_precision, def write(self): data = super(JSONTableWriter, self).write() - serialized = '{{"schema": {}, "data": {}}}'.format( - dumps(self.schema), data) + serialized = '{{"schema": {schema}, "data": {data}}}'.format( + schema=dumps(self.schema), data=data) return serialized @@ -391,8 +392,8 @@ def __init__(self, json, orient, dtype=True, convert_axes=True, if date_unit is not None: date_unit = date_unit.lower() if date_unit not in self._STAMP_UNITS: - raise ValueError('date_unit must be one of %s' % - (self._STAMP_UNITS,)) + raise ValueError('date_unit must be one of {units}' + .format(units=self._STAMP_UNITS)) self.min_stamp = self._MIN_STAMPS[date_unit] else: self.min_stamp = self._MIN_STAMPS['s'] @@ -410,8 +411,8 @@ def check_keys_split(self, decoded): bad_keys = set(decoded.keys()).difference(set(self._split_keys)) if bad_keys: bad_keys = ", ".join(bad_keys) - raise ValueError(u("JSON data had unexpected key(s): %s") % - pprint_thing(bad_keys)) + raise ValueError(u("JSON data had unexpected key(s): {bad_keys}") + .format(bad_keys=pprint_thing(bad_keys))) def parse(self): diff --git a/pandas/io/json/normalize.py b/pandas/io/json/normalize.py index 72776ed01de15..e811dd1eab142 100644 --- a/pandas/io/json/normalize.py +++ b/pandas/io/json/normalize.py @@ -249,7 +249,8 @@ def _recursive_extract(data, path, seen_meta, level=0): raise \ KeyError("Try running with " "errors='ignore' as key " - "%s is not always present", e) + "{err} is not always present" + .format(err=e)) meta_vals[key].append(meta_val) records.extend(recs) @@ -267,8 +268,8 @@ def _recursive_extract(data, path, seen_meta, level=0): k = meta_prefix + k if k in result: - raise ValueError('Conflicting metadata name %s, ' - 'need distinguishing prefix ' % k) + raise ValueError('Conflicting metadata name {name}, ' + 'need distinguishing prefix '.format(name=k)) result[k] = np.array(v).repeat(lengths) diff --git a/pandas/io/msgpack/_packer.pyx b/pandas/io/msgpack/_packer.pyx index ad7ce1fb2531a..fd3f4612fb432 100644 --- a/pandas/io/msgpack/_packer.pyx +++ b/pandas/io/msgpack/_packer.pyx @@ -224,7 +224,7 @@ cdef class Packer(object): default_used = 1 continue else: - raise TypeError("can't serialize %r" % (o,)) + raise TypeError("can't serialize {thing!r}".format(thing=o)) return ret cpdef pack(self, object obj): diff --git a/pandas/io/msgpack/_unpacker.pyx b/pandas/io/msgpack/_unpacker.pyx index 504bfed48df3c..22401d7514f65 100644 --- a/pandas/io/msgpack/_unpacker.pyx +++ b/pandas/io/msgpack/_unpacker.pyx @@ -94,7 +94,7 @@ cdef inline init_ctx(unpack_context *ctx, def default_read_extended_type(typecode, data): raise NotImplementedError("Cannot decode extended type " - "with typecode=%d" % typecode) + "with typecode={code}".format(code=typecode)) def unpackb(object packed, object object_hook=None, object list_hook=None, @@ -144,7 +144,7 @@ def unpackb(object packed, object object_hook=None, object list_hook=None, buf + off, buf_len - off)) return obj else: - raise UnpackValueError("Unpack failed: error = %d" % (ret,)) + raise UnpackValueError("Unpack failed: error = {ret}".format(ret=ret)) def unpack(object stream, object object_hook=None, object list_hook=None, @@ -411,7 +411,8 @@ cdef class Unpacker(object): else: raise OutOfData("No more data to unpack.") else: - raise ValueError("Unpack failed: error = %d" % (ret,)) + raise ValueError("Unpack failed: error = {ret}" + .format(ret=ret)) def read_bytes(self, Py_ssize_t nbytes): """Read a specified number of raw bytes from the stream""" diff --git a/pandas/io/sas/sas.pyx b/pandas/io/sas/sas.pyx index 4396180da44cb..41c03cb2799a3 100644 --- a/pandas/io/sas/sas.pyx +++ b/pandas/io/sas/sas.pyx @@ -101,10 +101,12 @@ cdef np.ndarray[uint8_t, ndim=1] rle_decompress( result[rpos] = 0x00 rpos += 1 else: - raise ValueError("unknown control byte: %v", control_byte) + raise ValueError("unknown control byte: {byte}" + .format(byte=control_byte)) if len(result) != result_length: - raise ValueError("RLE: %v != %v", (len(result), result_length)) + raise ValueError("RLE: {got} != {expect}".format(got=len(result), + expect=result_length)) return np.asarray(result) @@ -185,7 +187,8 @@ cdef np.ndarray[uint8_t, ndim=1] rdc_decompress( raise ValueError("unknown RDC command") if len(outbuff) != result_length: - raise ValueError("RDC: %v != %v\n", len(outbuff), result_length) + raise ValueError("RDC: {got} != {expect}\n" + .format(got=len(outbuff), expect=result_length)) return np.asarray(outbuff) @@ -258,7 +261,8 @@ cdef class Parser(object): self.column_types[j] = column_type_string else: raise ValueError("unknown column type: " - "%s" % self.parser.columns[j].ctype) + "{typ}" + .format(typ=self.parser.columns[j].ctype)) # compression if parser.compression == const.rle_compression: @@ -378,8 +382,8 @@ cdef class Parser(object): return True return False else: - raise ValueError("unknown page type: %s", - self.current_page_type) + raise ValueError("unknown page type: {typ}" + .format(typ=self.current_page_type)) cdef void process_byte_array_with_data(self, int offset, int length):