Перейти к содержанию

Публичная типизация современного API

Современный API поставляется с аннотациями в исходном коде и маркером fuzzyroutines/py.typed по PEP 561. Поддерживаются CPython 3.13 и 3.14. Импортируйте современные имена из fuzzyroutines или специализированных модулей; оба пути сохраняют одинаковые типы и объекты во время выполнения.

MembershipScalar принимает встроенные числа с плавающей точкой и реализации numbers.Real, включая целые числа и fractions.Fraction. Объединение явно включает float, поскольку статические анализаторы не моделируют каждое встроенное число как подкласс numbers.Real. Проверка во время выполнения по-прежнему отклоняет логические значения, неконечные координаты и недопустимые степени принадлежности. Статические аннотации не кодируют эти численные ограничения.

MembershipCallable — структурный контракт: функция, вызываемый объект или связанный метод должны принимать любую координату MembershipScalar и возвращать MembershipScalar. Функция с аннотацией только float обещает меньше, чем весь этот диапазон типов. Для пользовательских функций принадлежности используйте публичный скалярный псевдоним:

from fractions import Fraction

from fuzzyroutines import (
    ContinuousUniverse,
    MembershipCallable,
    MembershipScalar,
    ScalarFuzzySet,
)


def CustomMembership(coordinate: MembershipScalar) -> MembershipScalar:
    """Return a constant rational membership grade."""

    return Fraction(1, 2)


membership: MembershipCallable = CustomMembership
fuzzySet = ScalarFuzzySet(ContinuousUniverse(0, 1, True, True), membership)
grade: MembershipScalar = fuzzySet.Membership(0.5)

Скалярные результаты остаются MembershipScalar, поэтому аннотации не требуют преобразования рациональной или другой вещественной арифметики в float. Операции аналитических свойств требуют стандартного MembershipFunction или доверенного аналитического источника; произвольная функция не содержит необходимых аналитических оснований. DeriveProperties выбирает ContinuousFuzzyProperties или DiscreteFuzzyProperties по переданному универсальному множеству. Выборочные операции возвращают отдельные типы выборочных свидетельств. Поиск по шкале возвращает LinguisticTerm | None, поэтому вызывающий должен обрабатывать отсутствие терма.

Typeshed моделирует арифметику numbers.Real через интерфейс, совместимый с комплексными числами; выводимые результаты шире вещественных скалярных операций. На проверенных внутренних арифметических границах узкий cast(float, value) даёт анализатору представление вещественной арифметики. typing.cast возвращает тот же объект во время выполнения: он не вызывает float(value) и не меняет рациональную арифметику. Публичные результаты сохраняют широкий скалярный контракт, а современная диагностика остаётся полностью проверяемой.

Неизменяемые поля dataclass и доступные только для чтения таблицы параметров принадлежности видны анализатору. Операторы и функции анализа требуют конкретных типов политик и областей; передача другого семейства политики является ошибкой типов.

Воспроизводимая проверка

Установите закреплённый анализатор отдельно от зависимостей времени выполнения:

python -m pip install -r requirements-typing.txt
python -m tools.typecheck

Закреплённая версия mypy 1.19.1 поддерживает объявленные версии Python и псевдонимы PEP 695; транзитивные зависимости анализатора закреплены в том же файле. Проверка исходного кода отключает инкрементальное переиспользование, поэтому успешный результат не зависит от старого кэша. Сборщик wheel в CI и бэкенд сборки также используют фиксированные версии зависимостей только для разработки, с отключённой изоляцией сборки.

mypy.ini включает строгую проверку, коды диагностики и отчёт о неиспользуемых подавлениях. Он явно покрывает корень пакета, каждый современный модуль, включая внутреннюю численную проверку, команду анализатора и всех статических потребителей. Глобального подавления ошибок нет. Исторический фасад FuzzyRoutines, адаптеры _legacy и исполняемый модуль Examples имеют узкую границу пропуска импортов. Их контракт совместимости во время выполнения сохраняется; обещание современной статической типизации на них не распространяется.

Фикстуры потребителей в tests/typing включают допустимые импорты, численный ввод, пользовательские функции, политики, неизменяемые результаты и проверки точных возвращаемых типов. Ожидаемо недопустимые вызовы и присваивания имеют конкретный код диагностики. Если сигнатура становится Any или начинает принимать недопустимое использование, ранее нужное подавление становится неиспользуемым и проверка завершается ошибкой.

Граница установленного wheel

Workflow Public modern typing проверяет исходные контракты и собирает wheel на обеих поддерживаемых версиях Python. Он устанавливает wheel и закреплённый анализатор в новое виртуальное окружение, затем выполняет:

/path/to/isolated/environment/bin/python /path/to/checkout/tools/typecheck.py --installed

Этот режим проверяет, что Python находит пакет вне рабочего дерева и что установленный пакет содержит py.typed. Он копирует всех потребителей во временный каталог вне репозитория и запускает mypy там с изолированной обработкой путей Python, очищенными MYPYPATH и PYTHONPATH и свежим кэшем. Поэтому потребители проверяют аннотации wheel, а не случайно найденные файлы исходного дерева. Временные пробы удаляются и при успехе, и при неудаче; ошибки импорта и анализатора сохраняют ненулевой код завершения.