Tox: per-platform configuration for tools like flake8 and pylint - python

I've got tox.ini configuration for ci both in linux and windows environments, something like that:
[tox]
envlist =
{py3,py27}-{test,lint}-{linux,windows}
flake8
check-package
skip_missing_interpreters = true
isolated_build = True
distdir = dist
[testenv]
platform =
linux: linux
windows: win
# Reuse py3 and py27 envs for pylint
envdir =
py3: {toxworkdir}/py3
py27: {toxworkdir}/py27
!py3-!py27: {toxworkdir}/{envname}
deps =
py27: setuptools < 45.0.0
# test extras must include pytest and pylint
extras = test
commands =
test: python -m pytest -c {toxinidir}/pytest.ini --junitxml=test-reports/pytest.{envname}.xml {posargs}
lint: python -m pylint --rcfile=tox.ini src/displaylink {posargs}
[testenv:flake8]
basepython = python3
skip_install = true
deps = flake8
commands = flake8 src tests
[tool:pylint]
disable = missing-docstring,
R,
C,
line-too-long
output-format = parseable
reports = no
extension-pkg-whitelist = win32api, win32gui
[flake8]
ignore = E501, E722, W503
per-file-ignores =
# imported but unused
__init__.py: F401
max-complexity = 10
Question is how may I add per-platform configuration for tools (flake and pylint) ? I need to exclude files/dirs from flake8 and pylint runs depending on os, i.e. I've got windows subdir with files that won't pass linting on linux and vice-versa
EDIT:
example of pylint errors I have on linux:
py3-lint-linux run-test: commands[0] | python -m pylint --rcfile=tox.ini src/displaylink
************* Module displaylink.qa.windows.registry
registry.py:4: [E0401(import-error), ] Unable to import 'win32con'
registry.py:74: [E0602(undefined-variable), reg_value_exists] Undefined variable 'WindowsError'
registry.py:82: [E0602(undefined-variable), reg_key_exists] Undefined variable 'WindowsError'

Maybe I miss some parts of your requirement, but running flake8 platform specific seems pretty straightforward:
[testenv]
platform =
linux: linux
windows: win
[testenv:flake8]
deps = flake8
commands =
linux: flake8 <linux specific directories>
windows: flake8 <windows specific directories>
Also compare to the official documentation.

Related

Is there something like python setup.py --version for pyproject.toml?

With a simple setup.py file:
from setuptools import setup
setup(
name='foo',
version='1.2.3',
)
I can do
$> python setup.py --version
1.2.3
without installing the package.
Is there similar functionality for the equivalent pyproject.toml file:
[project]
name = "foo"
version = "1.2.3"
With Python 3.11+, something like this should work:
python3.11 -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])"
This parses the TOML file directly, and assumes that version is not dynamic.
In some cases, version is declared dynamic in pyproject.toml, so it can not be parsed directly from this file and a solution (the only one?) is to actually build the project, or at least its metadata.
For this purpose, we can use the build.util.project_wheel_metadata() function from the build project, for example with a small script like this:
#!/usr/bin/env python
import argparse
import pathlib
import build.util
def _main():
args_parser = argparse.ArgumentParser()
args_parser.add_argument('path')
args = args_parser.parse_args()
path_name = getattr(args, 'path')
path = pathlib.Path(path_name)
#
metadata = build.util.project_wheel_metadata(path)
version = metadata.get('Version')
print(version)
if __name__ == '__main__':
_main()
Or as a one-liner:
python -c "import build.util; print(build.util.project_wheel_metadata('.').get('Version'))"

How to use python black formatter under a project for python>=3.5 managed by poetry?

