Skip to main content

The Criteria Pattern is a Python package that simplifies and standardizes criteria based filtering, validation and selection.

Project description

๐Ÿค๐Ÿป Criteria Pattern

CI Pipeline Coverage Pipeline Package Version Supported Python Versions Package Downloads Project Documentation

The Criteria Pattern is a Python ๐Ÿ package that simplifies and standardizes criteria based filtering ๐Ÿค๐Ÿป, validation and selection. This package provides a set of prebuilt ๐Ÿ‘ท๐Ÿป objects and utilities that you can drop into your existing projects and not have to implement yourself.

These utilities ๐Ÿ› ๏ธ are useful when you need complex filtering logic. It also enforces ๐Ÿ‘ฎ๐Ÿป best practices so all your filtering processes follow a uniform standard.

Easy to install and integrate, this is a must have for any Python developer looking to simplify their workflow, enforce design patterns and use the full power of modern ORMs and SQL ๐Ÿ—„๏ธ in their projects ๐Ÿš€.

Table of Contents

๐Ÿ”ผ Back to top



๐Ÿ“ฅ Installation

You can install Criteria Pattern using pip:

pip install criteria-pattern

๐Ÿ”ผ Back to top



๐Ÿ“š Documentation

This project's documentation is powered by DeepWiki, which provides a comprehensive overview of the Criteria Pattern and its usage.

๐Ÿ”ผ Back to top



๐Ÿ’ป Utilization

from criteria_pattern import Criteria, Filter, Operator
from criteria_pattern.converters import CriteriaToPostgresqlConverter

is_adult = Criteria(filters=[Filter(field='age', operator=Operator.GREATER_OR_EQUAL, value=18)])
email_is_gmail = Criteria(filters=[Filter(field='email', operator=Operator.ENDS_WITH, value='@gmail.com')])
email_is_yahoo = Criteria(filters=[Filter(field='email', operator=Operator.ENDS_WITH, value='@yahoo.com')])

query, parameters = CriteriaToPostgresqlConverter.convert(criteria=is_adult & (email_is_gmail | email_is_yahoo), table='user')
print(query)
print(parameters)
# >>> SELECT * FROM user WHERE (age >= %(parameter_0)s AND (email LIKE '%%' || %(parameter_1)s OR email LIKE '%%' || %(parameter_2)s));
# >>> {'parameter_0': 18, 'parameter_1': '@gmail.com', 'parameter_2': '@yahoo.com'}

๐Ÿ”„ Available Converters

The package includes converters for SQL generation and request parsing:

๐Ÿ”ผ Back to top

๐ŸŽฏ Real-Life Case: Multi-tenant User Search Service

Imagine an admin dashboard where each request must:

  1. Always restrict results to the current tenant.
  2. Optionally filter active users.
  3. Search only users with company emails.
  4. Sort by newest users first.

With Criteria Pattern, each concern is a small reusable criteria object. You combine them using & and |, then convert once to SQL:

from criteria_pattern import Criteria, Direction, Filter, Operator, Order
from criteria_pattern.converters import CriteriaToPostgresqlConverter


class UserSearchService:
    def __init__(self, tenant_id: str) -> None:
        self.tenant_id = tenant_id

    def build_query(self, *, only_active: bool, corporate_domain: str) -> tuple[str, dict[str, object]]:
        tenant_scope = Criteria(filters=[Filter(field='tenant_id', operator=Operator.EQUAL, value=self.tenant_id)])
        active_scope = Criteria(filters=[Filter(field='is_active', operator=Operator.EQUAL, value=True)])
        email_scope = Criteria(filters=[Filter(field='email', operator=Operator.ENDS_WITH, value=corporate_domain)])
        sort_scope = Criteria(orders=[Order(field='created_at', direction=Direction.DESC)])

        criteria = tenant_scope & email_scope & sort_scope
        if only_active:
            criteria = criteria & active_scope

        return CriteriaToPostgresqlConverter.convert(criteria=criteria, table='users')


service = UserSearchService(tenant_id='tenant_123')
query, parameters = service.build_query(only_active=True, corporate_domain='@acme.com')

print(query)
print(parameters)

๐Ÿ”ผ Back to top



๐Ÿ”Ž Simple URL Query Examples

Use SimpleUrlToCriteriaConverter when you want a compact public query format where each parameter becomes one AND filter. Plain parameters use equality, and suffixes map to operators.

from criteria_pattern.converters import SimpleUrlToCriteriaConverter


criteria = SimpleUrlToCriteriaConverter.convert(
    url='https://api.example.com/users?name=Doe&age_gte=18&page_size=20&page_number=1'
)

print(criteria.filters[0].field, criteria.filters[0].operator, criteria.filters[0].value)
# >>> name EQUAL Doe

