Skip to main content

Fluent-based Lazily-evaluated Integrated Query for Python

Project description

drawing Fliq

Fluent-syntax Lazily-evaluated Integrated Query.

Python Versions Downloads build lint coverage Ruff

Fliq is a lightweight Python library for high-performance processing of iterables, inspired by Django's ORM and LINQ. It provides a fluent syntax for lazily-evaluated operations on iterables, and it is tested to have on-par performance with the standard library.

Installation

pip install fliq

Fliq

  • Readable & Easy: Designed for readability and ease of use. Using fluent syntax.
  • Lightweight: Thin wrapper for the standard library. No dependencies.
  • Performant: On-par with the standard library. Abstraction overhead is kept to a minimum, keeping CPython performance.
  • Lazy: All operations are lazy, and only evaluated when needed. This provides a performance boost for cases where user would have used list-comprehension otherwise.
  • Compatible: Compatible with APIs consuming iterables.

Query (aka q) API

Note that API docs may contain custom types to improve readability:

  • Predicates. Predicate = Callable[[Any], bool]

Streamers

where

def where(predicate: Optional[Predicate] = None) -> 'Query'

Yields elements that satisfy the predicate (aka filter).

Example:
q(range(10)).where(lambda x: x % 2 == 0)
[0, 2, 4, 6, 8]

Args:
predicate: Optional. The predicate to filter the iterable by. If None is given, no filtering takes place.

select

def select(selector: Callable[[Any], Any]) -> 'Query'

Yields the result of applying the selector function to each element (aka map).

Example:
q(range(5)).select(lambda x: x * 2 == 0)
[0, 2, 4, 6, 8, 10]

Args:
selector: The selector function to apply to each element.

exclude

def exclude(predicate: Predicate) -> 'Query'

Yields elements that do not satisfy the predicate.

Example:
q(range(5)).exclude(lambda x: x > 3)
[0, 1, 2, 3]

Args:
predicate: The predicate to filter the iterable by.

distinct

def distinct(preserve_order: bool = True) -> 'Query'

Yields distinct elements, preserving order if specified.

Example:
q([0, 1, 0, 2, 2]).distinct()
[0, 1, 2]

Args:
preserve_order: Optional. Whether to preserve the order of the items. Defaults to True.

order

def order(by: Optional[Callable[[Any], Any]] = None,
          ascending: bool = True) -> 'Query'

Yields elements in sorted order.

Example:
q([4, 3, 2, 1, 0]).order()
[0, 1, 2, 3, 4]

Args:
by: a selector function to extract the key from an item, defaults to None. If None, the default ordering is used.
ascending: whether to sort in ascending or descending order, defaults to True.

reverse

def reverse() -> 'Query'

Yields elements in reverse order. Notes:

  • in case of an irreversible iterable, TypeError is raised (e.g., set)
  • in case of a generator, the iterable is first converted to a list, then reversed, this has a performance impact, and assume a finite generator

Example:
q([0, 1, 2, 3, 4]).order()
[4, 3, 2, 1, 0]

slice

def slice(start: int = 0,
          stop: Optional[int] = None,
          step: int = 1) -> 'Query'

Yields a slice of the iterable. Examples:
q(range(10)).slice(start=1, stop=6, step=2)
[1, 3, 5]

Args:
start: Optional. The start index of the slice. Defaults to 0.
stop: Optional. The stop index of the slice. Defaults to None.
step: Optional. The step of the slice. Defaults to 1.

take

def take(n: int, predicate: Optional[Predicate] = None) -> 'Query'

Yields up to n items that satisfies the predicate (if provided). In case the iterable is ordered, the first n items are returned. Args:
n: Optional. The number of items to take. Defaults to 1.
predicate: Optional. The predicate to filter the iterable by.

Collectors

first

def first(predicate: Optional[Predicate] = None) -> Any

first_or_default

def first_or_default(default: Any = None,
                     predicate: Optional[Predicate] = None) -> Any

single

def single(predicate: Optional[Predicate] = None) -> Any

single_or_default

def single_or_default(predicate: Optional[Predicate] = None,
                      default: Any = None) -> Any

count

def count() -> int

Returns the number of elements in the iterable :return: The number of the elemtns :rtype: int

any

def any(predicate: Optional[Predicate] = None) -> bool

Returns whether any element in the iterable evaluates to true. If a predicate is provided, only elements that satisfy the predicate are considered. Args: predicate: Optional. The predicate to filter the iterable by.

Returns: True if any element evaluates to true, False otherwise.

to_list

def to_list() -> List

Roadmap

Streamers

  • where (aka filter)
  • select (aka map)
  • exclude (aka where_not)
  • distinct
  • group_by
  • order_by
  • reverse
  • slice
  • skip
  • skip_last
  • take
  • zip
  • remove
  • append
  • prepend
  • concat

Collectors

  • first
  • first_or_default
  • get
  • to_list
  • count
  • any
  • all
  • sum
  • min
  • max
  • average

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fliq-0.4.0.tar.gz (84.4 kB view hashes)

Uploaded Source

Built Distribution

fliq-0.4.0-py3-none-any.whl (19.9 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page