Description
It appears that (binary!) imports from markupsafe._speedups
have side-effects in a pylint
invocation. The file that is linted attempts to import a missing package in a try-except
clause. A common invocation of pylint
produces empty (plug-in) reports if markupsafe
is imported before pylint is linting (e.g. imported by a pylint plugin). However, output is produced as expected if either:
- the missing import is installed; or
- the
try
block is replaced by a non-import statement (e.g. raise ValueError
); or
markupsafe.__init__
is modified to prefer imports from markupsafe._native
; or
- one imports a Cython package, e.g.
ormsgpack
, instead of markupsafe
.
The first two observations may help in determining the root issue, but are not the problem themselves. The second two observations are what made me report the issue at MarkupSafe
, as that suggests that the issue is specific to this package. However: I don't know where the root cause is, so I'm submitting this issue to both MarkupSafe and Pylint and trust that the community has a more complete understanding of the powers at play.
The issue at Pylint
(copy of this issue): https://github.com/PyCQA/pylint/issues/8026.
This issue lies at the root of https://gitlab.com/smueller18/pylint-gitlab/-/issues/18.
Setup
I have two files in the same directory: invoke_pytest.py
and my_module.py
# invoke_pytest.py
import markupsafe # this import is not used -- it can only contribute side-effects or invoke pylint side-effects!
from pylint import run_pylint
run_pylint(
argv=[
"--output-format=pylint_junit.JUnitReporter:pylint-report.xml",
"my_module.py",
]
)
# my_module.py
try:
import gmpy2
except ImportError:
pass
I have a virtual environment in which I installed pylint pylint-junit markupsafe
. pylint-junit
is merely needed to show that a pylint plugin becomes unable to produce output. The issue surfaced originally in pylint-gitlab
, which has markupdown
as a dependency through jinja2
.
$ python invoke_pytest.py; head pylint-report.xml
Expected output
After commenting import markupsafe
from invoke_pytest.py
, the output is as expected:
$ python invoke_pytest.py; head pylint-report.xml
<?xml version="1.0" ?>
<testsuites disabled="0" errors="0" failures="2" tests="4" time="0.0">
<testsuite disabled="0" errors="0" failures="0" name="Command line or configuration file" skipped="0" tests="1" time="0">
<testcase name="Command line or configuration file:0:0" classname="pylint">
<system-out>All checks passed for: None</system-out>
</testcase>
</testsuite>
<testsuite disabled="0" errors="0" failures="2" name="my_module" skipped="0" tests="3" time="0">
<testcase name="my_module:0:0" classname="pylint" file="my_module.py">
<system-out>All checks passed for: my_module.py</system-out>
As mentioned above, the same output is achieved if markupsafe.__init__
is adjusted to not import from ._speedups
.
Environment
Windows 10 -> WSL2 -> Ubuntu
$ python --version
Python 3.10.9
$ pip list
Package Version
----------------- -------
astroid 2.12.13
dill 0.3.6
isort 5.11.4
junit-xml-2 1.9
lazy-object-proxy 1.9.0
MarkupSafe 2.1.1
mccabe 0.7.0
pip 22.3.1
platformdirs 2.6.2
pylint 2.15.9
pylint-junit 0.3.2
setuptools 65.5.0
six 1.16.0
tomli 2.0.1
tomlkit 0.11.6
wrapt 1.14.1
I understand that the example is not quite minimal yet -- there is a lot of pylint stuff under the hood. Again, let me emphasize that I reach out to both communities and I hope to jointly reduce the example shortly.
I want to finish this report by stating that I appreciate all your efforts, keep up the good work!