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
Metadata
Release files for complex-heart-criteria 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| complex_heart_criteria-1.0.0.tar.gz | 10.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| complex_heart_criteria-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.8 kB
Release files / complex_heart_criteria-1.0.0.tar.gz
| Download URL | complex_heart_criteria-1.0.0.tar.gz |
|---|---|
| Size | 10.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e6726f467e6c4a0d7bffa2fd11d1a3a9964f9bfa9edae3ec6d3538b75efd4cf
|
|
BLAKE2b-256 checksum How to use checksums |
5ab4ba17f120e796ca39b44569974370c65183592fcaa83f5d5fdded9af58dc5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.
Transparency logRelease files / complex_heart_criteria-1.0.0-py3-none-any.whl
| Download URL | complex_heart_criteria-1.0.0-py3-none-any.whl |
|---|---|
| Size | 7.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d84616db3e48a07f4683ceeba30389d03234ff655b9c148353131c550eedceaa
|
|
BLAKE2b-256 checksum How to use checksums |
f1ef184508e14c112ad98057745839675bdc0422daec9ca2b39b2837041c4c31
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 17, 2026.
Transparency log