las dependencias de poesía no están disponibles cuando se ejecuta un script con tox

3

Tengo un proyecto de Python que usa poesía y toxinas. Tiene código fuente, pruebas y scripts (cuadernos juptext). No puedo importar las dependencias de desarrollo en los scripts, pero puedo en las pruebas.

Cuando me encontré con este problema, creé el siguiente ejemplo mínimo. Al principio, no funcionó, luego lo manipulé y ahora está funcionando. Así que eliminé el proyecto que tiene el problema real para que no se pueda distinguir más que el nombre del proyecto, la ubicación, el entorno virtual y el directorio .git, pero eso todavía no funciona.

ACTUALIZAR la eliminación de todos los artefactos de compilación y el virtualenv para el ejemplo mínimo hace que deje de funcionar nuevamente

ACTUALIZAR agregando la línea scripts: poetry installa los comandos tox se corrigió solo el ejemplo mínimo

El código fuente, las pruebas y los scripts están en el siguiente diseño

foo
  +--foo
  |  +--__init__.py
  |
  +--tests
  |  +--__init__.py
  |  +--test_foo.py
  |
  +--scripts
  |  +--foo_script.py
  |
  +--pyproject.toml
  +--tox.ini

Los archivos están vacíos o de la siguiente manera:

foo_script.py

import requests

test_foo.py

import requests
import pytest

def test():
    assert True

pyproject.toml

[tool.poetry]
name = "foo"
version = "0.1.0"
description = ""
authors = ["foo maker"]

[tool.poetry.dependencies]
python = "^3.7"
requests = "*"

[tool.poetry.dev-dependencies]
pytest = "^4.6"

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

tox.ini

[tox]
envlist = test, scripts
isolated_build = true
skipsdist = true

[testenv]
basepython = python3.7
whitelist_externals =
    pytest
    bash
commands =
    test: pytest
    scripts: bash -c 'python3 scripts/*.py'

Cuando corro tox, consigo

test run-test-pre: PYTHONHASHSEED='4126239415'
test run-test: commands[0] | pytest
============================= test session starts ==============================
platform linux -- Python 3.6.9, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
cachedir: .tox/test/.pytest_cache
rootdir: /home/#######/foo
collected 1 item                                                               

tests/test_foo.py .                                                      [100%]

============================== 1 passed in 0.09s ===============================
scripts run-test-pre: PYTHONHASHSEED='4126239415'
scripts run-test: commands[0] | bash -c 'python3 scripts/*.py'
Traceback (most recent call last):
  File "scripts/foo_script.py", line 1, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'
ERROR: InvocationError for command /bin/bash -c 'python3 scripts/*.py' (exited with code 1)
___________________________________ summary ____________________________________
  test: commands succeeded
ERROR:   scripts: commands failed
3
  • ¿Tiene pytestinstalado globalmente? Se supone que el tox testenv nombrado testllama al comando pytest, pero no está declarado en ninguna parte como una dependencia por lo que yo sé. Entonces esta prueba debería fallar.
    sinoroc
    3 feb.20 a las 14:30
  • @sinoroc aparentemente sí. no estaba consciente de eso
    joel
    3 feb.20 a las 15:47
  • Por lo que puedo decir, tox no puede reconocer las dependencias de desarrollo de la poesía (no estoy seguro de por qué la poesía inventó lo suyo aquí). Un patrón más común que quizás desee seguir es usar una prueba adicional en su lugar para asegurarse de que las dependencias de prueba como pytest estén instaladas en los entornos _tox, como se explica en esta respuesta: stackoverflow.com/a/59522588/11138259
    sinoroc
    3 feb.20 a las 17:32
0

Creo que algo como lo siguiente debería funcionar:

pyproject.toml

[tool.poetry]
name = "foo"
version = "0.1.0"
description = ""
authors = ["foo maker"]

[tool.poetry.dependencies]
python = "^3.7"
requests = "*"
#
pytest = { version = "^4.6", optional = true }

[tool.poetry.extras]
test = ["pytest"]

