Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f598148
feat(python): expose remaining Topic/TopicDetails fields
Jul 6, 2026
159c023
test(python): assert new Topic/TopicDetails fields in topic tests
Jul 6, 2026
1c7445c
Merge branch 'master' into feat/python-sdk-topic-details-fields
mattp5657 Jul 7, 2026
3758607
feat(python): accept IggyExpiry/MaxTopicSize enums in create_topic an…
Jul 10, 2026
87aabd7
docs(python): spell out IggyExpiry/MaxTopicSize variant semantics
Jul 10, 2026
b55642f
fix(python): reject negative timedelta durations
Jul 12, 2026
78b6500
docs(python): note ValueError on negative message expiry
Jul 12, 2026
a511223
fix(python): reject max topic size at u64 boundary
Jul 12, 2026
d44155e
fix(python): widen timedelta-to-seconds conversion to i64
Jul 20, 2026
529411f
fix(python): reject IggyExpiry sentinel-boundary durations
Jul 20, 2026
9f8445b
refactor(python): dedup topic param resolution, mirror update_topic t…
Jul 20, 2026
9610f27
style(python): rustfmt py_delta_to_iggy_duration
Jul 20, 2026
4739950
Merge branch 'master' into feat/python-sdk-topic-details-fields
Jul 22, 2026
320135a
fix(python): raise ValueError on unrepresentable message expiry duration
Jul 22, 2026
877a462
Merge branch 'master' into feat/python-sdk-topic-details-fields
numinnex Jul 31, 2026
a569570
Merge branch 'master' into feat/python-sdk-topic-details-fields
slbotbm Aug 1, 2026
54429b7
chore(python-sdk): bump version to 0.8.1.dev4
Aug 1, 2026
8678193
Merge branch 'master' into feat/python-sdk-topic-details-fields
Aug 1, 2026
e679d42
Merge branch 'master' into feat/python-sdk-topic-details-fields
slbotbm Aug 3, 2026
7e694e5
Merge branch 'master' into feat/python-sdk-topic-details-fields
hubcio Aug 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bdd/python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/common/src/types/partition/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use serde::{Deserialize, Serialize};
/// - `current_offset`: the current offset of the partition.
/// - `size_bytes`: the size of the partition in bytes.
/// - `messages_count`: the number of messages in the partition.
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Partition {
/// Unique identifier of the partition.
pub id: u32,
Expand Down
2 changes: 1 addition & 1 deletion examples/python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion foreign/python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

[package]
name = "apache-iggy"
version = "0.8.1-dev3"
version = "0.8.1-dev4"
edition = "2024"
authors = ["Iggy Committers <dev@iggy.apache.org>"]
license = "Apache-2.0"
Expand Down
221 changes: 213 additions & 8 deletions foreign/python/apache_iggy.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ __all__ = [
"GlobalPermissions",
"IggyClient",
"IggyConsumer",
"IggyExpiry",
"MaxTopicSize",
"Partition",
"Permissions",
"PollingStrategy",
"ReceiveMessage",
Expand Down Expand Up @@ -956,12 +959,27 @@ class IggyClient:
partitions_count: builtins.int,
compression_algorithm: builtins.str | None = None,
replication_factor: builtins.int | None = None,
message_expiry: datetime.timedelta | None = None,
max_topic_size: builtins.int | None = None,
message_expiry: IggyExpiry | None = None,
max_topic_size: MaxTopicSize | None = None,
) -> collections.abc.Awaitable[None]:
r"""
Creates a new topic with the given parameters.
Returns Ok(()) on successful topic creation or a PyRuntimeError on failure.

Args:
stream: Stream identifier as `str | int`.
name: Topic name as `str`.
partitions_count: Number of partitions as `int`.
compression_algorithm: Compression algorithm as `str | None`.
replication_factor: Replication factor as `int | None`.
message_expiry: Message expiry as `IggyExpiry | None`.
max_topic_size: Maximum topic size as `MaxTopicSize | None`.

Returns:
An awaitable that resolves to `None` when the topic is created.

Raises:
ValueError: If `message_expiry` or `max_topic_size` is out of range.
PyRuntimeError: If another argument is invalid or the request fails.
"""
def get_topic(
self,
Expand Down Expand Up @@ -994,8 +1012,8 @@ class IggyClient:
name: builtins.str,
compression_algorithm: builtins.str | None = None,
replication_factor: builtins.int | None = None,
message_expiry: datetime.timedelta | None = None,
max_topic_size: builtins.int | None = None,
message_expiry: IggyExpiry | None = None,
max_topic_size: MaxTopicSize | None = None,
) -> collections.abc.Awaitable[None]:
r"""
Update an existing topic.
Expand All @@ -1009,14 +1027,15 @@ class IggyClient:
name: New topic name as `str`.
compression_algorithm: Compression algorithm as `str | None`.
replication_factor: Replication factor as `int | None`.
message_expiry: Message expiry as `datetime.timedelta | None`.
max_topic_size: Maximum topic size in bytes as `int | None`.
message_expiry: Message expiry as `IggyExpiry | None`.
max_topic_size: Maximum topic size as `MaxTopicSize | None`.

Returns:
An awaitable that resolves to `None` when the topic is updated.

Raises:
PyRuntimeError: If an argument is invalid or the request fails.
ValueError: If `message_expiry` or `max_topic_size` is out of range.
PyRuntimeError: If another argument is invalid or the request fails.
"""
def delete_topic(
self,
Expand Down Expand Up @@ -1325,6 +1344,134 @@ class IggyConsumer:
Returns an awaitable that completes when shutdown is signaled or a PyRuntimeError on failure.
"""

class IggyExpiry:
r"""
The expiry of the messages in a topic.
"""
@typing.final
class ServerDefault(IggyExpiry):
r"""
Use the message expiry configured on the server for this topic,
rather than an explicit value set by the client.
"""

__match_args__ = ()
def __new__(cls) -> IggyExpiry.ServerDefault: ...
def __len__(self) -> builtins.int: ...
def __getitem__(self, key: builtins.int, /) -> typing.Any: ...

@typing.final
class ExpireDuration(IggyExpiry):
r"""
Expire messages this long after they are appended to the topic.

`duration` must be greater than zero and less than the maximum
microsecond count a `u64` can hold (about 584,542 years): those two
values are reserved on the wire for `ServerDefault` and `NeverExpire`
respectively, so a `duration` at either boundary raises `ValueError`
when passed to `create_topic`/`update_topic`. A negative `timedelta`
also raises `ValueError`.
"""

__match_args__ = ("duration",)
@property
def duration(self) -> datetime.timedelta: ...
def __new__(cls, duration: datetime.timedelta) -> IggyExpiry.ExpireDuration: ...

@typing.final
class NeverExpire(IggyExpiry):
r"""
Retain messages indefinitely; they never expire.
"""

__match_args__ = ()
def __new__(cls) -> IggyExpiry.NeverExpire: ...
def __len__(self) -> builtins.int: ...
def __getitem__(self, key: builtins.int, /) -> typing.Any: ...

...

class MaxTopicSize:
r"""
The maximum size of a topic.
"""
@typing.final
class ServerDefault(MaxTopicSize):
r"""
Use the maximum topic size configured on the server, rather than an
explicit value set by the client.
"""

__match_args__ = ()
def __new__(cls) -> MaxTopicSize.ServerDefault: ...
def __len__(self) -> builtins.int: ...
def __getitem__(self, key: builtins.int, /) -> typing.Any: ...

@typing.final
class Custom(MaxTopicSize):
r"""
Cap the topic at this many bytes; as the topic approaches this size,
the server deletes the oldest sealed segments to make room for new
messages.

`bytes` must be greater than zero and less than the maximum value of
an unsigned 64-bit integer: those two values are reserved on the wire
for `ServerDefault` and `Unlimited` respectively, so a `Custom` size
at either boundary raises `ValueError` when passed to
`create_topic`/`update_topic`.
"""

__match_args__ = ("bytes",)
@property
def bytes(self) -> builtins.int: ...
def __new__(cls, bytes: builtins.int) -> MaxTopicSize.Custom: ...

@typing.final
class Unlimited(MaxTopicSize):
r"""
Do not cap the topic size; it may grow without bound.
"""

__match_args__ = ()
def __new__(cls) -> MaxTopicSize.Unlimited: ...
def __len__(self) -> builtins.int: ...
def __getitem__(self, key: builtins.int, /) -> typing.Any: ...

...

@typing.final
class Partition:
@property
def id(self) -> builtins.int:
r"""
The unique identifier (numeric) of the partition.
"""
@property
def created_at(self) -> builtins.int:
r"""
The timestamp of the partition creation, in microseconds.
"""
@property
def segments_count(self) -> builtins.int:
r"""
The number of segments in the partition.
"""
@property
def current_offset(self) -> builtins.int:
r"""
The current offset of the partition.
"""
@property
def size(self) -> builtins.int:
r"""
The size of the partition in bytes.
"""
@property
def messages_count(self) -> builtins.int:
r"""
The number of messages in the partition.
"""

@typing.final
class Permissions:
r"""
Expand Down Expand Up @@ -1574,6 +1721,36 @@ class Topic:
r"""
The total number of partitions in the topic.
"""
@property
def created_at(self) -> builtins.int:
r"""
The timestamp when the topic was created, in microseconds.
"""
@property
def size(self) -> builtins.int:
r"""
The total size of the topic in bytes.
"""
@property
def message_expiry(self) -> IggyExpiry:
r"""
The expiry of the messages in the topic.
"""
@property
def compression_algorithm(self) -> builtins.str:
r"""
Compression algorithm for the topic.
"""
@property
def max_topic_size(self) -> MaxTopicSize:
r"""
The maximum size of the topic.
"""
@property
def replication_factor(self) -> builtins.int:
r"""
Replication factor for the topic.
"""

@typing.final
class TopicDetails:
Expand All @@ -1598,15 +1775,43 @@ class TopicDetails:
The total number of partitions in the topic.
"""
@property
def created_at(self) -> builtins.int:
r"""
The timestamp when the topic was created, in microseconds.
"""
@property
def size(self) -> builtins.int:
r"""
The total size of the topic in bytes.
"""
@property
def message_expiry(self) -> IggyExpiry:
r"""
The expiry of the messages in the topic.
"""
@property
def compression_algorithm(self) -> builtins.str:
r"""
Compression algorithm for the topic.
"""
@property
def max_topic_size(self) -> MaxTopicSize:
r"""
The maximum size of the topic.
"""
@property
def replication_factor(self) -> builtins.int:
r"""
Replication factor for the topic.
"""
@property
def partitions(self) -> builtins.list[Partition]:
r"""
The collection of partitions in the topic.

Rebuilds the list from scratch on every access; cache the result
rather than reading this repeatedly in a loop.
"""

@typing.final
class TopicPermissions:
Expand Down
2 changes: 1 addition & 1 deletion foreign/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ build-backend = "maturin"
[project]
name = "apache-iggy"
requires-python = ">=3.10"
version = "0.8.1.dev3"
version = "0.8.1.dev4"
description = "Apache Iggy is the persistent message streaming platform written in Rust, supporting QUIC, TCP and HTTP transport protocols, capable of processing millions of messages per second."
readme = "README.md"
license = { file = "LICENSE" }
Expand Down
Loading
Loading