Skip to content

feat(python): expose TCP client configuration - #3776

Open
ethanlin01x wants to merge 7 commits into
apache:masterfrom
ethanlin01x:feat/python-tcp-config
Open

feat(python): expose TCP client configuration#3776
ethanlin01x wants to merge 7 commits into
apache:masterfrom
ethanlin01x:feat/python-tcp-config

Conversation

@ethanlin01x

@ethanlin01x ethanlin01x commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR address?

Closes #3742

Rationale

The Python binding accepts only a bare server address, so reconnection and auto-login cannot be configured from Python, which makes the SDK's session recovery (#2880) unreachable: a session dropped by a server restart surfaces as Unauthenticated on the next call and applications have to hand-roll connect/login/probe retry loops.

What changed?

IggyClient(...) only took host:port, with AutoLogin::Disabled hardcoded and the reconnection policy untunable. It now also accepts a TcpConfig mirroring the Rust TcpClientConfig (auto_login, reconnection, heartbeat_interval, the TLS options, nodelay), keyword-only, with every unset field falling back to the Rust default instead of a value duplicated in the binding. Durations are datetime.timedelta validated at construction, which also fixes the pre-existing conversion that cast a negative timedelta into a huge unsigned duration. Type names follow the maintainer's guidance in the issue (TcpConfig, TcpReconnectionConfig); scope is TCP only, and the bare-address constructor and from_connection_string are unchanged.

Local Execution

  • Passed
  • Pre-commit hooks ran

AI Usage

  1. Which tools? Claude
  2. Scope of usage? help generate and review this PR
  3. How did you verify the generated code works correctly? Integration tests against a real server prove credentials are replayed on connect without a manual login_user().
  4. Can you explain every line of the code if asked? Yes, all the changes are checked by the human.

IggyClient accepted only a server address, so auto-login and reconnection
tuning were unreachable from Python. Without credentials to replay, the
SDK's own session recovery never fires and a dropped session surfaces as
Unauthenticated on the next call, leaving the application to hand-roll a
connect/login/probe loop.

TcpConfig mirrors TcpClientConfig field for field and is accepted by the
IggyClient constructor alongside the existing address string. AutoLogin
carries the credentials without exposing them back to Python, and
TcpReconnectionConfig carries the retry policy.

Credentials is re-exported from the SDK prelude because AutoLogin::Enabled
cannot be constructed without naming it.

Closes apache#3742
Round-trip every field through the getters so a default that drifts from
the Rust SDK is caught, and assert that neither the password nor a personal
access token comes back out of repr.

The auto-login tests are the point of the configuration: a privileged call
succeeds without a manual login_user() when credentials are configured, and
fails without them.
The existing examples all reach for a connection string, which leaves the
new config types undiscoverable. This one configures auto-login and
reconnection directly and never calls login_user, so the recovery the
credentials unlock is visible: restart the server while it runs and the
client picks up where it left off.
The README pointed only at the examples directory, so the configuration
surface stayed invisible to anyone reading the package page on PyPI.
A negative timedelta normalizes to negative days plus positive seconds,
so the old conversion summed to a negative i32 and cast it to u64,
turning interval=timedelta(seconds=-1) into u64::MAX seconds: the config
constructed fine and the client then slept forever on reconnect. Days
arithmetic also overflowed i32 beyond ~68 years, and the reverse
conversion stuffed everything into the seconds argument so such values
could not read back. Conversion is now fallible, rejects negative input
with ValueError at construction, computes in i64, and splits days on the
way out. The AutoCommit conversion becomes TryFrom to carry the error.

The boolean constructor defaults were literals in the pyo3 signature, so
a change to a Rust default would silently not propagate. They are now
Option arguments that fall back to TcpClientConfig::default(), the same
way the durations already did.
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.24779% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.08%. Comparing base (f67f038) to head (b3190f4).

Files with missing lines Patch % Lines
foreign/python/src/config.rs 95.32% 8 Missing ⚠️
foreign/python/src/consumer.rs 60.00% 2 Missing ⚠️
foreign/python/src/duration.rs 92.00% 2 Missing ⚠️
foreign/python/src/client.rs 95.45% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3776      +/-   ##
============================================
- Coverage     75.10%   75.08%   -0.03%     
  Complexity      969      969              
