IterProxy: Extended Iterable API
iterproxy is a Python library that enhances any iterable object with a convenient API, allowing access patterns commonly found in ORM frameworks. It provides methods like `.one()`, `.one_or_none()`, `.many(k)`, `.skip(k)`, and `.all()`. The current version is 0.3.1, released on November 2, 2023, indicating an active but infrequent release cadence.
Warnings
- gotcha IterProxy methods, like other Python iterators, consume elements from the underlying iterable. Subsequent calls to methods such as `.one()`, `.many()`, or `.all()` on the same `IterProxy` instance will continue from where the last operation left off. If the iterable is fully consumed, further calls will yield no results or raise `StopIteration`.
- gotcha Calling `.one()` on an `IterProxy` that is empty or has been fully consumed will raise a `StopIteration` error. This is standard Python iterator behavior but can be unexpected if not handled.
- gotcha When using the `.filter()` method, passing multiple filter functions to a single `.filter()` call (e.g., `proxy.filter(func1, func2)`) applies them with an implicit logical `AND` operation. This means all functions must return `True` for an item to pass the filter. Users expecting an `OR` operation or more complex logic might encounter unexpected results.
Install
-
pip install iterproxy
Imports
- IterProxy
from iterproxy import IterProxy
Quickstart
from iterproxy import IterProxy
# Create an IterProxy from any iterable
my_list = list(range(10))
proxy = IterProxy(my_list)
# Access elements using ORM-like API
print(f"First element: {proxy.one()}") # Output: First element: 0
print(f"Next three elements: {proxy.many(3)}") # Output: Next three elements: [1, 2, 3]
# Skip elements and get subsequent ones
# Note: This operates on the *remaining* elements after previous calls
print(f"Skip 2, get next 2: {proxy.skip(2).many(2)}") # Output: Skip 2, get next 2: [6, 7]
# Get all remaining elements
print(f"All remaining elements: {proxy.all()}") # Output: All remaining elements: [8, 9]
# Handle potentially empty results gracefully
empty_proxy = IterProxy([])
print(f"One or none from empty: {empty_proxy.one_or_none()}") # Output: One or none from empty: None
# Chaining filter operations
def is_odd(x): return x % 2 == 1
def gte_5(x): return x >= 5
# Re-create proxy for fresh iteration
proxy_for_filter = IterProxy(range(10))
filtered_items = proxy_for_filter.filter(is_odd).filter(gte_5).all()
print(f"Filtered (odd and >=5): {filtered_items}") # Output: Filtered (odd and >=5): [5, 7, 9]
# Multiple filter functions in one call (implicit AND logic)
proxy_combined_filter = IterProxy(range(10))
combined_filtered_items = proxy_combined_filter.filter(is_odd, gte_5).all()
print(f"Combined filter (odd and >=5): {combined_filtered_items}") # Output: Combined filter (odd and >=5): [5, 7, 9]