This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 6a0fb7a0cf GH-15195: [C++][FlightRPC][Python] Add ToString/Equals for
Flight types (#15196)
6a0fb7a0cf is described below
commit 6a0fb7a0cf29ace28962674fa39b658aa096efed
Author: David Li <[email protected]>
AuthorDate: Wed Feb 22 16:55:50 2023 -0500
GH-15195: [C++][FlightRPC][Python] Add ToString/Equals for Flight types
(#15196)
* Closes: #15195
Authored-by: David Li <[email protected]>
Signed-off-by: David Li <[email protected]>
---
c_glib/test/flight/test-command-descriptor.rb | 2 +-
c_glib/test/flight/test-path-descriptor.rb | 2 +-
cpp/src/arrow/flight/flight_internals_test.cc | 355 ++++++++++++++++++--------
cpp/src/arrow/flight/perf_server.cc | 6 +-
cpp/src/arrow/flight/test_util.cc | 29 +--
cpp/src/arrow/flight/test_util.h | 6 +-
cpp/src/arrow/flight/types.cc | 99 ++++++-
cpp/src/arrow/flight/types.h | 28 +-
python/pyarrow/_flight.pyx | 54 ++--
python/pyarrow/includes/libarrow_flight.pxd | 9 +
python/pyarrow/tests/test_flight.py | 73 ++++++
11 files changed, 502 insertions(+), 161 deletions(-)
diff --git a/c_glib/test/flight/test-command-descriptor.rb
b/c_glib/test/flight/test-command-descriptor.rb
index 316973287f..8fcf2d65fc 100644
--- a/c_glib/test/flight/test-command-descriptor.rb
+++ b/c_glib/test/flight/test-command-descriptor.rb
@@ -22,7 +22,7 @@ class TestFlightCommandDescriptor < Test::Unit::TestCase
def test_to_s
descriptor = ArrowFlight::CommandDescriptor.new("command")
- assert_equal("FlightDescriptor<cmd = 'command'>",
+ assert_equal("<FlightDescriptor cmd='command'>",
descriptor.to_s)
end
diff --git a/c_glib/test/flight/test-path-descriptor.rb
b/c_glib/test/flight/test-path-descriptor.rb
index 441fc7bb04..ccee99cfbf 100644
--- a/c_glib/test/flight/test-path-descriptor.rb
+++ b/c_glib/test/flight/test-path-descriptor.rb
@@ -22,7 +22,7 @@ class TestFlightPathDescriptor < Test::Unit::TestCase
def test_to_s
descriptor = ArrowFlight::PathDescriptor.new(["a", "b", "c"])
- assert_equal("FlightDescriptor<path = 'a/b/c'>",
+ assert_equal("<FlightDescriptor path='a/b/c'>",
descriptor.to_s)
end
diff --git a/cpp/src/arrow/flight/flight_internals_test.cc
b/cpp/src/arrow/flight/flight_internals_test.cc
index 9818cb2079..3fef31b0ea 100644
--- a/cpp/src/arrow/flight/flight_internals_test.cc
+++ b/cpp/src/arrow/flight/flight_internals_test.cc
@@ -18,6 +18,8 @@
// ----------------------------------------------------------------------
// Tests for Flight which don't actually spin up a client/server
+#include <type_traits>
+
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -40,40 +42,250 @@ namespace pb = arrow::flight::protocol;
// ----------------------------------------------------------------------
// Core Flight types
-TEST(FlightTypes, FlightDescriptor) {
- auto a = FlightDescriptor::Command("select * from table");
- auto b = FlightDescriptor::Command("select * from table");
- auto c = FlightDescriptor::Command("select foo from table");
- auto d = FlightDescriptor::Path({"foo", "bar"});
- auto e = FlightDescriptor::Path({"foo", "baz"});
- auto f = FlightDescriptor::Path({"foo", "baz"});
-
- ASSERT_EQ(a.ToString(), "FlightDescriptor<cmd = 'select * from table'>");
- ASSERT_EQ(d.ToString(), "FlightDescriptor<path = 'foo/bar'>");
- ASSERT_TRUE(a.Equals(b));
- ASSERT_FALSE(a.Equals(c));
- ASSERT_FALSE(a.Equals(d));
- ASSERT_FALSE(d.Equals(e));
- ASSERT_TRUE(e.Equals(f));
-}
+template <typename PbType, typename FlightType>
+void TestRoundtrip(const std::vector<FlightType>& values,
+ const std::vector<std::string>& reprs) {
+ for (size_t i = 0; i < values.size(); i++) {
+ ARROW_SCOPED_TRACE("LHS = ", values[i].ToString());
+ for (size_t j = 0; j < values.size(); j++) {
+ ARROW_SCOPED_TRACE("RHS = ", values[j].ToString());
+ if (i == j) {
+ EXPECT_EQ(values[i], values[j]);
+ EXPECT_TRUE(values[i].Equals(values[j]));
+ } else {
+ EXPECT_NE(values[i], values[j]);
+ EXPECT_FALSE(values[i].Equals(values[j]));
+ }
+ }
+ EXPECT_EQ(values[i].ToString(), reprs[i]);
+
+ ASSERT_OK_AND_ASSIGN(std::string serialized,
values[i].SerializeToString());
+ ASSERT_OK_AND_ASSIGN(auto deserialized,
FlightType::Deserialize(serialized));
+ if constexpr (std::is_same_v<FlightType, FlightInfo>) {
+ EXPECT_EQ(values[i], *deserialized);
+ } else {
+ EXPECT_EQ(values[i], deserialized);
+ }
// This tests the internal protobuf types which don't get exported in the
Flight DLL.
#ifndef _WIN32
-TEST(FlightTypes, FlightDescriptorToFromProto) {
- FlightDescriptor descr_test;
- pb::FlightDescriptor pb_descr;
-
- FlightDescriptor descr1{FlightDescriptor::PATH, "", {"foo", "bar"}};
- ASSERT_OK(internal::ToProto(descr1, &pb_descr));
- ASSERT_OK(internal::FromProto(pb_descr, &descr_test));
- ASSERT_EQ(descr1, descr_test);
-
- FlightDescriptor descr2{FlightDescriptor::CMD, "command", {}};
- ASSERT_OK(internal::ToProto(descr2, &pb_descr));
- ASSERT_OK(internal::FromProto(pb_descr, &descr_test));
- ASSERT_EQ(descr2, descr_test);
-}
+ PbType pb_value;
+ ASSERT_OK(internal::ToProto(values[i], &pb_value));
+
+ if constexpr (std::is_same_v<FlightType, FlightInfo>) {
+ FlightInfo::Data data;
+ ASSERT_OK(internal::FromProto(pb_value, &data));
+ FlightInfo value(std::move(data));
+ EXPECT_EQ(values[i], value);
+ } else if constexpr (std::is_same_v<FlightType, SchemaResult>) {
+ std::string data;
+ ASSERT_OK(internal::FromProto(pb_value, &data));
+ SchemaResult value(std::move(data));
+ EXPECT_EQ(values[i], value);
+ } else {
+ FlightType value;
+ ASSERT_OK(internal::FromProto(pb_value, &value));
+ EXPECT_EQ(values[i], value);
+ }
#endif
+ }
+}
+
+TEST(FlightTypes, Action) {
+ std::vector<Action> values = {
+ {"type", Buffer::FromString("")},
+ {"type", Buffer::FromString("foo")},
+ {"type", Buffer::FromString("bar")},
+ };
+ std::vector<std::string> reprs = {
+ "<Action type='type' body=(0 bytes)>",
+ "<Action type='type' body=(3 bytes)>",
+ "<Action type='type' body=(3 bytes)>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::Action>(values, reprs));
+
+ // This doesn't roundtrip since we don't differentiate between no
+ // body and empty body on the wire
+ Action action{"", nullptr};
+ ASSERT_EQ("<Action type='' body=(nullptr)>", action.ToString());
+ ASSERT_NE(values[0], action);
+ ASSERT_EQ(action, action);
+}
+
+TEST(FlightTypes, ActionType) {
+ std::vector<ActionType> values = {
+ {"", ""},
+ {"type", ""},
+ {"type", "descr"},
+ {"", "descr"},
+ };
+ std::vector<std::string> reprs = {
+ "<ActionType type='' description=''>",
+ "<ActionType type='type' description=''>",
+ "<ActionType type='type' description='descr'>",
+ "<ActionType type='' description='descr'>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::ActionType>(values, reprs));
+}
+
+TEST(FlightTypes, BasicAuth) {
+ std::vector<BasicAuth> values = {
+ {"", ""},
+ {"user", ""},
+ {"", "pass"},
+ {"user", "pass"},
+ };
+ std::vector<std::string> reprs = {
+ "<BasicAuth username='' password=(redacted)>",
+ "<BasicAuth username='user' password=(redacted)>",
+ "<BasicAuth username='' password=(redacted)>",
+ "<BasicAuth username='user' password=(redacted)>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::BasicAuth>(values, reprs));
+}
+
+TEST(FlightTypes, Criteria) {
+ std::vector<Criteria> values = {{""}, {"criteria"}};
+ std::vector<std::string> reprs = {"<Criteria expression=''>",
+ "<Criteria expression='criteria'>"};
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::Criteria>(values, reprs));
+}
+
+TEST(FlightTypes, FlightDescriptor) {
+ std::vector<FlightDescriptor> values = {
+ FlightDescriptor::Command(""),
+ FlightDescriptor::Command("\x01"),
+ FlightDescriptor::Command("select * from table"),
+ FlightDescriptor::Command("select foo from table"),
+ FlightDescriptor::Path({}),
+ FlightDescriptor::Path({"foo", "baz"}),
+ };
+ std::vector<std::string> reprs = {
+ "<FlightDescriptor cmd=''>",
+ "<FlightDescriptor cmd='\x01'>",
+ "<FlightDescriptor cmd='select * from table'>",
+ "<FlightDescriptor cmd='select foo from table'>",
+ "<FlightDescriptor path=''>",
+ "<FlightDescriptor path='foo/baz'>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::FlightDescriptor>(values, reprs));
+}
+
+TEST(FlightTypes, FlightEndpoint) {
+ ASSERT_OK_AND_ASSIGN(auto location1, Location::ForGrpcTcp("localhost",
1024));
+ ASSERT_OK_AND_ASSIGN(auto location2, Location::ForGrpcTls("localhost",
1024));
+ std::vector<FlightEndpoint> values = {
+ {{""}, {}},
+ {{"foo"}, {}},
+ {{"bar"}, {}},
+ {{"foo"}, {location1}},
+ {{"bar"}, {location1}},
+ {{"foo"}, {location2}},
+ {{"foo"}, {location1, location2}},
+ };
+ std::vector<std::string> reprs = {
+ "<FlightEndpoint ticket=<Ticket ticket=''> locations=[]>",
+ "<FlightEndpoint ticket=<Ticket ticket='foo'> locations=[]>",
+ "<FlightEndpoint ticket=<Ticket ticket='bar'> locations=[]>",
+ "<FlightEndpoint ticket=<Ticket ticket='foo'> locations="
+ "[grpc+tcp://localhost:1024]>",
+ "<FlightEndpoint ticket=<Ticket ticket='bar'> locations="
+ "[grpc+tcp://localhost:1024]>",
+ "<FlightEndpoint ticket=<Ticket ticket='foo'> locations="
+ "[grpc+tls://localhost:1024]>",
+ "<FlightEndpoint ticket=<Ticket ticket='foo'> locations="
+ "[grpc+tcp://localhost:1024, grpc+tls://localhost:1024]>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::FlightEndpoint>(values, reprs));
+}
+
+TEST(FlightTypes, FlightInfo) {
+ ASSERT_OK_AND_ASSIGN(auto location, Location::ForGrpcTcp("localhost", 1234));
+ Schema schema1({field("ints", int64())});
+ Schema schema2({});
+ auto desc1 = FlightDescriptor::Command("foo");
+ auto desc2 = FlightDescriptor::Command("bar");
+ auto endpoint1 = FlightEndpoint{Ticket{"foo"}, {}};
+ auto endpoint2 = FlightEndpoint{Ticket{"foo"}, {location}};
+ std::vector<FlightInfo> values = {
+ MakeFlightInfo(schema1, desc1, {}, -1, -1),
+ MakeFlightInfo(schema1, desc2, {}, -1, -1),
+ MakeFlightInfo(schema2, desc1, {}, -1, -1),
+ MakeFlightInfo(schema1, desc1, {endpoint1}, -1, 42),
+ MakeFlightInfo(schema1, desc2, {endpoint1, endpoint2}, 64, -1),
+ };
+ std::vector<std::string> reprs = {
+ "<FlightInfo schema=(serialized) descriptor=<FlightDescriptor cmd='foo'>
"
+ "endpoints=[] total_records=-1 total_bytes=-1>",
+ "<FlightInfo schema=(serialized) descriptor=<FlightDescriptor cmd='bar'>
"
+ "endpoints=[] total_records=-1 total_bytes=-1>",
+ "<FlightInfo schema=(serialized) descriptor=<FlightDescriptor cmd='foo'>
"
+ "endpoints=[] total_records=-1 total_bytes=-1>",
+ "<FlightInfo schema=(serialized) descriptor=<FlightDescriptor cmd='foo'>
"
+ "endpoints=[<FlightEndpoint ticket=<Ticket ticket='foo'> locations=[]>] "
+ "total_records=-1 total_bytes=42>",
+ "<FlightInfo schema=(serialized) descriptor=<FlightDescriptor cmd='bar'>
"
+ "endpoints=[<FlightEndpoint ticket=<Ticket ticket='foo'> locations=[]>, "
+ "<FlightEndpoint ticket=<Ticket ticket='foo'> locations="
+ "[grpc+tcp://localhost:1234]>] total_records=64 total_bytes=-1>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::FlightInfo>(values, reprs));
+}
+
+TEST(FlightTypes, Result) {
+ std::vector<Result> values = {
+ {Buffer::FromString("")},
+ {Buffer::FromString("foo")},
+ {Buffer::FromString("bar")},
+ };
+ std::vector<std::string> reprs = {
+ "<Result body=(0 bytes)>",
+ "<Result body=(3 bytes)>",
+ "<Result body=(3 bytes)>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::Result>(values, reprs));
+
+ // This doesn't roundtrip since we don't differentiate between no
+ // body and empty body on the wire
+ Result result{nullptr};
+ ASSERT_EQ("<Result body=(nullptr)>", result.ToString());
+ ASSERT_NE(values[0], result);
+ ASSERT_EQ(result, result);
+}
+
+TEST(FlightTypes, SchemaResult) {
+ ASSERT_OK_AND_ASSIGN(auto value1, SchemaResult::Make(Schema({})));
+ ASSERT_OK_AND_ASSIGN(auto value2, SchemaResult::Make(Schema({field("foo",
int64())})));
+ std::vector<SchemaResult> values = {*value1, *value2};
+ std::vector<std::string> reprs = {
+ "<SchemaResult raw_schema=(serialized)>",
+ "<SchemaResult raw_schema=(serialized)>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::SchemaResult>(values, reprs));
+}
+
+TEST(FlightTypes, Ticket) {
+ std::vector<Ticket> values = {
+ {""},
+ {"foo"},
+ {"bar"},
+ };
+ std::vector<std::string> reprs = {
+ "<Ticket ticket=''>",
+ "<Ticket ticket='foo'>",
+ "<Ticket ticket='bar'>",
+ };
+
+ ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::Ticket>(values, reprs));
+}
// ARROW-6017: we should be able to construct locations for unknown
// schemes
@@ -82,89 +294,6 @@ TEST(FlightTypes, LocationUnknownScheme) {
ASSERT_OK(Location::Parse("https://example.com/foo"));
}
-TEST(FlightTypes, RoundTripTypes) {
- ActionType action_type{"action-type1", "action-type1-description"};
- ASSERT_OK_AND_ASSIGN(std::string action_type_serialized,
- action_type.SerializeToString());
- ASSERT_OK_AND_ASSIGN(ActionType action_type_deserialized,
- ActionType::Deserialize(action_type_serialized));
- ASSERT_EQ(action_type, action_type_deserialized);
-
- Criteria criteria{"criteria1"};
- ASSERT_OK_AND_ASSIGN(std::string criteria_serialized,
criteria.SerializeToString());
- ASSERT_OK_AND_ASSIGN(Criteria criteria_deserialized,
- Criteria::Deserialize(criteria_serialized));
- ASSERT_EQ(criteria, criteria_deserialized);
-
- Action action{"action1", Buffer::FromString("action1-content")};
- ASSERT_OK_AND_ASSIGN(std::string action_serialized,
action.SerializeToString());
- ASSERT_OK_AND_ASSIGN(Action action_deserialized,
- Action::Deserialize(action_serialized));
- ASSERT_EQ(action, action_deserialized);
-
- Result result{Buffer::FromString("result1-content")};
- ASSERT_OK_AND_ASSIGN(std::string result_serialized,
result.SerializeToString());
- ASSERT_OK_AND_ASSIGN(Result result_deserialized,
- Result::Deserialize(result_serialized));
- ASSERT_EQ(result, result_deserialized);
-
- BasicAuth basic_auth{"username1", "password1"};
- ASSERT_OK_AND_ASSIGN(std::string basic_auth_serialized,
basic_auth.SerializeToString());
- ASSERT_OK_AND_ASSIGN(BasicAuth basic_auth_deserialized,
- BasicAuth::Deserialize(basic_auth_serialized));
- ASSERT_EQ(basic_auth, basic_auth_deserialized);
-
- SchemaResult schema_result{"schema_result1"};
- ASSERT_OK_AND_ASSIGN(std::string schema_result_serialized,
- schema_result.SerializeToString());
- ASSERT_OK_AND_ASSIGN(SchemaResult schema_result_deserialized,
- SchemaResult::Deserialize(schema_result_serialized));
- ASSERT_EQ(schema_result, schema_result_deserialized);
-
- Ticket ticket{"foo"};
- ASSERT_OK_AND_ASSIGN(std::string ticket_serialized,
ticket.SerializeToString());
- ASSERT_OK_AND_ASSIGN(Ticket ticket_deserialized,
- Ticket::Deserialize(ticket_serialized));
- ASSERT_EQ(ticket, ticket_deserialized);
-
- FlightDescriptor desc = FlightDescriptor::Command("select * from foo;");
- ASSERT_OK_AND_ASSIGN(std::string desc_serialized, desc.SerializeToString());
- ASSERT_OK_AND_ASSIGN(FlightDescriptor desc_deserialized,
- FlightDescriptor::Deserialize(desc_serialized));
- ASSERT_EQ(desc, desc_deserialized);
-
- desc = FlightDescriptor::Path({"a", "b", "test.arrow"});
- ASSERT_OK_AND_ASSIGN(desc_serialized, desc.SerializeToString());
- ASSERT_OK_AND_ASSIGN(desc_deserialized,
FlightDescriptor::Deserialize(desc_serialized));
- ASSERT_EQ(desc, desc_deserialized);
-
- FlightInfo::Data data;
- std::shared_ptr<Schema> schema =
- arrow::schema({field("a", int64()), field("b", int64()), field("c",
int64()),
- field("d", int64())});
- ASSERT_OK_AND_ASSIGN(auto location1, Location::ForGrpcTcp("localhost",
10010));
- ASSERT_OK_AND_ASSIGN(auto location2, Location::ForGrpcTls("localhost",
10010));
- ASSERT_OK_AND_ASSIGN(auto location3,
Location::ForGrpcUnix("/tmp/test.sock"));
- std::vector<FlightEndpoint> endpoints{FlightEndpoint{ticket, {location1,
location2}},
- FlightEndpoint{ticket, {location3}}};
- ASSERT_OK(MakeFlightInfo(*schema, desc, endpoints, -1, -1, &data));
- auto info = std::make_unique<FlightInfo>(data);
- ASSERT_OK_AND_ASSIGN(std::string info_serialized, info->SerializeToString());
- ASSERT_OK_AND_ASSIGN(std::unique_ptr<FlightInfo> info_deserialized,
- FlightInfo::Deserialize(info_serialized));
- ASSERT_EQ(info->descriptor(), info_deserialized->descriptor());
- ASSERT_EQ(info->endpoints(), info_deserialized->endpoints());
- ASSERT_EQ(info->total_records(), info_deserialized->total_records());
- ASSERT_EQ(info->total_bytes(), info_deserialized->total_bytes());
-
- FlightEndpoint flight_endpoint{ticket, {location1, location2}};
- ASSERT_OK_AND_ASSIGN(std::string flight_endpoint_serialized,
- flight_endpoint.SerializeToString());
- ASSERT_OK_AND_ASSIGN(FlightEndpoint flight_endpoint_deserialized,
-
FlightEndpoint::Deserialize(flight_endpoint_serialized));
- ASSERT_EQ(flight_endpoint, flight_endpoint_deserialized);
-}
-
TEST(FlightTypes, RoundtripStatus) {
// Make sure status codes round trip through our conversions
diff --git a/cpp/src/arrow/flight/perf_server.cc
b/cpp/src/arrow/flight/perf_server.cc
index eb6ac92b83..db3e8b150e 100644
--- a/cpp/src/arrow/flight/perf_server.cc
+++ b/cpp/src/arrow/flight/perf_server.cc
@@ -195,10 +195,8 @@ class FlightPerfServer : public FlightServerBase {
uint64_t total_records =
perf_request.stream_count() * perf_request.records_per_stream();
- FlightInfo::Data data;
- RETURN_NOT_OK(
- MakeFlightInfo(*perf_schema_, request, endpoints, total_records, -1,
&data));
- *info = std::make_unique<FlightInfo>(data);
+ *info = std::make_unique<FlightInfo>(
+ MakeFlightInfo(*perf_schema_, request, endpoints, total_records, -1));
return Status::OK();
}
diff --git a/cpp/src/arrow/flight/test_util.cc
b/cpp/src/arrow/flight/test_util.cc
index a478aed998..0d6c28b296 100644
--- a/cpp/src/arrow/flight/test_util.cc
+++ b/cpp/src/arrow/flight/test_util.cc
@@ -510,14 +510,12 @@ std::unique_ptr<FlightServerBase> ExampleTestServer() {
return std::make_unique<FlightTestServer>();
}
-Status MakeFlightInfo(const Schema& schema, const FlightDescriptor& descriptor,
- const std::vector<FlightEndpoint>& endpoints, int64_t
total_records,
- int64_t total_bytes, FlightInfo::Data* out) {
- out->descriptor = descriptor;
- out->endpoints = endpoints;
- out->total_records = total_records;
- out->total_bytes = total_bytes;
- return internal::SchemaToString(schema, &out->schema);
+FlightInfo MakeFlightInfo(const Schema& schema, const FlightDescriptor&
descriptor,
+ const std::vector<FlightEndpoint>& endpoints,
+ int64_t total_records, int64_t total_bytes) {
+ EXPECT_OK_AND_ASSIGN(auto info, FlightInfo::Make(schema, descriptor,
endpoints,
+ total_records,
total_bytes));
+ return info;
}
NumberingStream::NumberingStream(std::unique_ptr<FlightDataStream> stream)
@@ -585,8 +583,6 @@ std::vector<FlightInfo> ExampleFlightInfo() {
Location location4 = *Location::ForGrpcTcp("foo4.bar.com", 12345);
Location location5 = *Location::ForGrpcTcp("foo5.bar.com", 12345);
- FlightInfo::Data flight1, flight2, flight3, flight4;
-
FlightEndpoint endpoint1({{"ticket-ints-1"}, {location1}});
FlightEndpoint endpoint2({{"ticket-ints-2"}, {location2}});
FlightEndpoint endpoint3({{"ticket-cmd"}, {location3}});
@@ -603,13 +599,12 @@ std::vector<FlightInfo> ExampleFlightInfo() {
auto schema3 = ExampleDictSchema();
auto schema4 = ExampleFloatSchema();
- ARROW_EXPECT_OK(
- MakeFlightInfo(*schema1, descr1, {endpoint1, endpoint2}, 1000, 100000,
&flight1));
- ARROW_EXPECT_OK(MakeFlightInfo(*schema2, descr2, {endpoint3}, 1000, 100000,
&flight2));
- ARROW_EXPECT_OK(MakeFlightInfo(*schema3, descr3, {endpoint4}, -1, -1,
&flight3));
- ARROW_EXPECT_OK(MakeFlightInfo(*schema4, descr4, {endpoint5}, 1000, 100000,
&flight4));
- return {FlightInfo(flight1), FlightInfo(flight2), FlightInfo(flight3),
- FlightInfo(flight4)};
+ return {
+ MakeFlightInfo(*schema1, descr1, {endpoint1, endpoint2}, 1000, 100000),
+ MakeFlightInfo(*schema2, descr2, {endpoint3}, 1000, 100000),
+ MakeFlightInfo(*schema3, descr3, {endpoint4}, -1, -1),
+ MakeFlightInfo(*schema4, descr4, {endpoint5}, 1000, 100000),
+ };
}
Status ExampleIntBatches(RecordBatchVector* out) {
diff --git a/cpp/src/arrow/flight/test_util.h b/cpp/src/arrow/flight/test_util.h
index c0c6d7514e..679e04fa1b 100644
--- a/cpp/src/arrow/flight/test_util.h
+++ b/cpp/src/arrow/flight/test_util.h
@@ -190,9 +190,9 @@ ARROW_FLIGHT_EXPORT
std::vector<ActionType> ExampleActionTypes();
ARROW_FLIGHT_EXPORT
-Status MakeFlightInfo(const Schema& schema, const FlightDescriptor& descriptor,
- const std::vector<FlightEndpoint>& endpoints, int64_t
total_records,
- int64_t total_bytes, FlightInfo::Data* out);
+FlightInfo MakeFlightInfo(const Schema& schema, const FlightDescriptor&
descriptor,
+ const std::vector<FlightEndpoint>& endpoints,
+ int64_t total_records, int64_t total_bytes);
// ----------------------------------------------------------------------
// A pair of authentication handlers that check for a predefined password
diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc
index a09f09ff9d..b051ec7081 100644
--- a/cpp/src/arrow/flight/types.cc
+++ b/cpp/src/arrow/flight/types.cc
@@ -29,6 +29,7 @@
#include "arrow/ipc/reader.h"
#include "arrow/status.h"
#include "arrow/table.h"
+#include "arrow/util/string_builder.h"
#include "arrow/util/uri.h"
namespace arrow {
@@ -105,11 +106,11 @@ bool FlightDescriptor::Equals(const FlightDescriptor&
other) const {
std::string FlightDescriptor::ToString() const {
std::stringstream ss;
- ss << "FlightDescriptor<";
+ ss << "<FlightDescriptor ";
switch (type) {
case PATH: {
+ ss << "path='";
bool first = true;
- ss << "path = '";
for (const auto& p : path) {
if (!first) {
ss << "/";
@@ -121,7 +122,7 @@ std::string FlightDescriptor::ToString() const {
break;
}
case CMD:
- ss << "cmd = '" << cmd << "'";
+ ss << "cmd='" << cmd << "'";
break;
default:
break;
@@ -161,6 +162,10 @@ Status SchemaResult::GetSchema(ipc::DictionaryMemo*
dictionary_memo,
return GetSchema(dictionary_memo).Value(out);
}
+std::string SchemaResult::ToString() const {
+ return "<SchemaResult raw_schema=(serialized)>";
+}
+
bool SchemaResult::Equals(const SchemaResult& other) const {
return raw_schema_ == other.raw_schema_;
}
@@ -225,6 +230,12 @@ Status FlightDescriptor::Deserialize(const std::string&
serialized,
return Deserialize(serialized).Value(out);
}
+std::string Ticket::ToString() const {
+ std::stringstream ss;
+ ss << "<Ticket ticket='" << ticket << "'>";
+ return ss.str();
+}
+
bool Ticket::Equals(const Ticket& other) const { return ticket ==
other.ticket; }
arrow::Result<std::string> Ticket::SerializeToString() const {
@@ -326,6 +337,36 @@ Status FlightInfo::Deserialize(const std::string&
serialized,
return Deserialize(serialized).Value(out);
}
+std::string FlightInfo::ToString() const {
+ std::stringstream ss;
+ ss << "<FlightInfo schema=";
+ if (schema_) {
+ ss << schema_->ToString();
+ } else {
+ ss << "(serialized)";
+ }
+ ss << " descriptor=" << data_.descriptor.ToString();
+ ss << " endpoints=[";
+ bool first = true;
+ for (const auto& endpoint : data_.endpoints) {
+ if (!first) ss << ", ";
+ ss << endpoint.ToString();
+ first = false;
+ }
+ ss << "] total_records=" << data_.total_records;
+ ss << " total_bytes=" << data_.total_bytes;
+ ss << '>';
+ return ss.str();
+}
+
+bool FlightInfo::Equals(const FlightInfo& other) const {
+ return data_.schema == other.data_.schema &&
+ data_.descriptor == other.data_.descriptor &&
+ data_.endpoints == other.data_.endpoints &&
+ data_.total_records == other.data_.total_records &&
+ data_.total_bytes == other.data_.total_bytes;
+}
+
Location::Location() { uri_ = std::make_shared<arrow::internal::Uri>(); }
Status FlightListing::Next(std::unique_ptr<FlightInfo>* info) {
@@ -393,6 +434,20 @@ bool Location::Equals(const Location& other) const {
return ToString() == other.ToString();
}
+std::string FlightEndpoint::ToString() const {
+ std::stringstream ss;
+ ss << "<FlightEndpoint ticket=" << ticket.ToString();
+ ss << " locations=[";
+ bool first = true;
+ for (const auto& location : locations) {
+ if (!first) ss << ", ";
+ ss << location.ToString();
+ first = false;
+ }
+ ss << "]>";
+ return ss.str();
+}
+
bool FlightEndpoint::Equals(const FlightEndpoint& other) const {
return ticket == other.ticket && locations == other.locations;
}
@@ -423,6 +478,11 @@ arrow::Result<FlightEndpoint>
FlightEndpoint::Deserialize(std::string_view seria
return out;
}
+std::string ActionType::ToString() const {
+ return arrow::util::StringBuilder("<ActionType type='", type, "'
description='",
+ description, "'>");
+}
+
bool ActionType::Equals(const ActionType& other) const {
return type == other.type && description == other.description;
}
@@ -453,6 +513,10 @@ arrow::Result<ActionType>
ActionType::Deserialize(std::string_view serialized) {
return out;
}
+std::string Criteria::ToString() const {
+ return arrow::util::StringBuilder("<Criteria expression='", expression,
"'>");
+}
+
bool Criteria::Equals(const Criteria& other) const {
return expression == other.expression;
}
@@ -483,6 +547,19 @@ arrow::Result<Criteria>
Criteria::Deserialize(std::string_view serialized) {
return out;
}
+std::string Action::ToString() const {
+ std::stringstream ss;
+ ss << "<Action type='" << type;
+ ss << "' body=";
+ if (body) {
+ ss << "(" << body->size() << " bytes)";
+ } else {
+ ss << "(nullptr)";
+ }
+ ss << '>';
+ return ss.str();
+}
+
bool Action::Equals(const Action& other) const {
return (type == other.type) &&
((body == other.body) || (body && other.body &&
body->Equals(*other.body)));
@@ -514,6 +591,17 @@ arrow::Result<Action> Action::Deserialize(std::string_view
serialized) {
return out;
}
+std::string Result::ToString() const {
+ std::stringstream ss;
+ ss << "<Result body=";
+ if (body) {
+ ss << "(" << body->size() << " bytes)>";
+ } else {
+ ss << "(nullptr)>";
+ }
+ return ss.str();
+}
+
bool Result::Equals(const Result& other) const {
return (body == other.body) || (body && other.body &&
body->Equals(*other.body));
}
@@ -638,6 +726,11 @@ arrow::Result<std::unique_ptr<Result>>
SimpleResultStream::Next() {
return std::make_unique<Result>(std::move(results_[position_++]));
}
+std::string BasicAuth::ToString() const {
+ return arrow::util::StringBuilder("<BasicAuth username='", username,
+ "' password=(redacted)>");
+}
+
bool BasicAuth::Equals(const BasicAuth& other) const {
return (username == other.username) && (password == other.password);
}
diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h
index 6957c5992a..39353bcb99 100644
--- a/cpp/src/arrow/flight/types.h
+++ b/cpp/src/arrow/flight/types.h
@@ -140,6 +140,7 @@ struct ARROW_FLIGHT_EXPORT ActionType {
/// \brief A human-readable description of the action.
std::string description;
+ std::string ToString() const;
bool Equals(const ActionType& other) const;
friend bool operator==(const ActionType& left, const ActionType& right) {
@@ -161,6 +162,7 @@ struct ARROW_FLIGHT_EXPORT Criteria {
/// Opaque criteria expression, dependent on server implementation
std::string expression;
+ std::string ToString() const;
bool Equals(const Criteria& other) const;
friend bool operator==(const Criteria& left, const Criteria& right) {
@@ -185,6 +187,7 @@ struct ARROW_FLIGHT_EXPORT Action {
/// The action content as a Buffer
std::shared_ptr<Buffer> body;
+ std::string ToString() const;
bool Equals(const Action& other) const;
friend bool operator==(const Action& left, const Action& right) {
@@ -205,6 +208,7 @@ struct ARROW_FLIGHT_EXPORT Action {
struct ARROW_FLIGHT_EXPORT Result {
std::shared_ptr<Buffer> body;
+ std::string ToString() const;
bool Equals(const Result& other) const;
friend bool operator==(const Result& left, const Result& right) {
@@ -226,6 +230,7 @@ struct ARROW_FLIGHT_EXPORT BasicAuth {
std::string username;
std::string password;
+ std::string ToString() const;
bool Equals(const BasicAuth& other) const;
friend bool operator==(const BasicAuth& left, const BasicAuth& right) {
@@ -312,6 +317,7 @@ struct ARROW_FLIGHT_EXPORT FlightDescriptor {
struct ARROW_FLIGHT_EXPORT Ticket {
std::string ticket;
+ std::string ToString() const;
bool Equals(const Ticket& other) const;
friend bool operator==(const Ticket& left, const Ticket& right) {
@@ -429,6 +435,7 @@ struct ARROW_FLIGHT_EXPORT FlightEndpoint {
/// generated
std::vector<Location> locations;
+ std::string ToString() const;
bool Equals(const FlightEndpoint& other) const;
friend bool operator==(const FlightEndpoint& left, const FlightEndpoint&
right) {
@@ -469,7 +476,7 @@ struct ARROW_FLIGHT_EXPORT SchemaResult {
/// \brief return schema
/// \param[in,out] dictionary_memo for dictionary bookkeeping, will
/// be modified
- /// \return Arrrow result with the reconstructed Schema
+ /// \return Arrow result with the reconstructed Schema
arrow::Result<std::shared_ptr<Schema>> GetSchema(
ipc::DictionaryMemo* dictionary_memo) const;
@@ -479,6 +486,7 @@ struct ARROW_FLIGHT_EXPORT SchemaResult {
const std::string& serialized_schema() const { return raw_schema_; }
+ std::string ToString() const;
bool Equals(const SchemaResult& other) const;
friend bool operator==(const SchemaResult& left, const SchemaResult& right) {
@@ -510,9 +518,7 @@ class ARROW_FLIGHT_EXPORT FlightInfo {
int64_t total_bytes;
};
- explicit FlightInfo(const Data& data) : data_(data),
reconstructed_schema_(false) {}
- explicit FlightInfo(Data&& data)
- : data_(std::move(data)), reconstructed_schema_(false) {}
+ explicit FlightInfo(Data data) : data_(std::move(data)),
reconstructed_schema_(false) {}
/// \brief Factory method to construct a FlightInfo.
static arrow::Result<FlightInfo> Make(const Schema& schema,
@@ -568,6 +574,20 @@ class ARROW_FLIGHT_EXPORT FlightInfo {
static Status Deserialize(const std::string& serialized,
std::unique_ptr<FlightInfo>* out);
+ std::string ToString() const;
+
+ /// Compare two FlightInfo for equality. This will compare the
+ /// serialized schema representations, NOT the logical equality of
+ /// the schemas.
+ bool Equals(const FlightInfo& other) const;
+
+ friend bool operator==(const FlightInfo& left, const FlightInfo& right) {
+ return left.Equals(right);
+ }
+ friend bool operator!=(const FlightInfo& left, const FlightInfo& right) {
+ return !(left == right);
+ }
+
private:
Data data_;
mutable std::shared_ptr<Schema> schema_;
diff --git a/python/pyarrow/_flight.pyx b/python/pyarrow/_flight.pyx
index 7feee8cf7b..db40d35f5c 100644
--- a/python/pyarrow/_flight.pyx
+++ b/python/pyarrow/_flight.pyx
@@ -314,6 +314,10 @@ cdef class Action(_Weakrefable):
def __eq__(self, Action other):
return self.action == other.action
+ def __repr__(self):
+ return (f"<pyarrow.flight.Action type={self.type!r} "
+ f"body=({self.body.size} bytes)>")
+
_ActionType = collections.namedtuple('_ActionType', ['type', 'description'])
@@ -377,6 +381,9 @@ cdef class Result(_Weakrefable):
def __eq__(self, Result other):
return deref(self.result.get()) == deref(other.result.get())
+ def __repr__(self):
+ return f"<pyarrow.flight.Result body=({self.body.size} bytes)>"
+
cdef class BasicAuth(_Weakrefable):
"""A container for basic auth."""
@@ -420,6 +427,10 @@ cdef class BasicAuth(_Weakrefable):
def __eq__(self, BasicAuth other):
return deref(self.basic_auth.get()) == deref(other.basic_auth.get())
+ def __repr__(self):
+ return (f"<pyarrow.flight.BasicAuth username={self.username!r} "
+ "password=(redacted)>")
+
class DescriptorType(enum.Enum):
"""
@@ -537,11 +548,11 @@ cdef class FlightDescriptor(_Weakrefable):
def __repr__(self):
if self.descriptor_type == DescriptorType.PATH:
- return "<FlightDescriptor path: {!r}>".format(self.path)
+ return f"<pyarrow.flight.FlightDescriptor path={self.path!r}>"
elif self.descriptor_type == DescriptorType.CMD:
- return "<FlightDescriptor command: {!r}>".format(self.command)
+ return f"<pyarrow.flight.FlightDescriptor cmd={self.command!r}>"
else:
- return "<FlightDescriptor type: {!r}>".format(self.descriptor_type)
+ return f"<pyarrow.flight.FlightDescriptor UNKNOWN>"
@staticmethod
cdef CFlightDescriptor unwrap(descriptor) except *:
@@ -581,14 +592,14 @@ cdef class Ticket(_Weakrefable):
"""A ticket for requesting a Flight stream."""
cdef:
- CTicket ticket
+ CTicket c_ticket
def __init__(self, ticket):
- self.ticket.ticket = tobytes(ticket)
+ self.c_ticket.ticket = tobytes(ticket)
@property
def ticket(self):
- return self.ticket.ticket
+ return self.c_ticket.ticket
def serialize(self):
"""Get the wire-format representation of this type.
@@ -597,7 +608,7 @@ cdef class Ticket(_Weakrefable):
services) that may want to return Flight types.
"""
- return GetResultValue(self.ticket.SerializeToString())
+ return GetResultValue(self.c_ticket.SerializeToString())
@classmethod
def deserialize(cls, serialized):
@@ -608,15 +619,15 @@ cdef class Ticket(_Weakrefable):
"""
cdef Ticket ticket = Ticket.__new__(Ticket)
- ticket.ticket = GetResultValue(
+ ticket.c_ticket = GetResultValue(
CTicket.Deserialize(tobytes(serialized)))
return ticket
def __eq__(self, Ticket other):
- return self.ticket == other.ticket
+ return self.c_ticket == other.c_ticket
def __repr__(self):
- return '<Ticket {}>'.format(self.ticket.ticket)
+ return f"<pyarrow.flight.Ticket ticket={self.ticket!r}>"
cdef class Location(_Weakrefable):
@@ -628,7 +639,7 @@ cdef class Location(_Weakrefable):
check_flight_status(CLocation.Parse(tobytes(uri)).Value(&self.location))
def __repr__(self):
- return '<Location {}>'.format(self.location.ToString())
+ return f'<pyarrow.flight.Location {self.location.ToString()}>'
@property
def uri(self):
@@ -762,15 +773,15 @@ cdef class FlightEndpoint(_Weakrefable):
return endpoint
def __repr__(self):
- return "<FlightEndpoint ticket: {!r} locations: {!r}>".format(
- self.ticket, self.locations)
+ return (f"<pyarrow.flight.FlightEndpoint ticket={self.ticket!r} "
+ f"locations={self.locations!r}>")
def __eq__(self, FlightEndpoint other):
return self.endpoint == other.endpoint
cdef class SchemaResult(_Weakrefable):
- """A result from a getschema request. Holding a schema"""
+ """The serialized schema returned from a GetSchema request."""
cdef:
unique_ptr[CSchemaResult] result
@@ -821,6 +832,9 @@ cdef class SchemaResult(_Weakrefable):
def __eq__(self, SchemaResult other):
return deref(self.result.get()) == deref(other.result.get())
+ def __repr__(self):
+ return f"<pyarrow.flight.SchemaResult schema=({self.schema})>"
+
cdef class FlightInfo(_Weakrefable):
"""A description of a Flight stream."""
@@ -926,6 +940,16 @@ cdef class FlightInfo(_Weakrefable):
CFlightInfo.Deserialize(tobytes(serialized))))
return info
+ def __eq__(self, FlightInfo other):
+ return deref(self.info.get()) == deref(other.info.get())
+
+ def __repr__(self):
+ return (f"<pyarrow.flight.FlightInfo schema={self.schema} "
+ f"descriptor={self.descriptor} "
+ f"endpoints={self.endpoints} "
+ f"total_records={self.total_records} "
+ f"total_bytes={self.total_bytes}>")
+
cdef class FlightStreamChunk(_Weakrefable):
"""A RecordBatch with application metadata on the side."""
@@ -1538,7 +1562,7 @@ cdef class FlightClient(_Weakrefable):
with nogil:
check_flight_status(
self.client.get().DoGet(
- deref(c_options), ticket.ticket).Value(&reader))
+ deref(c_options), ticket.c_ticket).Value(&reader))
result = FlightStreamReader()
result.reader.reset(reader.release())
return result
diff --git a/python/pyarrow/includes/libarrow_flight.pxd
b/python/pyarrow/includes/libarrow_flight.pxd
index 3301c1b636..34ba809438 100644
--- a/python/pyarrow/includes/libarrow_flight.pxd
+++ b/python/pyarrow/includes/libarrow_flight.pxd
@@ -39,6 +39,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" nogil:
shared_ptr[CBuffer] body
bint operator==(CAction)
CResult[c_string] SerializeToString()
+ c_string ToString()
@staticmethod
CResult[CAction] Deserialize(const c_string& serialized)
@@ -49,6 +50,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" nogil:
shared_ptr[CBuffer] body
bint operator==(CFlightResult)
CResult[c_string] SerializeToString()
+ c_string ToString()
@staticmethod
CResult[CFlightResult] Deserialize(const c_string& serialized)
@@ -61,6 +63,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" nogil:
c_string password
bint operator==(CBasicAuth)
CResult[c_string] SerializeToString()
+ c_string ToString()
@staticmethod
CResult[CBasicAuth] Deserialize(const c_string& serialized)
@@ -85,6 +88,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" nogil:
vector[c_string] path
bint operator==(CFlightDescriptor)
CResult[c_string] SerializeToString()
+ c_string ToString()
@staticmethod
CResult[CFlightDescriptor] Deserialize(const c_string& serialized)
@@ -94,6 +98,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" nogil:
c_string ticket
bint operator==(CTicket)
CResult[c_string] SerializeToString()
+ c_string ToString()
@staticmethod
CResult[CTicket] Deserialize(const c_string& serialized)
@@ -132,6 +137,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow"
nogil:
bint operator==(CFlightEndpoint)
CResult[c_string] SerializeToString()
+ c_string ToString()
@staticmethod
CResult[CFlightEndpoint] Deserialize(const c_string& serialized)
@@ -144,6 +150,8 @@ cdef extern from "arrow/flight/api.h" namespace "arrow"
nogil:
CFlightDescriptor& descriptor()
const vector[CFlightEndpoint]& endpoints()
CResult[c_string] SerializeToString()
+ c_string ToString()
+ bint operator==(CFlightInfo)
@staticmethod
CResult[unique_ptr[CFlightInfo]] Deserialize(
@@ -155,6 +163,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow"
nogil:
CResult[shared_ptr[CSchema]] GetSchema(CDictionaryMemo* memo)
bint operator==(CSchemaResult)
CResult[c_string] SerializeToString()
+ c_string ToString()
@staticmethod
CResult[CSchemaResult] Deserialize(const c_string& serialized)
diff --git a/python/pyarrow/tests/test_flight.py
b/python/pyarrow/tests/test_flight.py
index 28ace4f93e..dafa9e6011 100644
--- a/python/pyarrow/tests/test_flight.py
+++ b/python/pyarrow/tests/test_flight.py
@@ -870,6 +870,79 @@ class LargeMetadataFlightServer(FlightServerBase):
writer.write_metadata(self._metadata)
+def test_repr():
+ action_repr = "<pyarrow.flight.Action type='foo' body=(0 bytes)>"
+ action_type_repr = "ActionType(type='foo', description='bar')"
+ basic_auth_repr = "<pyarrow.flight.BasicAuth username=b'user'
password=(redacted)>"
+ descriptor_repr = "<pyarrow.flight.FlightDescriptor cmd=b'foo'>"
+ endpoint_repr = ("<pyarrow.flight.FlightEndpoint "
+ "ticket=<pyarrow.flight.Ticket ticket=b'foo'> "
+ "locations=[]>")
+ info_repr = (
+ "<pyarrow.flight.FlightInfo "
+ "schema= "
+ "descriptor=<pyarrow.flight.FlightDescriptor path=[]> "
+ "endpoints=[] "
+ "total_records=-1 "
+ "total_bytes=-1>")
+ location_repr = "<pyarrow.flight.Location b'grpc+tcp://localhost:1234'>"
+ result_repr = "<pyarrow.flight.Result body=(3 bytes)>"
+ schema_result_repr = "<pyarrow.flight.SchemaResult schema=()>"
+ ticket_repr = "<pyarrow.flight.Ticket ticket=b'foo'>"
+
+ assert repr(flight.Action("foo", b"")) == action_repr
+ assert repr(flight.ActionType("foo", "bar")) == action_type_repr
+ assert repr(flight.BasicAuth("user", "pass")) == basic_auth_repr
+ assert repr(flight.FlightDescriptor.for_command("foo")) == descriptor_repr
+ assert repr(flight.FlightEndpoint(b"foo", [])) == endpoint_repr
+ info = flight.FlightInfo(
+ pa.schema([]), flight.FlightDescriptor.for_path(), [], -1, -1)
+ assert repr(info) == info_repr
+ assert repr(flight.Location("grpc+tcp://localhost:1234")) == location_repr
+ assert repr(flight.Result(b"foo")) == result_repr
+ assert repr(flight.SchemaResult(pa.schema([]))) == schema_result_repr
+ assert repr(flight.SchemaResult(pa.schema([("int", "int64")]))) == \
+ "<pyarrow.flight.SchemaResult schema=(int: int64)>"
+ assert repr(flight.Ticket(b"foo")) == ticket_repr
+
+ with pytest.raises(TypeError):
+ flight.Action("foo", None)
+
+
+def test_eq():
+ items = [
+ lambda: (flight.Action("foo", b""), flight.Action("foo", b"bar")),
+ lambda: (flight.ActionType("foo", "bar"),
+ flight.ActionType("foo", "baz")),
+ lambda: (flight.BasicAuth("user", "pass"),
+ flight.BasicAuth("user2", "pass")),
+ lambda: (flight.FlightDescriptor.for_command("foo"),
+ flight.FlightDescriptor.for_path("foo")),
+ lambda: (flight.FlightEndpoint(b"foo", []),
+ flight.FlightEndpoint(b"", [])),
+ lambda: (
+ flight.FlightInfo(
+ pa.schema([]),
+ flight.FlightDescriptor.for_path(), [], -1, -1),
+ flight.FlightInfo(
+ pa.schema([]),
+ flight.FlightDescriptor.for_command(b"foo"), [], -1, 42)),
+ lambda: (flight.Location("grpc+tcp://localhost:1234"),
+ flight.Location("grpc+tls://localhost:1234")),
+ lambda: (flight.Result(b"foo"), flight.Result(b"bar")),
+ lambda: (flight.SchemaResult(pa.schema([])),
+ flight.SchemaResult(pa.schema([("ints", pa.int64())]))),
+ lambda: (flight.Ticket(b""), flight.Ticket(b"foo")),
+ ]
+
+ for gen in items:
+ lhs1, rhs1 = gen()
+ lhs2, rhs2 = gen()
+ assert lhs1 == lhs2
+ assert rhs1 == rhs2
+ assert lhs1 != rhs1
+
+
def test_flight_server_location_argument():
locations = [
None,