============================================
  Files          1307     1309       +2     
  Lines        152751   152950     +199     
  Branches     128185   128259      +74     
============================================
+ Hits         114726   114835     +109     
- Misses        34494    34497       +3     
- Partials       3531     3618      +87     
Components Coverage Δ
Rust Core 75.50% <ø> (-0.02%) ⬇️
Java SDK 62.71% <ø> (ø)
C# SDK 71.16% <ø> (-1.11%) ⬇️
Python SDK 92.86% <94.24%> (+0.59%) ⬆️
PHP SDK 84.52% <ø> (ø)
Node SDK 92.24% <ø> (+0.12%) ⬆️
Go SDK 43.08% <ø> (ø)
Files with missing lines Coverage Δ
foreign/python/src/lib.rs 100.00% <100.00%> (ø)
foreign/python/src/client.rs 99.15% <95.45%> (+0.01%) ⬆️
foreign/python/src/consumer.rs 80.47% <60.00%> (-0.06%) ⬇️
foreign/python/src/duration.rs 92.00% <92.00%> (ø)
foreign/python/src/config.rs 95.32% <95.32%> (ø)

... and 46 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ethanlin01x
ethanlin01x marked this pull request as ready for review July 29, 2026 18:32
@github-actions github-actions Bot added the S-waiting-on-review PR is waiting on a reviewer label Jul 29, 2026
@ethanlin01x
ethanlin01x marked this pull request as draft July 29, 2026 18:35
@github-actions github-actions Bot removed the S-waiting-on-review PR is waiting on a reviewer label Jul 29, 2026
conftest auto-marked every module as integration, so tests explicitly
marked unit could not be selected with -m "not integration" even though
they need no server. The auto-mark now skips them.

New cases pin the duration boundaries (negative rejected, zero legal,
beyond the i32 seconds range round-trips) and the README claim that a
connection string and TcpConfig reach the same behavior.
The snippet ended with a top-level await; every other sample in the repo
wraps in asyncio.run, so paste-and-run failed on the only snippet a PyPI
reader sees first.
@ethanlin01x
ethanlin01x force-pushed the feat/python-tcp-config branch from 2b6c6ee to b3190f4 Compare July 29, 2026 18:39
@ethanlin01x
ethanlin01x marked this pull request as ready for review July 29, 2026 19:01
@ethanlin01x

Copy link
Copy Markdown
Contributor Author

/ready

@github-actions github-actions Bot added the S-waiting-on-review PR is waiting on a reviewer label Jul 29, 2026

@slbotbm slbotbm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. Mostly cosmetic changes. One thing though: in the docs, you are declaring the thrown errors as PyValueError and similar types. These are rust types which the python user will not see. Also, there are references to the rust sdk in public docs. Please remove them. Our modelled users are python users, who would not know anything about rust.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There's no need for an extra example for the new config. Let's fold this into the getting-started/ example

Comment thread examples/python/README.md

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No need for this extra change if the above example gets folded in getting-started.

Comment thread foreign/python/README.md
Comment on lines +94 to +97
`TcpConfig` also carries `tls_enabled`, `tls_domain`, `tls_ca_file`,
`tls_validate_certificate` and `nodelay`. Every field is keyword-only and defaults to the
same value the Rust SDK uses. `IggyClient.from_connection_string(...)` remains available
for the same settings in string form.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You could show these as commented out options in the above config instead of mentioning them here. No need to mention anything about from_connection_string here.

Comment thread foreign/python/README.md
Comment on lines +63 to +65
`IggyClient` takes either a server address or a `TcpConfig`. Configuring `auto_login`
lets the SDK replay the credentials whenever it reconnects, so a session dropped by a
server restart is recovered instead of surfacing as `Unauthenticated`:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No need to mention the auto_login option specially. That is for the API comment docs.

@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author PR is waiting on author response

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python SDK: IggyClient exposes no client configuration — no reconnection or auto-login, so session recovery is unreachable (Go/C# already expose it)

2 participants