print(criteria.filters[1].field, criteria.filters[1].operator, criteria.filters[1].value)
# >>> age GREATER_OR_EQUAL 18

print(criteria.page_size, criteria.page_number)
# >>> 20 1

Common suffixes:

URL parameter Parsed filter
name=Doe Filter(field='name', operator=Operator.EQUAL, value='Doe')
name_eq=Doe Filter(field='name', operator=Operator.EQUAL, value='Doe')
status_ne=DELETED Filter(field='status', operator=Operator.NOT_EQUAL, value='DELETED')
price_gt=10 Filter(field='price', operator=Operator.GREATER, value=10)
price_gte=10 Filter(field='price', operator=Operator.GREATER_OR_EQUAL, value=10)
price_lt=100 Filter(field='price', operator=Operator.LESS, value=100)
price_lte=100 Filter(field='price', operator=Operator.LESS_OR_EQUAL, value=100)
email_contains=gmail.com Filter(field='email', operator=Operator.CONTAINS, value='gmail.com')
name_starts_with=Ad Filter(field='name', operator=Operator.STARTS_WITH, value='Ad')
email_ends_with=.com Filter(field='email', operator=Operator.ENDS_WITH, value='.com')
status_in=ACTIVE&status_in=PENDING Filter(field='status', operator=Operator.IN, value=['ACTIVE', 'PENDING'])
status_not_in=DELETED Filter(field='status', operator=Operator.NOT_IN, value=['DELETED'])
deleted_at_is_null=true Filter(field='deleted_at', operator=Operator.IS_NULL, value=None)
deleted_at_is_not_null=true Filter(field='deleted_at', operator=Operator.IS_NOT_NULL, value=None)

Comma-separated values are also supported for list operators:

criteria = SimpleUrlToCriteriaConverter.convert(
    url='https://api.example.com/users?status_in=ACTIVE,PENDING,BLOCKED'
)

print(criteria.filters[0].value)
# >>> ['ACTIVE', 'PENDING', 'BLOCKED']

You can map public field names to internal field names:

criteria = SimpleUrlToCriteriaConverter.convert(
    url='https://api.example.com/users?full_name_contains=Doe',
    fields_mapping={'full_name': 'name'},
)

print(criteria.filters[0].field, criteria.filters[0].operator, criteria.filters[0].value)
# >>> name CONTAINS Doe

You can also extend or override URL suffixes:

criteria = SimpleUrlToCriteriaConverter.convert(
    url='https://api.example.com/users?created_at_after=2026-05-18',
    suffix_operator_mapping={'after': Operator.GREATER},
)

print(criteria.filters[0].field, criteria.filters[0].operator, criteria.filters[0].value)
# >>> created_at GREATER 2026-05-18

๐Ÿ”ผ Back to top

๐Ÿค Contributing

We love community help! Before you open an issue or pull request, please read:

Thank you for helping make ๐Ÿค๐Ÿป Criteria Pattern package awesome! ๐ŸŒŸ

๐Ÿ”ผ Back to top



๐Ÿ”‘ License

This project is licensed under the terms of the MIT license.

๐Ÿ”ผ Back to top

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

criteria_pattern-3.11.0.tar.gz (31.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

criteria_pattern-3.11.0-py3-none-any.whl (63.9 kB view details)

Uploaded Python 3

File details

Details for the file criteria_pattern-3.11.0.tar.gz.

File metadata

  • Download URL: criteria_pattern-3.11.0.tar.gz
  • Upload date:
  • Size: 31.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for criteria_pattern-3.11.0.tar.gz
Algorithm Hash digest
SHA256 c26d3b60895a297da6abd11219b84df4a6a641ac063411e9e88b97a97f9e4f16
MD5 f2e43f0f40feaf9e8b423ff838e6b467
BLAKE2b-256 a48a3670163cd5084db497d9bb4a35d4088def9140f5bc531faf684ae5be4059

See more details on using hashes here.

Provenance

The following attestation bundles were made for criteria_pattern-3.11.0.tar.gz:

Publisher: ci.yaml on adriamontoto/criteria-pattern

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file criteria_pattern-3.11.0-py3-none-any.whl.

File metadata

File hashes

Hashes for criteria_pattern-3.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8435fc486c48a8232743b608680a7768e67ceb6d8d1ece430c1846391db503fe
MD5 8f7744c4d24b3128cc813d54457f5cbd
BLAKE2b-256 606cdcfabb418e9358aee61583c8bfb8ceb1eab4453c1018ec8ad1769eb7529a

See more details on using hashes here.

Provenance

The following attestation bundles were made for criteria_pattern-3.11.0-py3-none-any.whl:

Publisher: ci.yaml on adriamontoto/criteria-pattern

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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