Skip to content

Conversation

rmnskb
Copy link
Contributor

@rmnskb rmnskb commented Aug 29, 2025

Rationale for this change

Please see #47358

What changes are included in this PR?

Added __repr__ dunder methods to ipc.IpcWriteOptions, ipc.IpcReadOptions and flight.FlightCallOptions

Are these changes tested?

Yes

Are there any user-facing changes?

Nicer representations of the classes mentioned above

@rmnskb
Copy link
Contributor Author

rmnskb commented Aug 29, 2025

hey @pitrou, I hope you're doing well :)
I've started implementing the __repr__ dunders for the classes that you've mentioned in #47358, however, now I stumbled upon FlightCallOptions's arguments not being convertable back to Python objects after they are set as C objects inside FlightCallOptions.options.
Could you please provide some guidance on what's the better way to tackle this? I've gone through the implementations of underlying objects in both APIs, and couldn't find any methods that would already do that? Thank you :)

@pitrou
Copy link
Member

pitrou commented Sep 1, 2025

I've started implementing the __repr__ dunders for the classes that you've mentioned in #47358, however, now I stumbled upon FlightCallOptions's arguments not being convertable back to Python objects after they are set as C objects inside FlightCallOptions.options.

I'm not sure what you mean, because if you define the __repr__ in Cython you should be able to access the C-level attributes. You may need to add the necessary API declarations for C++ Flight types.

For example, this change works for me:

diff --git a/python/pyarrow/_flight.pyx b/python/pyarrow/_flight.pyx
index fe2e1b3d67..ca842f35bb 100644
--- a/python/pyarrow/_flight.pyx
+++ b/python/pyarrow/_flight.pyx
@@ -142,6 +142,10 @@ cdef class FlightCallOptions(_Weakrefable):
             return &((<FlightCallOptions> obj).options)
         raise TypeError(f"Expected a FlightCallOptions object, not '{type(obj)}'")
 
+    def __repr__(self):
+        # Draft implementation, should be improved
+        return f'FlightCallOptions(timeout={self.options.timeout.count()})'
+
 
 _CertKeyPair = collections.namedtuple('_CertKeyPair', ['cert', 'key'])
 
diff --git a/python/pyarrow/includes/libarrow_flight.pxd b/python/pyarrow/includes/libarrow_flight.pxd
index b1af6bcb4f..f2b15fb706 100644
--- a/python/pyarrow/includes/libarrow_flight.pxd
+++ b/python/pyarrow/includes/libarrow_flight.pxd
@@ -272,6 +272,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" nogil:
 
     cdef cppclass CTimeoutDuration" arrow::flight::TimeoutDuration":
         CTimeoutDuration(double)
+        double count()
 
     cdef cppclass CFlightCallOptions" arrow::flight::FlightCallOptions":
         CFlightCallOptions()

@rmnskb
Copy link
Contributor Author

rmnskb commented Sep 1, 2025

I've started implementing the __repr__ dunders for the classes that you've mentioned in #47358, however, now I stumbled upon FlightCallOptions's arguments not being convertable back to Python objects after they are set as C objects inside FlightCallOptions.options.

I'm not sure what you mean, because if you define the __repr__ in Cython you should be able to access the C-level attributes. You may need to add the necessary API declarations for C++ Flight types.

For example, this change works for me:

diff --git a/python/pyarrow/_flight.pyx b/python/pyarrow/_flight.pyx
index fe2e1b3d67..ca842f35bb 100644
--- a/python/pyarrow/_flight.pyx
+++ b/python/pyarrow/_flight.pyx
@@ -142,6 +142,10 @@ cdef class FlightCallOptions(_Weakrefable):
             return &((<FlightCallOptions> obj).options)
         raise TypeError(f"Expected a FlightCallOptions object, not '{type(obj)}'")
 
+    def __repr__(self):
+        # Draft implementation, should be improved
+        return f'FlightCallOptions(timeout={self.options.timeout.count()})'
+
 
 _CertKeyPair = collections.namedtuple('_CertKeyPair', ['cert', 'key'])
 