# [tool.poetry.dev-dependencies]
# use 'test' extra instead

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

tox.ini

[tox]
envlist = test, scripts
isolated_build = true

[testenv]
basepython = python3.7
whitelist_externals =
    pytest
    bash
extras =
    test
commands =
    test: pytest
    scripts: bash -c 'for f in scripts/*.py; do python "$f"; done'
0

Suponiendo que ha instalado poesía y tox y pytest son dependencias en su pyproject.yml (aviso poetry run, consulte https://python-poetry.org/docs/cli/#run ):

[tox]
envlist = py37
isolated_build = True
skipsdist = True

[testenv]
whitelist_externals = poetry
commands=
    poetry run pytest

opcionalmente, puede hacer que la instalación se realice al ejecutar las pruebas cambiando el último bit a (pero luego necesitará tener instalado tox fuera de la poesía, lo que podría causarle problemas en el futuro)

commands=
    poetry install
    poetry run pytest

Además, dependiendo de su carpeta raíz y de dónde estén las pruebas, puede configurar la ruta para que tox cambie el directorio agregando

changedir = tests

En cuyo caso, todo el archivo se vería así si se encuentra en el directorio foo ejecutando tox:

[tox]
envlist = py37
isolated_build = True
skipsdist = True

[testenv]
whitelist_externals = poetry
commands=
    poetry run pytest
changedir = tests
2
  • @JoelB He votado en contra. Aunque entiendo la idea en ambas sugerencias (sé que también está en las preguntas frecuentes de poesía), creo que esta forma de hacer (llamar a la poesía en los comandos) es algo contraproducente, o al menos contra la filosofía de tox. Más detalles en esta discusión . Un ejemplo obvio es que hará imposible (o al menos muy difícil) probar el proyecto con diferentes versiones de una dependencia, como en esta pregunta .
    sinoroc
    13 feb.20 a las 11:02
  • Muy bien, gracias por dejar una explicación, entiendo el razonamiento. 14 feb.20 a las 13:39
-1

Primero necesito instalar las dependencias con poetry install. Luego, agregue poetry runal comienzo del comando para habilitar las dependencias. Además, ejecutar scripts de Python como ese solo ejecutará el primero, pasando el nombre de los demás como argumentos al primer programa. En su lugar use for f in scripts/*.py; do python "$f"; done(ver aquí )

Todos juntos

poetry install
poetry run bash -c 'for f in scripts/*.py; do python "$f"; done'
5
  • ¿No crea un entorno virtual de poesía desde dentro del entorno virtual de toxinas ?
    sinoroc
    2 feb.20 a las 12:51
  • @sinoroc no lo sé, pero es lo que sugieren los documentos de poesía python-poetry.org/docs/faq/#is-tox-supported
    joel
    3 feb.20 a las 23:40
  • Lo sé, también he visto esto en el documento. Todo el asunto simplemente no tiene ningún sentido para mí. tox ya se encarga de instalar el proyecto y sus dependencias en un entorno virtual. Así que no hay necesidad de involucrar a la poesía en este punto, excepto para construir el sdist , que es exactamente lo que isolated_build = truehace gracias a PEP517 y PEP518.
    sinoroc
    4 feb.20 a las 10:45
  • @sinoroc entiendo tu punto, aunque personalmente siento que la poesía debería estar a cargo de las dependencias no de toxinas, ya que yo no usaría toxinas en todos los casos, pero usaría poesía
    joel
    4 feb.20 a las 11:13
  • 1
    Verdadero. Depende para qué quieras usar toxinas . No estoy del todo seguro de que su caso de uso requiera toxinas en absoluto. En general, tox se utiliza para realizar pruebas con varias versiones de Python. Y también contra múltiples versiones de una dependencia, y aquí es donde la poesía definitivamente se interpone en el camino de la toxicidad , vea esta pregunta y este tema, por ejemplo. En esos casos la poesía reinstala el proyecto y las dependencias lo que cancela el trabajo realizado anteriormente por tox .
    sinoroc
    4 feb.20 a las 11:22