Поэзия + Cython + тесты (Nosetests) - PullRequest
1 голос
/ 03 марта 2020

Я использую Poetry для сборки своего пакета с расширениями Cython. Теперь я хотел бы написать тесты для этого (желательно с тестом на нос). Проблема в том, что мне нужно предварительно скомпилировать двоичные файлы, что обычно делается с setup.py build_clib build_ext --inplace

. Лучшее решение для меня - запустить тесты без создания дополнительных .py или .sh файлов в каталоге, как у меня уже есть. build.py. Можно запускать тесты после установки пакета в виртуальной среде, как это реализовано на сервере readthedocs.

Я также познакомился с taskipy, поэтому некоторые команды bash в моем pyproject.toml тоже хорошо Любые другие пакеты, которые работают с pyproject.toml, приветствуются.

Возможно, есть какие-то хуки для Поэзии, так как она цитонизируется и компилируется при создании .whl дистрибутивного файла.

Любая помощь по этому вопросу будет оценена.

UPD Токс выглядит как подходящий инструмент, но он не видит pyproject.toml, находясь в каталоге. Ссылки на репозитории с tox и cython в пакетах или руководствах приветствуются.

1 Ответ

2 голосов
/ 04 марта 2020

Если расширение является частью дистрибутива, вам не нужно ничего делать, кроме того, что poetry install - poetry создаст расширения на месте как часть редактируемой установки вашего проекта.

В других случаях вы можете встроить вызывающие команды distutils в свои тесты как часть установки / разрыва комплекта. Я не очень знаком с nose, но вот простой пример. Представьте, что у меня есть fib.pyx (это пример из книги по Cython):

def fib(long n):
    '''Returns the nth Fibonacci number.'''
    cdef long a=0, b=1, i
    for i in range(n):
        a, b = a + b, a
    return a

test_fib.py модуль, который создает библиотеку fib и удаляет ее при успешном выполнении тестов:

from distutils.dist import Distribution
from distutils.core import Extension
from pathlib import Path
from Cython.Build import cythonize


fib_source = Path('fib.pyx')

# distutils magic. This is essentially the same as calling
# python setup.py build_ext --inplace
dist = Distribution(attrs={'ext_modules': cythonize(fib_source.name)})
build_ext_cmd = dist.get_command_obj('build_ext')
build_ext_cmd.ensure_finalized()
build_ext_cmd.inplace = 1
build_ext_cmd.run()

fib_obj = Path(build_ext_cmd.get_ext_fullpath(fib_source.stem))

# the lib was built, so the import will succeed now
from fib import fib


def teardown_module():
    # remove built library
    fib_obj.unlink()

    # if you also want to clean the build dir:
    from distutils.dir_util import remove_tree
    remove_tree(build_ext_cmd.build_lib)
    remove_tree(build_ext_cmd.build_temp)


# sample tests

def test_zero():
    assert fib(0) == 0


def test_ten():
    assert fib(10) == 55

Возможно, вы настраиваете setup_kwargs в пользовательском build.py. Чтобы повторно использовать этот код, адаптируйте инициализацию dist, например:

from build import build

setup_kwargs = {}
build(setup_kwargs)
dist = Distribution(attrs=setup_kwargs)
...

pytest пример

Все может быть организовано намного удобнее с помощью pytest. Создайте файл с именем conftest.py с кодом установки / разрыва, извлеченным для хуков:

# conftest.py

from distutils.core import Extension
from distutils.dist import Distribution
from distutils.dir_util import remove_tree
from pathlib import Path
from Cython.Build import cythonize


def pytest_sessionstart(session):
    fib_source = Path('fib.pyx')
    dist = Distribution(attrs={'ext_modules': cythonize(fib_source.name)})
    build_ext_cmd = dist.get_command_obj('build_ext')
    build_ext_cmd.ensure_finalized()
    build_ext_cmd.inplace = 1
    build_ext_cmd.run()
    session.fib_obj = Path(build_ext_cmd.get_ext_fullpath(fib_source.stem))


def pytest_sessionfinish(session):
    session.fib_obj.unlink()

Теперь тесты становятся намного чище, и код установки запускается один раз для всего сеанса тестирования. Приведенный выше пример тестирования, вновь:

from fib import fib


def test_zero():
    assert fib(0) == 0


def test_ten():
    assert fib(10) == 55
...