FenjuFu opened a new issue, #4356:
URL: https://github.com/apache/iggy/issues/4356

   ### Bug description
   
   Several Python SDK methods are declared as 
`collections.abc.Awaitable[None]`, but their successful futures return Rust 
unit (`()`). With the pinned PyO3 0.29.2 and pyo3-async-runtimes 0.29.0, that 
path resolves to an empty Python tuple rather than `None`.
   
   This affects callers that check `result is None` and makes the runtime 
contract inconsistent with the generated type declarations.
   
   ### Affected area / component
   
   Python SDK
   
   ### Versions
   
   Audited checkout: 
[e0c2423a](https://github.com/FenjuFu/iggy/commit/e0c2423a2961ed6728c0cc92bf377c8a06dc251e),
 based on upstream `3a00b5ba1ebcca9ccfaab532b406c9591a862dcb`. PyO3 0.29.2 and 
pyo3-async-runtimes 0.29.0.
   
   ### Evidence and validation limits
   
   Source inspection at `e0c2423a2961ed6728c0cc92bf377c8a06dc251e` identified 
24 `IggyClient` methods and 3 `IggyConsumer` methods. This audit did not run 
runtime tests for those 27 methods. The standalone `ping` reproduction below is 
prepared but has not yet been run: the available Windows environment lacks the 
build tools and a usable local Linux/server environment.
   
   The same conversion was observed in the initial `delete_segments` 
implementation: two real-server tests failed with `assert () is None` in [this 
CI 
run](https://github.com/FenjuFu/iggy/actions/runs/36674942438/job/109757764924).
 That new method was separately corrected for #4328. Its successful rerun does 
not establish runtime coverage for the other methods listed here.
   
   ### Minimal reproduction to run
   
   Build/install the Python SDK from the audited checkout and start an Iggy 
server from the same checkout, then run:
   
   ```python
   import asyncio
   from apache_iggy import IggyClient
   
   async def main():
       client = IggyClient("127.0.0.1:8090")
       await client.connect()
       try:
           result = await client.ping()
           print(repr(result), type(result).__name__)
           assert result is None
       finally:
           await client.shutdown()
   
   asyncio.run(main())
   ```
   
   Expected: `None`. Source-predicted result before a fix: `()` (`tuple`). The 
reproduction only opens a connection and pings the server; it does not create 
or delete resources.
   
   ### Affected methods from source inspection
   
   - `IggyClient`: `ping`, `login_user`, `update_user`, `delete_user`, 
`update_permissions`, `change_password`, `logout_user`, `connect`, 
`disconnect`, `shutdown`, `create_stream`, `update_stream`, `delete_stream`, 
`purge_stream`, `create_topic`, `update_topic`, `delete_topic`, `purge_topic`, 
`create_partitions`, `delete_partitions`, `create_consumer_group`, 
`delete_consumer_group`, `join_consumer_group`, `leave_consumer_group`
   - `IggyConsumer`: `store_offset`, `delete_offset`, `consume_messages`
   
   `IggyClient.delete_segments` and `IggyProducer.shutdown` explicitly return 
Python `None` and are excluded.
   
   ### Conversion path
   
   Source references: [client 
bindings](https://github.com/FenjuFu/iggy/blob/e0c2423a2961ed6728c0cc92bf377c8a06dc251e/foreign/python/src/client.rs),
 [consumer 
bindings](https://github.com/FenjuFu/iggy/blob/e0c2423a2961ed6728c0cc92bf377c8a06dc251e/foreign/python/src/consumer.rs),
 and [type 
declarations](https://github.com/FenjuFu/iggy/blob/e0c2423a2961ed6728c0cc92bf377c8a06dc251e/foreign/python/apache_iggy.pyi).
   
   - The wrappers declare `Awaitable[None]` using a stub override, which does 
not change runtime conversion.
   - `pyo3-async-runtimes` 0.29.0 converts the future's successful value with 
`val.into_py_any(py)` (`src/generic.rs:655`).
   - PyO3 0.29.2 implements `IntoPyObject for ()` using `PyTuple::empty(py)` 
(`src/conversion.rs:561-572`).
   
   ### Related work and scope
   
   #4166 proposes returning resource details from `create_stream`, 
`create_topic`, and `create_consumer_group`. #4167 proposes returning identity 
details from `login_user`. Those four methods should be coordinated with that 
work rather than assigned a new final return contract here.
   
   For methods intended to retain a `None` contract, an explicit Python `None` 
conversion and a return-value regression test would align runtime behavior with 
the type declaration. The approach should be agreed before a broad fix. This 
report is separate from #4328.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to