diff --git a/python/pyarrow/includes/libarrow_flight.pxd b/python/pyarrow/includes/libarrow_flight.pxd
index b1af6bcb4f..f2b15fb706 100644
--- a/python/pyarrow/includes/libarrow_flight.pxd
+++ b/python/pyarrow/includes/libarrow_flight.pxd
@@ -272,6 +272,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" nogil:
 
     cdef cppclass CTimeoutDuration" arrow::flight::TimeoutDuration":
         CTimeoutDuration(double)
+        double count()
 
     cdef cppclass CFlightCallOptions" arrow::flight::FlightCallOptions":
         CFlightCallOptions()

Hm, that's interesting, since the same changes have segfaulted for me 🤔
Ok, thanks for the confirmation, I will look into that further.

@rmnskb rmnskb marked this pull request as ready for review September 5, 2025 23:34
@rmnskb
Copy link
Contributor Author

rmnskb commented Sep 5, 2025

hi @pitrou,

I have implemented __repr__ methods for the aforementioned objects as discussed. For flight.FlightCallOptions, I've decided to go with the straightforward approach by assigning the constructor arguments to private attributes, and then accessing them later. Please let me know what you think :)

@AlenkaF
Copy link
Member

AlenkaF commented Sep 8, 2025

Thank you for another contribution @rmnskb !

The overall approach looks good to me. I like that you're only appending the read and write options when they're defined. I think we don’t currently have wrap_options functionality to reconstruct the Python Ipc*Options from self.options.read/write_options, so holding on to the original Python objects makes sense.

One request from me — it would be great to add __repr__ tests, though there aren’t many currently.

One very minor nit: stylistically, I’d consider adding the parentheses inside the class name in the __repr__, like this:

    def __repr__(self):
        return (f"<pyarrow.ipc.IpcReadOptions ("
                ...
                f"included_fields={self.included_fields})>")

@rmnskb
Copy link
Contributor Author

rmnskb commented Sep 13, 2025

Hey @AlenkaF ! Thank you for the comments :)

Regarding the formatting: I wanted to stay consistent with other __repr__ dunders that were already present at the moment of implementing the new ones, hence this style.

Other than that, I've covered the implementation with tests, as you've suggested.
Please let me know if you have any other suggestions :)

@rmnskb rmnskb force-pushed the gh-47358-ipc-flight-repr branch from 9869c14 to 80ab8fa Compare September 13, 2025 00:23
Copy link
Member

@AlenkaF AlenkaF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the changes, the PR is looking great!
I only have one small comment and then that is all from my side.

@pitrou mind giving one more look?

@github-actions github-actions bot added awaiting committer review Awaiting committer review and removed awaiting review Awaiting review labels Sep 15, 2025
@AlenkaF
Copy link
Member

AlenkaF commented Sep 15, 2025

It also looks like the linter needs a change:

diff --git a/python/pyarrow/ipc.pxi b/python/pyarrow/ipc.pxi
index c25b2dcab2..565fe3d8fe 100644
--- a/python/pyarrow/ipc.pxi
+++ b/python/pyarrow/ipc.pxi
@@ -335,7 +335,7 @@ cdef class IpcWriteOptions(_Weakrefable):
 
     def __repr__(self):
         compression_repr = f"compression=\"{self.compression}\" " \
-                if self.compression is not None else ""
+            if self.compression is not None else ""
 
         metadata_version = MetadataVersion(self.metadata_version).name

@github-actions github-actions bot added awaiting changes Awaiting changes and removed awaiting committer review Awaiting committer review labels Sep 15, 2025
@github-actions github-actions bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Sep 15, 2025
@rmnskb
Copy link
Contributor Author

rmnskb commented Sep 15, 2025

Hey @AlenkaF @pitrou @raulcd , thank you for the review!
Regarding the read_options and write_options: I decided to go ahead with the wrapper functions implementations as @raulcd has suggested. Thank you for pointing in the right direction :)
I've also added the docstrings for the FlightCallOptions getters.
Please let me know if there is anything else that I can enhance on this PR :)

