Skip to main content

Classic Criteria

Основывается на книге Эрика Эванса "Domain Driven Design: tackling complexity in the heart of software".

Предоставляет базовый примитив для описания языка предметной области - Criteria (Критерий).

Критерий нужен для описания выборки объектов. Есть два пути использования - через определение класса, и через декоратор.

Установка

pip install classic-criteria

Критерии-классы

Представим себе, что у нас класс, олицетворяющий понятие из предметной области - задачу:

Также, представим себе, что в предметной области задача называется открытой, если нет времени завершения и просроченной, если больше работа не завершена больше какого-то количества дней.

Также представим, что нам необходимо получать из некоторого хранилища задачи, соответствующие этим критериям.

Задачу можно описать обычным датаклассом, а состояния задач - критериями. У критериев можно определить метод is_satisfied_by, которые будут определять, подходит ли объект под этот критерий или нет:

from datetime import datetime
from dataclasses import dataclass
from typing import Optional

from classic.criteria import Criteria


@dataclass
class Task:
    created_at: datetime
    finished_at: Optional[datetime] = None


@dataclass
class Open(Criteria[Task]):
    """Критерий для открытых задач"""

    def is_satisfied_by(self, candidate: Task) -> bool:
        return candidate.finished_at is None

    
@dataclass
class Obsolete(Criteria[Task]):
    """Критерий для просроченных задач"""
    days_to_work: int

    def is_satisfied_by(self, candidate: Task) -> bool:
        return (
            candidate.finished_at is not None and
            (candidate.created_at - candidate.finished_at).days > self.days_to_work
        )

Затем описанные критерии можно использовать в разных сценариях.

Прямое использование

from datetime import datetime

some_task = Task(created_at=datetime(2025, 1, 1))
is_open = Open()

is_open.is_satisfied_by(some_task)
# True

Булева алгебра

Критерии можно связать логическими условиями:

from datetime import datetime

some_task = Task(created_at=datetime(2025, 1, 1))
some_crit = Open() | Obsolete(3)

some_crit.is_satisfied_by(some_task)
# True

Фильтрация

У критерия метод __call__ определен как алиас для is_satisfied_by. Это придает лаконичности при использовании критерия для фильтрации списка:

from datetime import datetime

tasks = [
    Task(created_at=datetime(2025, 1, 1)),
    Task(created_at=datetime(2025, 1, 1),
         finished_at=datetime(2025, 1, 5)),
    Task(created_at=datetime(2025, 1, 1),
         finished_at=datetime(2025, 1, 2)),
] 
some_crit = Open() | Obsolete(3)

filtered_tasks = filter(some_crit, tasks)
# True

Критерии-методы

Критерии можно определить как методы у класса (например, у самой сущности), используя декоратор criteria:

from datetime import datetime
from dataclasses import dataclass
from typing import Optional

from classic.criteria import criteria


@dataclass
class Task:
    created_at: datetime
    finished_at: Optional[datetime] = None
    
    @criteria
    def open(self) -> bool:
        return self.finished_at is None
    
    @criteria
    def obsolete(self, days_to_work: int) -> bool:
        return (
            self.finished_at is not None and
            (self.created_at - self.finished_at).days > days_to_work
        )

У таких критериев есть две группы сценариев использования, использование на инстансах, и использование на классах.

Далее будут примеры с инстансами, аналогичные примерам выше.

Прямое использование

from datetime import datetime

some_task = Task(created_at=datetime(2025, 1, 1))

some_task.open()
# True

Булева алгебра:

from datetime import datetime

some_task = Task(created_at=datetime(2025, 1, 1))

some_task.open() or some_task.obsolete()
# True

Обратите внимание, что булева алгебра используется с and, 'or' и not.

Критерии-методы с классами

Критериев-методы можно использовать без инстансов, обращаясь к классам. При таком применении не произойдет проверки критерия. Полученный объект-критерий предоставляет собой отложенное условие:

from datetime import datetime

is_open = Task.open()  # Отложенная проверка

some_task = Task(created_at=datetime(2025, 1, 1))

is_open.is_satisfied_by(some_task)
# True

Фильтрация

Отложенные критерии также можно использовать для фильтрации списка:

from datetime import datetime

some_crit = Task.open() | Task.obsolete()

tasks = [
    Task(created_at=datetime(2025, 1, 1)),
    Task(created_at=datetime(2025, 1, 1),
         finished_at=datetime(2025, 1, 5)),
    Task(created_at=datetime(2025, 1, 1),
         finished_at=datetime(2025, 1, 2)),
]

filtered_tasks = filter(some_crit, tasks)
# True

Критерии-функции

Также можно использовать декоратор criteria на обычных функциях. Все свойства таких критериев абсолютно аналогичны варианту с методами:

from datetime import datetime
from dataclasses import dataclass
from typing import Optional

from classic.criteria import criteria


@dataclass
class Task:
    created_at: datetime
    finished_at: Optional[datetime] = None
    

@criteria
def task_open(task: Task) -> bool:
    return task.finished_at is None


@criteria
def task_is_obsolete(task: Task, days_to_work: int) -> bool:
    return (
        task.finished_at is not None and
        (task.created_at - task.finished_at).days > days_to_work
    )

Выборки в БД

Также, критерии можно использовать для построения запросов к БД.

Пример рендера и обхода дерева можно увидеть в classic-db-tools.

Download files

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

Source Distribution

classic_criteria-0.2.0.tar.gz (9.9 kB view details)

Uploaded Source

Built Distribution

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

classic_criteria-0.2.0-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file classic_criteria-0.2.0.tar.gz.

File metadata

  • Download URL: classic_criteria-0.2.0.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for classic_criteria-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a23076e495af8d4fb6fee7495dc72f66e208b7a93999c2b488efad3199a863f8
MD5 1f15aa0e6853eeb280d2c0e8a60e3440
BLAKE2b-256 df73ddba5a5a90994517eb51527a1c067e86691ea58b01487dadbefccde6e81c

See more details on using hashes here.

Provenance

The following attestation bundles were made for classic_criteria-0.2.0.tar.gz:

Publisher: publish.yml on variasov/classic-criteria

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

File details

Details for the file classic_criteria-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for classic_criteria-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cdef16440df9aabee120c533ed7ee4d4d03df9dee0cab2adef5f676d059017ec
MD5 893964ad7c7811707344101198af648a
BLAKE2b-256 e7dd58e1b02256f16f5579bda5c0699ed17462950e59cf3b5a69ea951849abec

See more details on using hashes here.

Provenance

The following attestation bundles were made for classic_criteria-0.2.0-py3-none-any.whl:

Publisher: publish.yml on variasov/classic-criteria

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

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

0.0.1

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page