diff --git a/python/pyarrow/_csv.pyx b/python/pyarrow/_csv.pyx index ed9d20beb6b3..79985530af17 100644 --- a/python/pyarrow/_csv.pyx +++ b/python/pyarrow/_csv.pyx @@ -332,6 +332,22 @@ cdef class ReadOptions(_Weakrefable): except TypeError: return False + def _repr_base(self): + return (f""" + use_threads={self.use_threads}, + block_size={self.block_size}, + skip_rows={self.skip_rows}, + skip_rows_after_names={self.skip_rows_after_names}, + column_names={self.column_names}, + autogenerate_column_names={self.autogenerate_column_names}, + encoding={self.encoding!r}""") + + def __repr__(self): + return (f"({self._repr_base()})") + + def __str__(self): + return (f"ReadOptions({self._repr_base()})") + cdef class ParseOptions(_Weakrefable): """ @@ -585,6 +601,23 @@ cdef class ParseOptions(_Weakrefable): except TypeError: return False + def _repr_base(self): + return (f""" + delimiter={self.delimiter!r}, + quote_char={self.quote_char!r}, + double_quote={self.double_quote}, + escape_char={self.escape_char!r}, + newlines_in_values={self.newlines_in_values}, + ignore_empty_lines={self.ignore_empty_lines}, + invalid_row_handler={getattr(self.invalid_row_handler, '__name__', + self.invalid_row_handler)}""") + + def __repr__(self): + return (f"({self._repr_base()})") + + def __str__(self): + return (f"ParseOptions({self._repr_base()})") + cdef class _ISO8601(_Weakrefable): """ @@ -1108,6 +1141,28 @@ cdef class ConvertOptions(_Weakrefable): except TypeError: return False + def _repr_base(self): + return (f""" + check_utf8={self.check_utf8}, + column_types={self.column_types}, + null_values={self.null_values}, + true_values={self.true_values}, + false_values={self.false_values}, + decimal_point={self.decimal_point!r}, + strings_can_be_null={self.strings_can_be_null}, + quoted_strings_can_be_null={self.quoted_strings_can_be_null}, + include_columns={self.include_columns}, + include_missing_columns={self.include_missing_columns}, + auto_dict_encode={self.auto_dict_encode}, + auto_dict_max_cardinality={self.auto_dict_max_cardinality}, + timestamp_parsers={[str(i) for i in self.timestamp_parsers]}""") + + def __repr__(self): + return (f"({self._repr_base()})") + + def __str__(self): + return (f"ConvertOptions({self._repr_base()})") + cdef _get_reader(input_file, ReadOptions read_options, shared_ptr[CInputStream]* out): @@ -1459,6 +1514,19 @@ cdef class WriteOptions(_Weakrefable): def validate(self): check_status(self.options.get().Validate()) + def _repr_base(self): + return (f""" + include_header={self.include_header}, + batch_size={self.batch_size}, + delimiter={self.delimiter!r}, + quoting_style={self.quoting_style!r}""") + + def __repr__(self): + return (f"({self._repr_base()})") + + def __str__(self): + return (f"WriteOptions({self._repr_base()})") + cdef _get_write_options(WriteOptions write_options, CCSVWriteOptions* out): if write_options is None: diff --git a/python/pyarrow/_json.pyx b/python/pyarrow/_json.pyx index 07e615dd5e48..f8373feeabe5 100644 --- a/python/pyarrow/_json.pyx +++ b/python/pyarrow/_json.pyx @@ -105,6 +105,16 @@ cdef class ReadOptions(_Weakrefable): except TypeError: return False + def __repr__(self): + return (f"""( + use_threads={self.use_threads}, + block_size={self.block_size})""") + + def __str__(self): + return (f"""ReadOptions( + use_threads={self.use_threads}, + block_size={self.block_size})""") + @staticmethod cdef ReadOptions wrap(CJSONReadOptions options): out = ReadOptions() @@ -244,6 +254,18 @@ cdef class ParseOptions(_Weakrefable): except TypeError: return False + def _repr_base(self): + return (f""" + explicit_schema={self.explicit_schema}, + newlines_in_values={self.newlines_in_values}, + unexpected_field_behavior={self.unexpected_field_behavior!r}""") + + def __repr__(self): + return (f"({self._repr_base()})") + + def __str__(self): + return (f"ParseOptions({self._repr_base()})") + @staticmethod cdef ParseOptions wrap(CJSONParseOptions options): out = ParseOptions() diff --git a/python/pyarrow/tests/test_csv.py b/python/pyarrow/tests/test_csv.py index dce605c7156d..d608d2bee5eb 100644 --- a/python/pyarrow/tests/test_csv.py +++ b/python/pyarrow/tests/test_csv.py @@ -213,6 +213,18 @@ def test_read_options(pickle_module): opts.column_names = ('a', 'b') opts.validate() + expected_repr_inner = """ + use_threads=True, + block_size=1048576, + skip_rows=0, + skip_rows_after_names=0, + column_names=['a', 'b'], + autogenerate_column_names=True, + encoding='utf8'""" + + assert repr(opts) == f"({expected_repr_inner})" + assert str(opts) == f"ReadOptions({expected_repr_inner})" + def test_parse_options(pickle_module): cls = ParseOptions @@ -273,6 +285,18 @@ def test_parse_options(pickle_module): opts.escape_char = "\r" opts.validate() + expected_repr_inner = r""" + delimiter=',', + quote_char='"', + double_quote=True, + escape_char='\r', + newlines_in_values=False, + ignore_empty_lines=True, + invalid_row_handler=None""" + + assert repr(opts) == f"({expected_repr_inner})" + assert str(opts) == f"ParseOptions({expected_repr_inner})" + def test_convert_options(pickle_module): cls = ConvertOptions @@ -354,6 +378,23 @@ def test_convert_options(pickle_module): assert opts.auto_dict_max_cardinality == 999 assert opts.timestamp_parsers == [ISO8601, '%Y-%m-%d'] + expected_repr_inner = (""" + check_utf8=True, + column_types={'a': DataType(null)}, + null_values=['N', 'nn'], + true_values=['T', 'tt'], + false_values=['F', 'ff'], + decimal_point='.', + strings_can_be_null=False, + quoted_strings_can_be_null=True, + include_columns=[], + include_missing_columns=False, + auto_dict_encode=False, + auto_dict_max_cardinality=999, + timestamp_parsers=['ISO8601', '%Y-%m-%d']""") + assert repr(opts) == f"({expected_repr_inner})" + assert str(opts) == f"ConvertOptions({expected_repr_inner})" + def test_write_options(): cls = WriteOptions @@ -378,6 +419,15 @@ def test_write_options(): opts.batch_size = 0 opts.validate() + expected_repr_inner = """ + include_header=True, + batch_size=0, + delimiter=',', + quoting_style='needed'""" + + assert repr(opts) == f"({expected_repr_inner})" + assert str(opts) == f"WriteOptions({expected_repr_inner})" + class BaseTestCSV(abc.ABC): """Common tests which are shared by streaming and non streaming readers""" diff --git a/python/pyarrow/tests/test_json.py b/python/pyarrow/tests/test_json.py index c3f9fe333bd0..8d5e6f43db06 100644 --- a/python/pyarrow/tests/test_json.py +++ b/python/pyarrow/tests/test_json.py @@ -80,6 +80,13 @@ def test_read_options(pickle_module): assert opts.block_size == 1234 assert opts.use_threads is False + expected_repr_inner = """ + use_threads=False, + block_size=1234""" + + assert repr(opts) == f"({expected_repr_inner})" + assert str(opts) == f"ReadOptions({expected_repr_inner})" + check_options_class_pickling(cls, pickler=pickle_module, block_size=1234, use_threads=False) @@ -94,6 +101,14 @@ def test_parse_options(pickle_module): opts.newlines_in_values = True assert opts.newlines_in_values is True + expected_repr_inner = """ + explicit_schema=None, + newlines_in_values=True, + unexpected_field_behavior='infer'""" + + assert repr(opts) == f"({expected_repr_inner})" + assert str(opts) == f"ParseOptions({expected_repr_inner})" + schema = pa.schema([pa.field('foo', pa.int32())]) opts.explicit_schema = schema assert opts.explicit_schema == schema