@rmnskb rmnskb requested review from pitrou and AlenkaF September 15, 2025 23:23
Copy link
Member

@raulcd raulcd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, just a nit on a test which I don't think it's covered.

@github-actions github-actions bot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Sep 16, 2025
@github-actions github-actions bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Sep 16, 2025
@AlenkaF
Copy link
Member

AlenkaF commented Sep 16, 2025

@github-actions crossbow submit -g python

Copy link

Revision: de04f9b

Submitted crossbow builds: ursacomputing/crossbow @ actions-71c612bccb

Task Status
example-python-minimal-build-fedora-conda GitHub Actions
example-python-minimal-build-ubuntu-venv GitHub Actions
test-conda-python-3.10 GitHub Actions
test-conda-python-3.10-hdfs-2.9.2 GitHub Actions
test-conda-python-3.10-hdfs-3.2.1 GitHub Actions
test-conda-python-3.10-pandas-1.3.4-numpy-1.21.2 GitHub Actions
test-conda-python-3.11 GitHub Actions
test-conda-python-3.11-dask-latest GitHub Actions
test-conda-python-3.11-dask-upstream_devel GitHub Actions
test-conda-python-3.11-hypothesis GitHub Actions
test-conda-python-3.11-pandas-latest-numpy-latest GitHub Actions
test-conda-python-3.11-spark-master GitHub Actions
test-conda-python-3.12 GitHub Actions
test-conda-python-3.12-cpython-debug GitHub Actions
test-conda-python-3.12-pandas-latest-numpy-1.26 GitHub Actions
test-conda-python-3.12-pandas-latest-numpy-latest GitHub Actions
test-conda-python-3.13 GitHub Actions
test-conda-python-3.13-pandas-nightly-numpy-nightly GitHub Actions
test-conda-python-3.13-pandas-upstream_devel-numpy-nightly GitHub Actions
test-conda-python-emscripten GitHub Actions
test-cuda-python-ubuntu-22.04-cuda-11.7.1 GitHub Actions
test-debian-12-python-3-amd64 GitHub Actions
test-debian-12-python-3-i386 GitHub Actions
test-fedora-42-python-3 GitHub Actions
test-ubuntu-22.04-python-3 GitHub Actions
test-ubuntu-22.04-python-313-freethreading GitHub Actions
test-ubuntu-24.04-python-3 GitHub Actions

@AlenkaF
Copy link
Member

AlenkaF commented Sep 17, 2025

Thanks for the reviews and the responsive updates! The PR looks much better now.
While checking the minimal extended builds, I noticed we’ll need a pytest zstd mark (see this example).

The test-conda-python-emscripten failure seems unrelated.

@AlenkaF
Copy link
Member

AlenkaF commented Sep 18, 2025

@github-actions crossbow submit example-python-minimal-build-*

@AlenkaF
Copy link
Member

AlenkaF commented Sep 18, 2025

Rebase would probably remove the AppVeyor build (failure).

Copy link

Revision: 593a0a8

Submitted crossbow builds: ursacomputing/crossbow @ actions-b9c2408cdb

Task Status
example-python-minimal-build-fedora-conda GitHub Actions
example-python-minimal-build-ubuntu-venv GitHub Actions

@raulcd
Copy link
Member

raulcd commented Sep 18, 2025

Rebase would probably remove the AppVeyor build (failure).

Not really, we are waiting for INFRA to remove the integration because the job was migrated so there's no AppVeyor configuration on the repo anymore, see:
https://issues.apache.org/jira/browse/INFRA-27239

@AlenkaF
Copy link
Member

AlenkaF commented Sep 18, 2025

Aha, thanks for the info @raulcd !

Copy link
Member

@AlenkaF AlenkaF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There has been some great work done here, thanks!
I think this PR is ready. Will wait for another approval before we merge. cc @pitrou @raulcd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants