pytest: Slowdown of pytest collection in sqlalchemy in python 3.9+
- a detailed description of the bug or problem you are having
- output of
pip list
from the virtual environment you are using - pytest and operating system versions
- minimal example if possible
We noticed that from python 3.9 pytest takes a significantly more time (~4x) to collect the tests for sqlalchemy. You can run the following docker to compare. python 3.7 and 3.8 are ok (not fast not slow), python 3.9 and 3.10 are noticeably slower
docker run -ti --name py --rm python:3.7 bash -c 'git clone https://github.com/sqlalchemy/sqlalchemy.git --depth 100; pip install pytest; cd sqlalchemy; time pytest --collect-only'
docker run -ti --name py --rm python:3.8 bash -c 'git clone https://github.com/sqlalchemy/sqlalchemy.git --depth 100; pip install pytest; cd sqlalchemy; time pytest --collect-only'
docker run -ti --name py --rm python:3.9 bash -c 'git clone https://github.com/sqlalchemy/sqlalchemy.git --depth 100; pip install pytest; cd sqlalchemy; time pytest --collect-only'
docker run -ti --name py --rm python:3.10 bash -c 'git clone https://github.com/sqlalchemy/sqlalchemy.git --depth 100; pip install pytest; cd sqlalchemy; time pytest --collect-only'
the times on my pc are as floows:
#py37
real 0m27.949s
user 0m26.717s
sys 0m1.220s
#py38
real 0m27.952s
user 0m26.893s
sys 0m1.050s
# py39
real 1m45.581s
user 1m42.574s
sys 0m2.990s
# py310
real 1m46.255s
user 1m43.648s
sys 0m2.590s
cc @zzzeek
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 31 (14 by maintainers)
Ok, I had to use
hookwrapper
inpytest_runtest_teardown
since that finalizer needs to run after all the class fixture ones, but it seems to be working,The last version is on gerrit https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/3332
edit, yes the test all pass.
Having the previous behaviour of addfinalizer would be nice to have, but I think this can be closed. Thanks a lot for all the support and help!
We are planning a release candidate pretty soon, likely within the week, so shouldn’t be far.
The traceback shows
get_test_class_from_fn
, does that function returnpytest.Class
both in v6 and v7? If so things should just work, you should be able to attach finalizers to classes.I don’t seeget_test_class_from_fn
in the link, was that removed afterwards?Ahh I see it in Gerrit. You actually don’t need that function,
item.getparent(pytest.Class)
will return the class for that item, or None in case it doesn’t have a class (it is a free function). And this will work in v6 and v7.Same is valid for other places like this:
Which can be written as:
item.getparent(pytest.Module)
will always return apytest.Module
of course.cant wait for the speedup! ive been pretty depressed about the slow collection times for some time now, there have been different “slow collection” issues over the years (like in the 4.x series too with fixtures).
btw I’ve started supporting pytest v7 here https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/3332
edit: apart from the
addfinalizer
issue above, everything seems to be working with v7. I confirm that also in windows the speedup is very significant, 1:33s down to 18sedit of edit: no still some work to be done. we seem to be loosing the class variables from the test function that handle the skips. probably related to the parent change
Thanks for all the help and suggestions!
I confirm that this commit does collect and also the slowdown in gone:
would it be possible to backport that improvement to the v6 series? @bluetech alternatively is there an approximate date you are aiming towards for v7?
Regarding your suggestion @nicoddemus that fixes the collection but it will require other changes. The issue is that we use
parent.parent
in many places and we now should just useparent
. This change seems one that may trip many places even if they are not usingInstance
directly.We also tripping an assert while adding a finalizer:
pdbing there in v6 shows that
the_class.session._setupstate.statck
is also empty (and stack is a list not a dict):are are trying to add it in
pytest_runtest_setup
here: https://github.com/sqlalchemy/sqlalchemy/blob/9c5dfddfbd405a72d33b72ed097690a6c2c88b3a/lib/sqlalchemy/testing/plugin/pytestplugin.py#L400what’s the suggested way of adding a class finalizer?