Small implementation of a filter criteria pattern in Python for Complex Heart SDK. Compose several filters using fluent interface.
Project description
Criteria (a.k.a Filter)
Small implementation of a filter criteria pattern in Python for Complex Heart SDK. Query-system agnostic - works with SQL, NoSQL, APIs, or any data source.
Installation
pip install complex-heart-criteria
or using uv:
uv add complex-heart-criteria
Usage
from complexheart.domain.criteria import Criteria, Filter, FilterGroup, Order, Page
Building FilterGroups
Use + to compose filters into a FilterGroup (AND logic within group):
active_adults = Filter.equal("status", "active") + Filter.greater_or_equal_than("age", 18)
Or use the fluent API:
active_adults = (
FilterGroup.empty()
.add_filter_equal("status", "active")
.add_filter_greater_or_equal_than("age", 18)
)
Building Criteria
Add FilterGroups to Criteria (OR logic between groups):
c = (
Criteria()
.with_filter_group(active_adults)
.with_order(Order.desc(("created_at",)))
.with_page_limit(10)
.with_page_offset(20)
)
Merging Criteria
Use | for OR and & for AND between Criteria objects:
active_users = Criteria().with_filter_group(
Filter.equal("status", "active") + Filter.greater_than("age", 18)
)
admin_users = Criteria().with_filter_group(
FilterGroup.create(Filter.equal("role", "admin"))
)
# OR: concatenate groups
combined = active_users | admin_users
# Result: (status = 'active' AND age > 18) OR (role = 'admin')
# AND: merge into single group
merged = active_users & admin_users
# Result: (status = 'active' AND age > 18 AND role = 'admin')
Fluent API
criteria = (
Criteria()
.filter("status", "==", "active", group=0)
.filter("age", ">=", 18, group=0)
.filter("role", "==", "admin", group=1)
.order_by(("created_at",), "DESC")
.limit(10)
.offset(20)
)
# Result: (status = 'active' AND age >= 18) OR (role = 'admin')
Filter Factories
Filter.equal("name", "Vincent") # name == 'Vincent'
Filter.not_equal("name", "Vincent") # name != 'Vincent'
Filter.greater_than("age", 18) # age > 18
Filter.greater_or_equal_than("age", 18) # age >= 18
Filter.less_than("age", 65) # age < 65
Filter.less_or_equal_than("age", 65) # age <= 65
Filter.in_("status", ["a", "b"]) # status IN ('a', 'b')
Filter.not_in("status", ["x"]) # status NOT IN ('x')
Filter.like("name", "Vin%") # name LIKE 'Vin%'
Filter.not_like("name", "Vin%") # name NOT LIKE 'Vin%'
Filter.contains("tags", "vip") # tags contains 'vip'
Filter.not_contains("tags", "x") # tags not contains 'x'
FilterGroup Methods
group = (
FilterGroup.empty()
.add_filter_equal("status", "active")
.add_filter_greater_than("age", 18)
.add_filter_in("role", ["admin", "moderator"])
)
Available methods: add_filter_equal, add_filter_not_equal, add_filter_greater_than,
add_filter_greater_or_equal_than, add_filter_less_than, add_filter_less_or_equal_than,
add_filter_in, add_filter_not_in, add_filter_like, add_filter_not_like,
add_filter_contains, add_filter_not_contains.
Repository Integration
customers = customer_repository.match(criteria)
Immutability
All classes are immutable frozen dataclasses. Methods return new instances:
c1 = Criteria()
c2 = c1.filter("name", "==", "Vincent")
assert c1 is not c2
assert len(c1.filters) == 0
assert len(c2.filters) == 1
Migration from v0.x
v1.0 introduces breaking changes:
Immutability
# Old (v0.x) - mutation pattern
c = Criteria()
c.filter("name", "==", "Vincent") # mutated c
# New (v1.x) - immutable, must reassign
c = Criteria()
c = c.filter("name", "==", "Vincent") # returns new instance
Filter Factory Names
# Old
Filter.eq("name", "v")
Filter.neq("name", "v")
Filter.gt("age", 18)
Filter.gte("age", 18)
Filter.lt("age", 65)
Filter.lte("age", 65)
# New (aligned with PHP version)
Filter.equal("name", "v")
Filter.not_equal("name", "v")
Filter.greater_than("age", 18)
Filter.greater_or_equal_than("age", 18)
Filter.less_than("age", 65)
Filter.less_or_equal_than("age", 65)
Order.by is now tuple
# Old
Order.desc(["name", "age"])
# New
Order.desc(("name", "age"))
Criteria operators only accept Criteria
# Old - operators accepted Filter/FilterGroup
c = Criteria() | Filter.equal("a", 1)
# New - use with_filter_group instead
c = Criteria().with_filter_group(FilterGroup.create(Filter.equal("a", 1)))
# Operators only work between Criteria objects
c1 = Criteria().with_filter_group(group1)
c2 = Criteria().with_filter_group(group2)
combined = c1 | c2 # OK
merged = c1 & c2 # OK
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file complex_heart_criteria-1.0.0.tar.gz.
File metadata
- Download URL: complex_heart_criteria-1.0.0.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e6726f467e6c4a0d7bffa2fd11d1a3a9964f9bfa9edae3ec6d3538b75efd4cf
|
|
| MD5 |
8f25595a3c9ac07e63842034ca56b4e8
|
|
| BLAKE2b-256 |
5ab4ba17f120e796ca39b44569974370c65183592fcaa83f5d5fdded9af58dc5
|
Provenance
The following attestation bundles were made for complex_heart_criteria-1.0.0.tar.gz:
Publisher:
release.yml on ComplexHeart/py-criteria
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
complex_heart_criteria-1.0.0.tar.gz -
Subject digest:
9e6726f467e6c4a0d7bffa2fd11d1a3a9964f9bfa9edae3ec6d3538b75efd4cf - Sigstore transparency entry: 956156547
- Sigstore integration time:
-
Permalink:
ComplexHeart/py-criteria@955e6407c2b698f5f01ccaf589d8a8bdee3cc5f0 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/ComplexHeart
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@955e6407c2b698f5f01ccaf589d8a8bdee3cc5f0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file complex_heart_criteria-1.0.0-py3-none-any.whl.
File metadata
- Download URL: complex_heart_criteria-1.0.0-py3-none-any.whl
- Upload date:
- Size: 7.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d84616db3e48a07f4683ceeba30389d03234ff655b9c148353131c550eedceaa
|
|
| MD5 |
562e2e2f6caffaa51f06647337010262
|
|
| BLAKE2b-256 |
f1ef184508e14c112ad98057745839675bdc0422daec9ca2b39b2837041c4c31
|
Provenance
The following attestation bundles were made for complex_heart_criteria-1.0.0-py3-none-any.whl:
Publisher:
release.yml on ComplexHeart/py-criteria
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
complex_heart_criteria-1.0.0-py3-none-any.whl -
Subject digest:
d84616db3e48a07f4683ceeba30389d03234ff655b9c148353131c550eedceaa - Sigstore transparency entry: 956156556
- Sigstore integration time:
-
Permalink:
ComplexHeart/py-criteria@955e6407c2b698f5f01ccaf589d8a8bdee3cc5f0 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/ComplexHeart
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@955e6407c2b698f5f01ccaf589d8a8bdee3cc5f0 -
Trigger Event:
push
-
Statement type: