From 3ee967a1c8a35bebe25519e0b58f81585297552e Mon Sep 17 00:00:00 2001 From: MomIsBestFriend <> Date: Mon, 23 Dec 2019 11:18:09 +0200 Subject: [PATCH 1/3] TYP: Typing hints in pandas/io/formats/{css,csvs}.py --- pandas/io/formats/css.py | 48 ++++++++++++++++++++++++++---------- pandas/io/formats/csvs.py | 51 ++++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/pandas/io/formats/css.py b/pandas/io/formats/css.py index 583dd49d4c66a..334daab3083c0 100644 --- a/pandas/io/formats/css.py +++ b/pandas/io/formats/css.py @@ -1,4 +1,5 @@ -"""Utilities for interpreting CSS from Stylers for formatting non-HTML outputs +""" +Utilities for interpreting CSS from Stylers for formatting non-HTML outputs. """ import re @@ -6,19 +7,33 @@ class CSSWarning(UserWarning): - """This CSS syntax cannot currently be parsed""" + """ + This CSS syntax cannot currently be parsed. + """ pass def _side_expander(prop_fmt: str): - def expand(self, prop, value): + """ + Parameters + ---------- + prop_fmt : str + """ + + def expand(self, prop, value: str): + """ + Parameters + ---------- + prop + value : str + """ tokens = value.split() try: mapping = self.SIDE_SHORTHANDS[len(tokens)] except KeyError: warnings.warn( - f'Could not expand "{prop}: {value}"', CSSWarning, + f"Could not expand {prop}: {value}", CSSWarning, ) return for key, idx in zip(self.SIDES, mapping): @@ -28,12 +43,13 @@ def expand(self, prop, value): class CSSResolver: - """A callable for parsing and resolving CSS to atomic properties - + """ + A callable for parsing and resolving CSS to atomic properties. """ def __call__(self, declarations_str, inherited=None): - """ the given declarations to atomic properties + """ + The given declarations to atomic properties. Parameters ---------- @@ -46,8 +62,8 @@ def __call__(self, declarations_str, inherited=None): Returns ------- - props : dict - Atomic CSS 2.2 properties + dict + Atomic CSS 2.2 properties. Examples -------- @@ -69,7 +85,6 @@ def __call__(self, declarations_str, inherited=None): ('font-size', '24pt'), ('font-weight', 'bold')] """ - props = dict(self.atomize(self.parse(declarations_str))) if inherited is None: inherited = {} @@ -172,7 +187,9 @@ def __call__(self, declarations_str, inherited=None): def size_to_pt(self, in_val, em_pt=None, conversions=UNIT_RATIOS): def _error(): - warnings.warn(f"Unhandled size: {repr(in_val)}", CSSWarning) + warnings.warn( + f"Unhandled size: {repr(in_val)}", CSSWarning, + ) return self.size_to_pt("1!!default", conversions=conversions) try: @@ -235,10 +252,15 @@ def atomize(self, declarations): expand_margin = _side_expander("margin-{:s}") expand_padding = _side_expander("padding-{:s}") - def parse(self, declarations_str): - """Generates (prop, value) pairs from declarations + def parse(self, declarations_str: str): + """ + Generates (prop, value) pairs from declarations. In a future version may generate parsed tokens from tinycss/tinycss2 + + Parameters + ---------- + declarations_str : str """ for decl in declarations_str.split(";"): if not decl.strip(): diff --git a/pandas/io/formats/csvs.py b/pandas/io/formats/csvs.py index 72ba1a892cb8f..6d2975d29fa6d 100644 --- a/pandas/io/formats/csvs.py +++ b/pandas/io/formats/csvs.py @@ -5,7 +5,7 @@ import csv as csvlib from io import StringIO import os -from typing import List +from typing import List, Optional, Sequence, Union import warnings from zipfile import ZipFile @@ -21,6 +21,8 @@ ) from pandas.core.dtypes.missing import notna +from pandas._typing import FilePathOrBuffer + from pandas.io.common import ( get_compression_method, get_filepath_or_buffer, @@ -33,27 +35,26 @@ class CSVFormatter: def __init__( self, obj, - path_or_buf=None, - sep=",", - na_rep="", + path_or_buf: Optional[FilePathOrBuffer[str]] = None, + sep: str = ",", + na_rep: str = "", float_format=None, cols=None, - header=True, - index=True, + header: Union[bool, Sequence[str]] = True, + index: bool = True, index_label=None, - mode="w", - encoding=None, + mode: str = "w", + encoding: Optional[str] = None, compression="infer", - quoting=None, - line_terminator="\n", - chunksize=None, - quotechar='"', - date_format=None, - doublequote=True, + quoting: Optional[int] = None, + line_terminator: Optional[str] = "\n", + chunksize: Optional[int] = None, + quotechar: Optional[str] = '"', + date_format: Optional[str] = None, + doublequote: bool = True, escapechar=None, - decimal=".", + decimal: Optional[str] = ".", ): - self.obj = obj if path_or_buf is None: @@ -154,14 +155,17 @@ def __init__( if not index: self.nlevels = 0 - def save(self): + def save(self) -> None: """ - Create the writer & save + Create the writer & save. """ # GH21227 internal compression is not used when file-like passed. if self.compression and hasattr(self.path_or_buf, "write"): - msg = "compression has no effect when passing file-like object as input." - warnings.warn(msg, RuntimeWarning, stacklevel=2) + warnings.warn( + "compression has no effect when passing file-like object as input.", + RuntimeWarning, + stacklevel=2, + ) # when zip compression is called. is_zip = isinstance(self.path_or_buf, ZipFile) or ( @@ -223,7 +227,6 @@ def save(self): _fh.close() def _save_header(self): - writer = self.writer obj = self.obj index_label = self.index_label @@ -303,8 +306,7 @@ def _save_header(self): encoded_labels.extend([""] * len(columns)) writer.writerow(encoded_labels) - def _save(self): - + def _save(self) -> None: self._save_header() nrows = len(self.data_index) @@ -321,8 +323,7 @@ def _save(self): self._save_chunk(start_i, end_i) - def _save_chunk(self, start_i: int, end_i: int): - + def _save_chunk(self, start_i: int, end_i: int) -> None: data_index = self.data_index # create the data for a chunk From 6167f1afa314360eeac6ebafb2f5fad347f7dbd9 Mon Sep 17 00:00:00 2001 From: MomIsBestFriend <> Date: Wed, 25 Dec 2019 04:31:33 +0200 Subject: [PATCH 2/3] Added WillAyd's typing suggestions --- pandas/io/formats/css.py | 18 ++---------------- pandas/io/formats/csvs.py | 15 +++++++-------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/pandas/io/formats/css.py b/pandas/io/formats/css.py index 334daab3083c0..b40d2a57b8106 100644 --- a/pandas/io/formats/css.py +++ b/pandas/io/formats/css.py @@ -15,25 +15,13 @@ class CSSWarning(UserWarning): def _side_expander(prop_fmt: str): - """ - Parameters - ---------- - prop_fmt : str - """ - def expand(self, prop, value: str): - """ - Parameters - ---------- - prop - value : str - """ tokens = value.split() try: mapping = self.SIDE_SHORTHANDS[len(tokens)] except KeyError: warnings.warn( - f"Could not expand {prop}: {value}", CSSWarning, + f'Could not expand "{prop}: {value}"', CSSWarning, ) return for key, idx in zip(self.SIDES, mapping): @@ -187,9 +175,7 @@ def __call__(self, declarations_str, inherited=None): def size_to_pt(self, in_val, em_pt=None, conversions=UNIT_RATIOS): def _error(): - warnings.warn( - f"Unhandled size: {repr(in_val)}", CSSWarning, - ) + warnings.warn(f"Unhandled size: {repr(in_val)}", CSSWarning) return self.size_to_pt("1!!default", conversions=conversions) try: diff --git a/pandas/io/formats/csvs.py b/pandas/io/formats/csvs.py index 6d2975d29fa6d..edd4304dd4b6b 100644 --- a/pandas/io/formats/csvs.py +++ b/pandas/io/formats/csvs.py @@ -5,13 +5,14 @@ import csv as csvlib from io import StringIO import os -from typing import List, Optional, Sequence, Union +from typing import Hashable, List, Mapping, Optional, Sequence, Union import warnings from zipfile import ZipFile import numpy as np from pandas._libs import writers as libwriters +from pandas._typing import FilePathOrBuffer from pandas.core.dtypes.generic import ( ABCDatetimeIndex, @@ -21,8 +22,6 @@ ) from pandas.core.dtypes.missing import notna -from pandas._typing import FilePathOrBuffer - from pandas.io.common import ( get_compression_method, get_filepath_or_buffer, @@ -38,21 +37,21 @@ def __init__( path_or_buf: Optional[FilePathOrBuffer[str]] = None, sep: str = ",", na_rep: str = "", - float_format=None, + float_format: Optional[str] = None, cols=None, - header: Union[bool, Sequence[str]] = True, + header: Union[bool, Sequence[Hashable]] = True, index: bool = True, - index_label=None, + index_label: Optional[Union[bool, Hashable, Sequence[Hashable]]] = None, mode: str = "w", encoding: Optional[str] = None, - compression="infer", + compression: Union[str, Mapping[str, str], None] = "infer", quoting: Optional[int] = None, line_terminator: Optional[str] = "\n", chunksize: Optional[int] = None, quotechar: Optional[str] = '"', date_format: Optional[str] = None, doublequote: bool = True, - escapechar=None, + escapechar: Optional[str] = None, decimal: Optional[str] = ".", ): self.obj = obj From 1fcab9c2d7b6d6539ffdaa41ab70654efd3ff24f Mon Sep 17 00:00:00 2001 From: MomIsBestFriend <> Date: Wed, 25 Dec 2019 20:10:51 +0200 Subject: [PATCH 3/3] Review Fixes --- pandas/io/formats/csvs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/csvs.py b/pandas/io/formats/csvs.py index edd4304dd4b6b..0d581f30e50e7 100644 --- a/pandas/io/formats/csvs.py +++ b/pandas/io/formats/csvs.py @@ -46,13 +46,13 @@ def __init__( encoding: Optional[str] = None, compression: Union[str, Mapping[str, str], None] = "infer", quoting: Optional[int] = None, - line_terminator: Optional[str] = "\n", + line_terminator="\n", chunksize: Optional[int] = None, - quotechar: Optional[str] = '"', + quotechar='"', date_format: Optional[str] = None, doublequote: bool = True, escapechar: Optional[str] = None, - decimal: Optional[str] = ".", + decimal=".", ): self.obj = obj