Skip to content

Commit

Permalink
apacheGH-37979: [C++] Add support for specifying custom Array opening…
Browse files Browse the repository at this point in the history
… and closing delimiters to `arrow::PrettyPrintDelimiters` (apache#38187)

### Rationale for this change

This is a follow up to  apache#37981.

in order to make the [`arrow::PrettyPrint`](https://github.com/apache/arrow/blob/7667b81bffcb5b361fab6d61c42ce396d98cc6e1/cpp/src/arrow/pretty_print.h#L101) functionality for `arrow::Array` more flexible, it would be useful to be able to specify a custom `Array` opening and closing delimiter other than `"["` and `"]"`.

For example, the MATLAB interface wraps the Arrow C++ libraries and being able to specify a custom opening and closing delimiter for `Array` would make it possible to make the display of MATLAB `arrow.array.Array` objects more MATLAB-like.

In order to support custom `Array` opening and closing delimiters, this pull request adds two new properties, `open` and `close`, to the [`arrow::PrettyPrintDelimiters`](https://github.com/apache/arrow/blob/c37059ad7b87f0cbb681f6388aca0e3f02860351/cpp/src/arrow/pretty_print.h#L38) struct.

This enable use cases like the ability to display an `arrow::Array` as `<1,2,3>` instead of `[1,2,3]`, by setting `options.array_delimiters.open = "<"` and `options.array_delimiters.close = ">"`.

### What changes are included in this PR?

This pull request adds two new properties to the [`arrow::PrettyPrintDelimiters`](https://github.com/apache/arrow/blob/c37059ad7b87f0cbb681f6388aca0e3f02860351/cpp/src/arrow/pretty_print.h#L38) struct:

1. `open` - the opening delimiter to use for an `Array` or `ChunkedArray` (default = `[`).
1. `close` - the closing delimiter to use for an `Array` or `ChunkedArray` (default = `]`).

### Are these changes tested?

Yes.

1. Added two new tests: (1) `ArrayCustomOpenCloseDelimiter` and (2) `ChunkedArrayCustomOpenCloseDelimiter`.
2. All existing tests related to `arrow::PrettyPrint` pass.

### Are there any user-facing changes?

Yes.

This pull request adds two new public, user-facing properties, (1) `open` (of type `std::string`) and (2) `close` (also of type `std::string`) to the `PrettyPrintDelimiters` struct. This enables client code to specify custom opening and closing delimiters to use when printing an `arrow::Array` or `arrow::ChunkedArray` by changing the values of the nested `open` and `close` properties of the `array_delimiters`/`chunked_array_delimiters` properties of `PrettyPrintOptions`.

### Notes

1. This pull request was motivated by our desire to improve the display of Arrow related classes in the MATLAB interface, but it is hopefully a generic enough change that it may benefit other use cases too.

### Future Directions

1. Now that client code can easily specify custom opening, closing, and element delimiters, it may make sense to address apache#30951.
* Closes: apache#37979

Authored-by: Kevin Gurney <[email protected]>
Signed-off-by: Joris Van den Bossche <[email protected]>
  • Loading branch information
kevingurney authored and loicalleyne committed Nov 13, 2023
1 parent db49859 commit 246735f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 4 deletions.
8 changes: 4 additions & 4 deletions cpp/src/arrow/pretty_print.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void PrettyPrinter::OpenArray(const Array& array) {
if (!options_.skip_new_lines) {
Indent();
}
(*sink_) << "[";
(*sink_) << options_.array_delimiters.open;
if (array.length() > 0) {
Newline();
indent_ += options_.indent_size;
Expand All @@ -101,7 +101,7 @@ void PrettyPrinter::CloseArray(const Array& array) {
Indent();
}
}
(*sink_) << "]";
(*sink_) << options_.array_delimiters.close;
}

void PrettyPrinter::Write(std::string_view data) { (*sink_) << data; }
Expand Down Expand Up @@ -449,7 +449,7 @@ Status PrettyPrint(const ChunkedArray& chunked_arr, const PrettyPrintOptions& op
for (int i = 0; i < indent; ++i) {
(*sink) << " ";
}
(*sink) << "[";
(*sink) << options.chunked_array_delimiters.open;
if (!skip_new_lines) {
*sink << "\n";
}
Expand Down Expand Up @@ -488,7 +488,7 @@ Status PrettyPrint(const ChunkedArray& chunked_arr, const PrettyPrintOptions& op
for (int i = 0; i < indent; ++i) {
(*sink) << " ";
}
(*sink) << "]";
(*sink) << options.chunked_array_delimiters.close;

return Status::OK();
}
Expand Down
6 changes: 6 additions & 0 deletions cpp/src/arrow/pretty_print.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ class Table;
/// \brief Options for controlling which delimiters to use when printing
/// an Array or ChunkedArray.
struct ARROW_EXPORT PrettyPrintDelimiters {
/// Delimiter to use when opening an Array or ChunkedArray (e.g. "[")
std::string open = "[";

/// Delimiter to use when closing an Array or ChunkedArray (e.g. "]")
std::string close = "]";

/// Delimiter for separating individual elements of an Array (e.g. ","),
/// or individual chunks of a ChunkedArray
std::string element = ",";
Expand Down
73 changes: 73 additions & 0 deletions cpp/src/arrow/pretty_print_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,25 @@ TEST_F(TestPrettyPrint, ArrayCustomElementDelimiter) {
}
}

TEST_F(TestPrettyPrint, ArrayCustomOpenCloseDelimiter) {
PrettyPrintOptions options{};
// Use a custom opening Array delimiter of "{", rather than the default "]".
options.array_delimiters.open = "{";
// Use a custom closing Array delimiter of "}", rather than the default "]".
options.array_delimiters.close = "}";

std::vector<bool> is_valid = {true, true, false, true, false};
std::vector<int32_t> values = {1, 2, 3, 4, 5};
static const char* expected = R"expected({
1,
2,
null,
4,
null
})expected";
CheckPrimitive<Int32Type, int32_t>(options, is_valid, values, expected, false);
}

TEST_F(TestPrettyPrint, Int8) {
static const char* expected = R"expected([
0,
Expand Down Expand Up @@ -1131,6 +1150,60 @@ TEST_F(TestPrettyPrint, ChunkedArrayCustomElementDelimiter) {
}
}

TEST_F(TestPrettyPrint, ChunkedArrayCustomOpenCloseDelimiter) {
PrettyPrintOptions options{};
// Use a custom opening Array delimiter of "{", rather than the default "]".
options.array_delimiters.open = "{";
// Use a custom closing Array delimiter of "}", rather than the default "]".
options.array_delimiters.close = "}";
// Use a custom opening ChunkedArray delimiter of "<", rather than the default "]".
options.chunked_array_delimiters.open = "<";
// Use a custom closing ChunkedArray delimiter of ">", rather than the default "]".
options.chunked_array_delimiters.close = ">";

const auto chunk = ArrayFromJSON(int32(), "[1, 2, null, 4, null]");

// ChunkedArray with 1 chunk
{
const ChunkedArray chunked_array(chunk);

static const char* expected = R"expected(<
{
1,
2,
null,
4,
null
}
>)expected";
CheckStream(chunked_array, options, expected);
}

// ChunkedArray with 2 chunks
{
const ChunkedArray chunked_array({chunk, chunk});

static const char* expected = R"expected(<
{
1,
2,
null,
4,
null
},
{
1,
2,
null,
4,
null
}
>)expected";

CheckStream(chunked_array, options, expected);
}
}

TEST_F(TestPrettyPrint, TablePrimitive) {
std::shared_ptr<Field> int_field = field("column", int32());
auto array = ArrayFromJSON(int_field->type(), "[0, 1, null, 3, null]");
Expand Down

0 comments on commit 246735f

Please sign in to comment.