I created a python project "foo" with Poetry.
This is the content of pyproject.toml:
[tool.poetry]
name = "bar"
version = "0.1.0"
description = ""
[tool.poetry.dependencies]
python = ">=3.5"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
This package is compatible with Python3.5.
I want to black formatter, which is not compatible with Python3.5.
I think there is no problem if I use Python>=3.6 for development, but I cannot install black formatter:
$ poetry add black --dev
[SolverProblemError]
The current project's Python requirement (>=3.5) is not compatible with some of the required packages Python requirement:
- black requires Python >=3.6
Because no versions of black match >19.10b0,<20.0
and black (19.10b0) requires Python >=3.6, black is forbidden.
So, because bar depends on black (^19.10b0), version solving failed.
So I installed black directly with pip:
$ poetry run pip install black
This way doesn't sit well with me. I want to install black by poetry.
How should I do? (I don't want to modify the dependency to python>=3.6)
Seems a bit late but actually you can do what you want even if black supports only Python >=3.6.2
In your pyproject.toml you can define a restricted dependcy as documented in https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies
[tool.poetry.dependencies]
python = ">=3.5"
[tool.poetry.dev-dependencies]
black = {version = "^21.7b0", python = ">=3.6.2"}
Poetry won't complain and you won't have any problems since it is a dev dependency.
You need to edit the python value in your pyproject.toml:
[tool.poetry]
name = "bar"
version = "0.1.0"
description = ""
[tool.poetry.dependencies]
python = ">=3.6"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

Platform specific settings in tox

I would like to specify a few additional settings in my tox configuration, but only when I'm running on a certain platform.
For example, when running on windows I want an extra environment variable to be defined. I would like to do something like this
[tox]
envlist = env1, env2, env_win32, env_arch
[testenv]
commands=
do stuff...
[testenv]
platform = arch
setenv =
NAME = VALUE
[testenv:env_win32]
plaform = win32
more = stuff
[testenv:env_arch]
platform = arch
more = different_stuff
but this doesn't work because of the duplicate testenv section. I want the specified environment variable to apply to all environments (e.g. env1, env2, env_arch) but not on env_win32.
Note: The specific case that I'm dealing with is that on *nix platforms we need to specify an extra environment variable for install_command only, so the command includes /usr/bin/env NAME=VALUE at the beginning. Unfortunately, this doesn't exist on windows which causes it to fail. I want to conditionally define the install_command differently depending on the platform to get around this.
[tox]
envlist = env1, env2, env_win32, env_linux
[testenv]
install_command = pip install {opts} {packages}
[testenv-linux]
platform = linux
install_command = /usr/bin/env NAME=VALUE pip install {opts} {packages}
[testenv:env_win32]
plaform = win32
install_command = {[testenv]install_command}
[testenv:env_linux]
platform = linux
install_command = {[testenv-linux]install_command}

How to run different tox command inside Jenkins environment?

I would like to use different command line arguments for py.test, depending on environment: running locally there should be only default ones, but on Jenkins I would like to add --junitxml=junit-{envname}.xml, so the test results could be published in nice format.
I know from documentation, that there is special [tox:jenkins] section, which should be used in case there is defined 'JENKINS_URL' or 'HUDSON_URL'. So now I created simple tox.ini file:
[tox]
envlist = py27, py35
[tox:jenkins]
commands = echo "We are in JENKINS!"
[testenv]
setenv =
PYTHONPATH = {toxinidir}:{toxinidir}/my_module
commands = python setup.py test
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/requirements_test.txt
And have defined JENKINS_URL environment variable:
export JENKINS_URL=true
I expect, that if I run tox, then my original command will be substituted with echo, but it doesn't work, instead I end with original command been executed.
Could someone help me with this problem?
Okay, found the solution myself:
[tox]
envlist = py27, py35
[testenv]
setenv =
PYTHONPATH = {toxinidir}:{toxinidir}/my_module
commands = py.test {env:CUSTOM_ARGS} ; <== use environment variable here
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/requirements_test.txt
and in Jenkins just define CUSTOM_ARGS environment variable like this:
export CUSTOM_ARGS="--junitxml=junit.xml"
You could have used positional arguments.
Like this:
commands = py.test --mandatory-flag {posargs:--default-flag}
And in Jenkins you can call tox like this:
tox -- --override-flag
Note the separation with two dashes --.

how to configure tox for getting the logs

I am trying to use tox automating testing in my project. But I am not able to figure out where the logs or prints from my test_methods in python file goes while using tox. I also grepped the entire tox directory for logs but couldn't find it.
Questions
1) How to configure log directory in tox ?
2) What is the default configuration for logs ?
Any Pointers to the documentation and examples ?
My tox.ini file
[tox]
minversion = 1.6
skipsdist = True
[testenv]
skip_install = True
setenv =
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/test-requirements.txt
passenv = LANG
[testenv:test]
commands = ./test.sh --slowest --testr-args='{posargs}'
it's not really an answer, but I ended up using asserts.. so instead of
print(type(x))
I do
assert type(x)==1
which gives me
E AssertionError: assert <class 'tuple'> == 1
... so it's a tuple.. A bit crap but it works
There's envlogdir exactly for that:
envlogdir=path
defines a directory for logging where tox will put logs of tool invocation.
default: {envdir}/log
By default your testrunner's logs are in ./.tox/envname/log/envname-k.log where envname is environment name (e.g. py27) and k is number of the command which actually runs your testrunner (python -m testtools.run). k==0 is envname creation log, k==1 is log for first dependency installation, etc.
You can use --verbose and throw error intentionaly to print out log
Example:
print('HERE')
assertTrue(False)
tox -e unit-tests --verbose
If you use Linux, you can simply log the test using:
tox > toxlog.txt
And the output will be in the toxlog.txt file

Categories