Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IndexError: list index out of range on coverage lcov #1553

Closed
mdantonio opened this issue Feb 8, 2023 · 41 comments
Closed

IndexError: list index out of range on coverage lcov #1553

mdantonio opened this issue Feb 8, 2023 · 41 comments
Labels
bug Something isn't working fixed

Comments

@mdantonio
Copy link

Describe the bug
I'm running coverage lcov and getting the following error: IndexError: list index out of range
This error mostly match this old report: #1362

To Reproduce
How can we reproduce the problem? Please be specific. Don't link to a failing CI job. Answer the questions below:

  1. What version of Python are you using?
    3.10.8
  2. What version of coverage.py shows the problem? The output of coverage debug sys is helpful.
               coverage_version: 7.1.0
                coverage_module: /opt/homebrew/lib/python3.10/site-packages/coverage/__init__.py
                         tracer: -none-
                        CTracer: available
           plugins.file_tracers: -none-
            plugins.configurers: -none-
      plugins.context_switchers: -none-
              configs_attempted: .coveragerc
                   configs_read: /Users/md/api/.coveragerc
                    config_file: /Users/md/api/.coveragerc
                config_contents: b'[run]\nomit = ./venv/*,*test/*,*apps.py,*manage.py,*__init__.py,*migrations*,*admin.py,*urls.py\nrelative_files = True\n\n[report]\nomit = ./venv/*,*test/*,*apps.py,*manage.py,*__init__.py,*migrations*,*admin.py,*urls.py\n'
                      data_file: -none-
                         python: 3.10.8 (main, Oct 21 2022, 22:22:30) [Clang 14.0.0 (clang-1400.0.29.202)]
                       platform: macOS-13.1-arm64-arm-64bit
                 implementation: CPython
                     executable: /opt/homebrew/opt/python@3.10/bin/python3.10
                   def_encoding: utf-8
                    fs_encoding: utf-8
                            pid: 46910
                            cwd: /Users/md/api
                           path: /opt/homebrew/bin
                                 /opt/homebrew/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python310.zip
                                 /opt/homebrew/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10
                                 /opt/homebrew/Cellar/python@3.10/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/lib-dynload
                                 /Users/md/Library/Python/3.10/lib/python/site-packages
                                 /opt/homebrew/lib/python3.10/site-packages
                                 __editable__.rapydo-3.0.finder.__path_hook__
                                 /Users/md/infra/cli
                    environment: HOME = /Users/md
                                 RAPYDO = /Users/md/rapydo/components
                   command_line: /opt/homebrew/bin/coverage debug sys
         sqlite3_sqlite_version: 3.39.4
             sqlite3_temp_store: 0
        sqlite3_compile_options: ATOMIC_INTRINSICS=1, COMPILER=clang-14.0.0, DEFAULT_AUTOVACUUM,
                                 DEFAULT_CACHE_SIZE=-2000, DEFAULT_FILE_FORMAT=4,
                                 DEFAULT_JOURNAL_SIZE_LIMIT=-1, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096,
                                 DEFAULT_PCACHE_INITSZ=20, DEFAULT_RECURSIVE_TRIGGERS,
                                 DEFAULT_SECTOR_SIZE=4096, DEFAULT_SYNCHRONOUS=2,
                                 DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=2,
                                 DEFAULT_WORKER_THREADS=0, ENABLE_COLUMN_METADATA, ENABLE_FTS3,
                                 ENABLE_FTS3_PARENTHESIS, ENABLE_FTS4, ENABLE_FTS5, ENABLE_GEOPOLY,
                                 ENABLE_MATH_FUNCTIONS, ENABLE_PREUPDATE_HOOK, ENABLE_RTREE, ENABLE_SESSION,
                                 MALLOC_SOFT_LIMIT=1024, MAX_ATTACHED=10, MAX_COLUMN=2000,
                                 MAX_COMPOUND_SELECT=500, MAX_DEFAULT_PAGE_SIZE=8192, MAX_EXPR_DEPTH=1000,
                                 MAX_FUNCTION_ARG=127, MAX_LENGTH=1000000000, MAX_LIKE_PATTERN_LENGTH=50000,
                                 MAX_MMAP_SIZE=0x7fff0000, MAX_PAGE_COUNT=1073741823, MAX_PAGE_SIZE=65536,
                                 MAX_SQL_LENGTH=1000000000, MAX_TRIGGER_DEPTH=1000,
                                 MAX_VARIABLE_NUMBER=250000, MAX_VDBE_OP=250000000, MAX_WORKER_THREADS=8,
                                 MUTEX_PTHREADS, SYSTEM_MALLOC, TEMP_STORE=1, THREADSAFE=1
  1. What versions of what packages do you have installed? The output of pip freeze is helpful.
  2. What code shows the problem? Give us a specific commit of a specific repo that we can check out. If you've already worked around the problem, please provide a commit before that fix.
  3. What commands did you run?
pytest --cov-report=term-missing --cov=internal/ --cov=a/internal/ --cov=b/internal/ --cov=c/internal/ --cov=d/internal/ --cov=e/internal/  --cov=f/internal/ --cov=g/internal/
coverage lcov

Expected behavior
I expect it to write to the lcov file without error

Additional context
Add any other context about the problem here.

I was playing with the .coverage -> coverage.lcov conversion and I noticed a different behaviour between coverage 6.5.0 and any 7.x version

version 7 fails with error:

$ coverage lcov

Wrote LCOV report to coverage.lcov
Traceback (most recent call last):
  File "/opt/homebrew/bin/coverage", line 8, in <module>
    sys.exit(main())
  File "/opt/homebrew/lib/python3.10/site-packages/coverage/cmdline.py", line 972, in main
    status = CoverageScript().command_line(argv)
  File "/opt/homebrew/lib/python3.10/site-packages/coverage/cmdline.py", line 744, in command_line
    total = self.coverage.lcov_report(
  File "/opt/homebrew/lib/python3.10/site-packages/coverage/control.py", line 1233, in lcov_report
    return render_report(self.config.lcov_output, LcovReporter(self), morfs, self._message)
  File "/opt/homebrew/lib/python3.10/site-packages/coverage/report.py", line 59, in render_report
    return reporter.report(morfs, outfile=outfile)
  File "/opt/homebrew/lib/python3.10/site-packages/coverage/lcovreport.py", line 45, in report
    self.get_lcov(fr, analysis, outfile)
  File "/opt/homebrew/lib/python3.10/site-packages/coverage/lcovreport.py", line 72, in get_lcov
    line = source_lines[covered-1].encode("utf-8")
IndexError: list index out of range

while coverage 6 is fine:

$ coverage lcov

Wrote LCOV report to coverage.lcov

But also the report is different,

coverage 6 only reports few files (only from the first --cov)

$ coverage report
Name                                 Stmts   Miss  Cover
--------------------------------------------------------
internal/constants.py                    7      0   100%
internal/forms.py                      231      5    98%
internal/hooks.py                       18      0   100%
internal/mixins.py                      62      1    98%
internal/permissions.py                  5      0   100%
internal/read_only_settings.py           2      2     0%
internal/rests.py                       18      0   100%
internal/serializers.py                448    161    64%
internal/templatetags/utilities.py      32      1    97%
internal/views.py                      831    168    80%
internal/widgets.py                     27      2    93%
--------------------------------------------------------
TOTAL                                 1681    340    80%

On the opposite coverage 7 reports the whole list of files from all the --cov

coverage report                                                                                                        
Name                                                            Stmts   Miss  Cover
-----------------------------------------------------------------------------------
a/internal/test/test_dashboard_detail_view.py        30      0   100%
b/internal/test/test_dashboard_views.py               33      0   100%
b/internal/test/test_platform_management.py           21      0   100%
b/internal/test/test_dashboard_detail_views.py           109      1    99%
b/internal/test/test_dashboard_serializers.py             68      1    99%
b/internal/test/test_dashboard_views.py                   59      0   100%
internal/constants.py                                               7      0   100%
internal/forms.py                                                 231      5    98%
internal/hooks.py                                                  18      0   100%
internal/mixins.py                                                 62      1    98%
internal/permissions.py                                             5      0   100%
internal/read_only_settings.py                                      2      2     0%
.... redacted ... very long list

Probably the fact that coverage 6 is successful is because it is only consider a few files and this other issue was about coverage version 6.3.2, so I don't think it is a regression with coverage 7

@mdantonio mdantonio added bug Something isn't working needs triage labels Feb 8, 2023
@AnastasiiaTomashevska
Copy link

Hello, did you solve this problem? I see the same error

@nedbat
Copy link
Owner

nedbat commented Feb 21, 2023

Can you provide me with a way to reproduce the error?

@mdantonio
Copy link
Author

Unfortunately I'm not able to isolate the problem to provide a test case and our repository is private.
I hope that @AnastasiiaTomashevska could be able to share more details 🙏
At the moment we applied this temporarily workaround to downgrade to version 6.5.0

@AnastasiiaTomashevska
Copy link

AnastasiiaTomashevska commented Feb 22, 2023

Can you provide me with a way to reproduce the error?
@nedbat @mdantonio
I have the same errors as described here.
I run tests and create a coverage report, then the code is scanned by sonarqube. I see this error on several of my projects.

I noticed that the error appears in repositories where there are several components, they all have a build and test stage.
Changing the coverage version (to 6.0b1) didn't help me with this.

The way I see the error is this:
ERROR: Line 409 is out of range in the file lambda/handlers//.py (lines: 386)

The command to test and create a coverage is simple:

`#!/bin/bash
set -euxo pipefail

if [ -z ${CI_PROJECT_DIR-} ] ; then
ROOT_DIR=$(pwd)
else
ROOT_DIR=$CI_PROJECT_DIR
fi

pip install --quiet --no-python-version-warning --disable-pip-version-check -U -r ${ROOT_DIR}/api/requirements.txt

cd ${ROOT_DIR}/api
coverage run --source=handlers -m unittest discover
coverage report
coverage xml -o ${ROOT_DIR}/api/coverage.xml
cd ${ROOT_DIR}`

In my coverage file I see that lines are called that are not in the file:

<line number="548" hits="0"/> <line number="550" hits="0"/> <line number="551" hits="0"/> <line number="552" hits="0"/>

I will try to replace it with coverage version 6.5, but this is a temporary solution.

@mushyshah
Copy link

Also facing this issue and I can't seem to get coverage lcov working at all. Neither at 6.5 or anything higher.

python version: 3.7

pytest \
            --cov=/app_tests \
            --capture=no \
            --durations=50 \
              tests \
            `cat ${workspace}/tests/skip_tests_args.txt` \

and then

coverage lcov -i -o /coverage_out/coverage.lcov --rcfile=.coveragerc

coveragerc:

[report]
omit = 
      test/*
       scripts/* 
       etc

@nedbat
Copy link
Owner

nedbat commented Mar 11, 2023

@mushyshah Can you provide me with a way to reproduce the error?

@ewianda
Copy link

ewianda commented Mar 11, 2023

Seeing same error and it seems kind of random

@RomainBrault
Copy link

I could get rid of this error by removing my old .coverage file and run again the test suite (pytest) followed by coverage.

@nedbat nedbat added the good first This could be a good first contribution label Apr 24, 2023
@nhoening
Copy link

nhoening commented Apr 30, 2023

I also see this error when running this:

coverage run --branch --source=flexmeasures -m pytest flexmeasures
coverage lcov

(flexmeasures being my folder with code)

coverage html works fine.

I can't easily give you a reproducible setup right now. It happens locally, but I have a lot f tests. When I ran fewer tests (with pytest -k), the error went away.

But I have a link to an open repo: https://github.com/FlexMeasures/flexmeasures/actions/runs/4841139765/jobs/8627196789?pr=655

And I can attach the .coverage file (renamed so I'm allowed to upload here)
coverage.log

@nhoening
Copy link

I did not have any luck with deleting .coverage or downgrading to 6.5.0.

I run Python3.9 and coverage 7.2.2.

.coveragerc:

[run]
omit = */tests/*, */scripts/*

Removing .coveragerc did not help, either.

@nedbat
Copy link
Owner

nedbat commented May 9, 2023

#1362 and #1620 are other reports of this same problem.

@joshlincoln, @nlou9, @nhoening, @RomainBrault, @ewianda, @mushyshah, @AnastasiiaTomashevska, @mdantonio: can anyone show a full reproduction, including source code? It seems like a lot of people have this issue, but only on private repos?

@nhoening
Copy link

nhoening commented May 9, 2023

Above, I linked to this happening in a public repo. Is that helpful?

@nedbat
Copy link
Owner

nedbat commented May 9, 2023

@nhoening Thanks, I misunderstood your message. I thought you said it wasn't reproducible with your repo. I tried it, and I don't see the error. I ran under Python3.9, but had a large number of test failures:

#11 335.1 >       conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
#11 335.1 E       sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
#11 335.1 E       	Is the server running on that host and accepting TCP/IP connections?
#11 335.1 E       connection to server at "localhost" (::1), port 5432 failed: Cannot assign requested address
#11 335.1 E       	Is the server running on that host and accepting TCP/IP connections?
#11 335.1 E
#11 335.1 E       (Background on this error at: https://sqlalche.me/e/14/e3q8)

When I ran python3.9 -m coverage lcov, I got a complete coverage.lcov file (348K, 13539 lines).

Can you provide more details about how exactly to reproduce the failure? Include every step, even the "pip install", etc. Thanks!

@mdantonio
Copy link
Author

Unfortunately I'm unable to get it reproduced in a sharable way 😞

@nhoening
Copy link

nhoening commented May 9, 2023

@nedbat Yes running the tests in that repo requires a test postgres database to be present (see the github action workflow). In this PR, the run I linked to happens.

I'm not sure what you need - probably a way to reproduce the problem on your local machine.

I don't have time to verify right now what a fresh install would do, but I believe it involves setting up the test db with the commands below, then running make test.

If that doesn't work, maybe I can attempt a better reproduction later.

Test database setup (from https://flexmeasures.readthedocs.io/en/latest/host/data.html)

createdb -U postgres flexmeasures_test
createuser --pwprompt -U postgres flexmeasures_test  # enter "flexmeasures_test" as password

And in the database:

\connect flexmeasures_test
CREATE EXTENSION cube;
CREATE EXTENSION earthdistance;

@nhoening
Copy link

nhoening commented May 9, 2023

@nedbat make test of course doesn't provide the coverage information. Replace it with:

make install-for-test
pytest --cov=flexmeasures --cov-config .coveragerc

Then, for me python3 -m coverage html works, but not the lcov way:

± python3 -m coverage lcov
Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/__main__.py", line 8, in <module>
    sys.exit(main())
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/cmdline.py", line 974, in main
    status = CoverageScript().command_line(argv)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/cmdline.py", line 746, in command_line
    total = self.coverage.lcov_report(
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/control.py", line 1257, in lcov_report
    return render_report(self.config.lcov_output, LcovReporter(self), morfs, self._message)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/report.py", line 59, in render_report
    ret = reporter.report(morfs, outfile=outfile)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/lcovreport.py", line 45, in report
    self.get_lcov(fr, analysis, outfile)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/lcovreport.py", line 72, in get_lcov
    line = source_lines[covered-1].encode("utf-8")
IndexError: list index out of range

I also ran it like you did - without a test database and many tests failing (not all). In that case, python3 -m coverage lcov also does not complain. I hope that helps.

@nedbat
Copy link
Owner

nedbat commented May 9, 2023

Does this work for you?

make install-for-test

Your Makefile has:

install-for-test:
	pip-sync requirements/app.txt requirements/dev.txt requirements/test.txt
	make install-flexmeasures

install-flexmeasures:
	pip install -e

So I get this:

#9 109.1 make install-flexmeasures
#9 109.1 make[1]: Entering directory '/home/me/flexmeasures'
#9 109.1 pip install -e
#9 109.5
#9 109.5 Usage:
#9 109.5   pip install [options] <requirement specifier> [package-index-options] ...
#9 109.5   pip install [options] -r <requirements file> [package-index-options] ...
#9 109.5   pip install [options] [-e] <vcs project url> ...
#9 109.5   pip install [options] [-e] <local project path> ...
#9 109.5   pip install [options] <archive url/path> ...
#9 109.5
#9 109.5 -e option requires 1 argument

@nlou9
Copy link

nlou9 commented May 10, 2023

It seems I could generate xml fine but not lcov

% coverage run -m pytest 
================================================================= test session starts ==================================================================
platform darwin -- Python 3.9.16, pytest-7.2.2, pluggy-1.0.0
rootdir: /Users/nlou/workspace/common-tools
plugins: asyncio-0.21.0, requests-mock-1.10.0, xdist-3.2.1, common-tools-1.2.1755, cov-4.0.0, aiohttp-1.0.4
asyncio: mode=strict
collected 44 items                                                                                                                                     

test/common_tools/test_cli.py ......                                                                                                             [ 13%]
test/common_tools/test_common.py ..                                                                                                              [ 18%]
test/common_tools/test_config.py ........................                                                                                        [ 72%]
test/common_tools/test_ownership.py .......                                                                                                      [ 88%]
test/common_tools/test_testing.py .....                                                                                                          [100%]

================================================================== 44 passed in 1.89s ==================================================================

% coverage lcov
Traceback (most recent call last):
  File "/Users/nlou/.pyenv/versions/3.9.16/bin/coverage", line 8, in <module>
    sys.exit(main())
  File "/Users/nlou/.pyenv/versions/3.9.16/lib/python3.9/site-packages/coverage/cmdline.py", line 974, in main
    status = CoverageScript().command_line(argv)
  File "/Users/nlou/.pyenv/versions/3.9.16/lib/python3.9/site-packages/coverage/cmdline.py", line 746, in command_line
    total = self.coverage.lcov_report(
  File "/Users/nlou/.pyenv/versions/3.9.16/lib/python3.9/site-packages/coverage/control.py", line 1257, in lcov_report
    return render_report(self.config.lcov_output, LcovReporter(self), morfs, self._message)
  File "/Users/nlou/.pyenv/versions/3.9.16/lib/python3.9/site-packages/coverage/report.py", line 59, in render_report
    ret = reporter.report(morfs, outfile=outfile)
  File "/Users/nlou/.pyenv/versions/3.9.16/lib/python3.9/site-packages/coverage/lcovreport.py", line 45, in report
    self.get_lcov(fr, analysis, outfile)
  File "/Users/nlou/.pyenv/versions/3.9.16/lib/python3.9/site-packages/coverage/lcovreport.py", line 72, in get_lcov
    line = source_lines[covered-1].encode("utf-8")
IndexError: list index out of range

% coverage xml
Wrote XML report to coverage.xml

@nedbat
Copy link
Owner

nedbat commented May 10, 2023

@nlou9 Thanks, but I need a repo that I can use to demonstrate the problem. Could you provide me with the repo, even privately? I'm willing to devote time and energy. Can you chip in a repo?

@nlou9
Copy link

nlou9 commented May 10, 2023

@nlou9 Thanks, but I need a repo that I can use to demonstrate the problem. Could you provide me with the repo, even privately? I'm willing to devote time and energy. Can you chip in a repo?

wonder if you have a slack or other contact that we could discuss this

@nlou9
Copy link

nlou9 commented May 10, 2023

After I add the /private/var/folders/* into .coveragerc . It will work with lcov. Since one of my test case will use pytest tmpdir and create temp files under tmpdir. It will be deleted when test finished I assume. I feel like it doesn't handle no source file error for lcov but xml might handle skipping missing scenario. I think the way to reproduce this issue might be creating a test case using tmpdir and create files under that.

[run]
omit =
    .git/*
    .tox/*
    docs/*
    setup.py
    test/*
    tests/*
    bazel-*/*
    /private/var/folders/*

@nhoening
Copy link

Does this work for you?

make install-for-test

I apologize @nedbat we just stopped calling setup.py directly and the missing dot slipped through. It should of course be

install-flexmeasures:
	pip install -e .

@nedbat
Copy link
Owner

nedbat commented May 10, 2023

@nhoening I still need to work out how to get the database going. I'm hoping maybe you'll come up with a way to reproduce it without that. I run these in Docker containers.

@nlou9 You can find me in the Boston Python Slack workspace: https://about.bostonpython.com/slack, or in the Python Discord: https://pythondiscord.com.

@nhoening
Copy link

@nedbat we describe how to use Docker, also for the database, in a tutorial.
When I find the time later today, I'll provide instructions here to do it that way.
This also helps me to improve our developer docs 😃

@nlou9
Copy link

nlou9 commented May 10, 2023

@nedbat thanks! found you on the slack. talk there

@nedbat
Copy link
Owner

nedbat commented May 10, 2023

@nlou9 provided a small reproduction: https://github.com/nlou9/coverage

The problem in that repo is a file templated by Jinja2. The file happens to be valid Python, although it is a JSON data file. It's important that it be valid Python for the bug to happen.

@nhoening I see you use Jinja2 also. What kind of files are you templating?

Others who have had this problem: are you using Jinja2, and are you templating files that are valid Python syntax (even if they are not Python files)?

@nhoening
Copy link

I don't believe we are templating anything but HTML views and emails.
There are some very short email templates, and some are in FLask-Security-Too or maybe even Flask-Login, so I can't be 100% sure that not one of them might be valid Python. But usually they contain a sentence of natural language at least.

@mdantonio
Copy link
Author

We have several jinja2 templates, but I found none that seems to be also valid as python syntax (and all of them are .html, if that matters)

@nedbat
Copy link
Owner

nedbat commented May 11, 2023

@nhoening can you show the output of coverage debug data when lcov fails?

@nhoening
Copy link

@nedbat I see indeed Jinja2 templates in there, although as I said I don't believe any would pass as Python code. But maybe you'll find something there. Code is at https://github.com/FlexMeasures/flexmeasures/ I did this on the up-to-date main branch.

± python3 -m coverage lcov                         
Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/__main__.py", line 8, in <module>
    sys.exit(main())
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/cmdline.py", line 974, in main
    status = CoverageScript().command_line(argv)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/cmdline.py", line 746, in command_line
    total = self.coverage.lcov_report(
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/control.py", line 1257, in lcov_report
    return render_report(self.config.lcov_output, LcovReporter(self), morfs, self._message)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/report.py", line 59, in render_report
    ret = reporter.report(morfs, outfile=outfile)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/lcovreport.py", line 45, in report
    self.get_lcov(fr, analysis, outfile)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/lcovreport.py", line 72, in get_lcov
    line = source_lines[covered-1].encode("utf-8")
IndexError: list index out of range
(fm-3.10) nicolas at pop-os in ~/workspace/seita/flexmeasures on main
± coverage debug data
-- data ------------------------------------------------------
path: /home/nicolas/workspace/seita/flexmeasures/.coverage
has_arcs: False
172 files:
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/__init__.py: 10 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/__init__.py: 53 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/__init__.py: 5 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/implementations.py: 66 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/responses.py: 124 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/routes.py: 15 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/schemas/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/schemas/generic_assets.py: 13 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/schemas/sensor_data.py: 177 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/schemas/sensors.py: 42 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/schemas/users.py: 25 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/utils/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/utils/api_utils.py: 66 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/utils/args_parsing.py: 25 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/utils/decorators.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/utils/deprecation_utils.py: 36 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/utils/migration_utils.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/common/utils/validators.py: 71 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/dev/__init__.py: 7 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/dev/sensors.py: 81 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/play/__init__.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/play/implementations.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/play/routes.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1/__init__.py: 16 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1/routes.py: 7 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1_1/__init__.py: 16 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1_1/routes.py: 17 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1_2/__init__.py: 16 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1_2/routes.py: 21 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1_3/__init__.py: 16 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v1_3/routes.py: 21 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v2_0/__init__.py: 17 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v2_0/routes.py: 39 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v3_0/__init__.py: 15 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v3_0/accounts.py: 31 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v3_0/assets.py: 107 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v3_0/health.py: 11 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v3_0/public.py: 14 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v3_0/sensors.py: 141 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/api/v3_0/users.py: 66 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/app.py: 68 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/auth/__init__.py: 20 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/auth/decorators.py: 45 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/auth/error_handling.py: 38 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/auth/policy.py: 75 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/__init__.py: 22 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/data_add.py: 548 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/data_delete.py: 101 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/data_edit.py: 137 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/data_show.py: 205 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/db_ops.py: 45 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/jobs.py: 45 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/monitor.py: 79 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/testing.py: 37 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/cli/utils.py: 14 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/config/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/conftest.py: 524 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/__init__.py: 12 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/config.py: 23 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/__init__.py: 10 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/annotations.py: 85 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/assets.py: 165 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/charts/__init__.py: 4 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/charts/belief_charts.py: 17 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/charts/defaults.py: 149 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/charts/test_chart_defaults.py: 5 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/data_sources.py: 48 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/forecasting/__init__.py: 16 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/forecasting/exceptions.py: 4 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/forecasting/model_spec_factory.py: 161 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/forecasting/model_specs/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/forecasting/model_specs/linear_regression.py: 11 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/forecasting/model_specs/naive.py: 21 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/forecasting/utils.py: 61 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/generic_assets.py: 189 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/legacy_migration_utils.py: 30 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/markets.py: 100 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/parsing_utils.py: 19 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/planning/__init__.py: 59 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/planning/battery.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/planning/charging_station.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/planning/exceptions.py: 10 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/planning/linear_optimization.py: 184 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/planning/storage.py: 208 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/planning/utils.py: 149 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/reporting/__init__.py: 65 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/reporting/pandas_reporter.py: 53 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/task_runs.py: 12 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/time_series.py: 373 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/user.py: 151 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/validation_utils.py: 21 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/models/weather.py: 112 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/analytics.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/annotations.py: 18 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/data_sources.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/generic_assets.py: 44 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/portfolio.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/sensors.py: 32 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/queries/utils.py: 90 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/__init__.py: 5 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/account.py: 28 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/assets.py: 86 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/generic_assets.py: 86 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/reporting/__init__.py: 28 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/reporting/pandas_reporter.py: 46 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/scheduling/__init__.py: 8 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/scheduling/storage.py: 61 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/sensors.py: 33 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/sources.py: 11 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/times.py: 39 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/units.py: 21 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/users.py: 20 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/schemas/utils.py: 24 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/accounts.py: 22 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/annotations.py: 12 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/asset_grouping.py: 48 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/data_sources.py: 35 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/forecasting.py: 124 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/resources.py: 124 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/scheduling.py: 136 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/sensors.py: 8 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/time_series.py: 98 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/users.py: 101 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/services/utils.py: 55 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/transactional.py: 20 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/data/utils.py: 60 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/templates/security/email/reset_instructions.html: 20 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/templates/security/email/reset_instructions.txt: 18 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/templates/security/email/reset_notice.html: 15 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/templates/security/email/reset_notice.txt: 12 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/__init__.py: 89 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/crud/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/crud/accounts.py: 23 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/crud/api_wrapper.py: 59 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/crud/assets.py: 222 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/crud/users.py: 105 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/error_handlers.py: 63 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/admin/login_user.html: 83 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/base.html: 386 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/crud/asset.html: 171 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/crud/asset_new.html: 96 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/crud/assets.html: 103 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/crud/user.html: 99 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/crud/users.html: 109 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/defaults.jinja: 90 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/error.html: 59 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/views/control.html: 81 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/templates/views/new_dashboard.html: 235 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/utils/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/utils/chart_defaults.py: 6 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/utils/view_utils.py: 119 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/views/__init__.py: 7 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/views/control.py: 12 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/views/logged_in_user.py: 8 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/views/new_dashboard.py: 34 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/ui/views/sensors.py: 31 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/__init__.py: 1 line
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/app_utils.py: 47 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/calculations.py: 32 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/coding_utils.py: 57 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/config_defaults.py: 132 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/config_utils.py: 53 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/entity_address_utils.py: 186 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/error_utils.py: 53 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/flexmeasures_inflection.py: 22 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/geo_utils.py: 18 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/grid_cells.py: 0 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/plugin_utils.py: 21 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/time_utils.py: 135 lines
/home/nicolas/workspace/seita/flexmeasures/flexmeasures/utils/unit_utils.py: 112 lines

@nedbat
Copy link
Owner

nedbat commented May 11, 2023

Thanks everyone for persisting with me. If you can, install this branch of coverage which will show the file that makes lcov fail. The output will include the name and contents of the file. Post your results here if you are comfortable.

pip install git+https://github.com/nedbat/coveragepy@nedbat/debug-1553#egg=coverage==0.0

@nedbat
Copy link
Owner

nedbat commented May 11, 2023

@nhoening for your situation, the file might be flexmeasures/ui/templates/defaults.jinja, which I think could render to just whitespace?

@nhoening
Copy link

nhoening commented May 11, 2023

Successfully installed coverage-7.2.6a0.dev1
± python3 -m coverage lcov                                                                  
Failure processing '/home/nicolas/workspace/seita/flexmeasures/flexmeasures/templates/security/email/reset_instructions.txt':
================================================================================
{{ _fsdomain('You can now choose a new FlexMeasures password.') }}

{{ _fsdomain('Click the link below to reset your password:') }}

{{ reset_link }}

================================================================================
Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/__main__.py", line 8, in <module>
    sys.exit(main())
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/cmdline.py", line 973, in main
    status = CoverageScript().command_line(argv)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/cmdline.py", line 746, in command_line
    total = self.coverage.lcov_report(
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/control.py", line 1257, in lcov_report
    return render_report(self.config.lcov_output, LcovReporter(self), morfs, self._message)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/report.py", line 59, in render_report
    ret = reporter.report(morfs, outfile=outfile)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/lcovreport.py", line 44, in report
    self.get_lcov(fr, analysis, outfile)
  File "/home/nicolas/envs/fm-3.10/lib/python3.10/site-packages/coverage/lcovreport.py", line 72, in get_lcov
    line = source_lines[covered-1].encode("utf-8")
IndexError: list index out of range

(sorry, first edit was wrong branch)

@nedbat
Copy link
Owner

nedbat commented May 11, 2023

Thanks! That Jinja template is syntactically correct Python which can be compiled:

{{ _fsdomain('You can now choose a new FlexMeasures password.') }}

{{ _fsdomain('Click the link below to reset your password:') }}

{{ reset_link }}
  1           0 LOAD_NAME                0 (_fsdomain)
              2 LOAD_CONST               0 ('You can now choose a new FlexMeasures password.')
              4 CALL_FUNCTION            1
              6 BUILD_SET                1
              8 BUILD_SET                1
             10 POP_TOP

  3          12 LOAD_NAME                0 (_fsdomain)
             14 LOAD_CONST               1 ('Click the link below to reset your password:')
             16 CALL_FUNCTION            1
             18 BUILD_SET                1
             20 BUILD_SET                1
             22 POP_TOP

  5          24 LOAD_NAME                1 (reset_link)
             26 BUILD_SET                1
             28 BUILD_SET                1
             30 POP_TOP
             32 LOAD_CONST               2 (None)
             34 RETURN_VALUE

(although it couldn't execute for a few reasons...)

@nhoening
Copy link

nhoening commented May 11, 2023

My idea of valid Python is expanding today! Curly braces can denote sets, so it is valid, but it doesn't run:

>>> { 1 }
{1}
>>> type({ 1 })
<class 'set'>
>>> {{ 1 }}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'

It's not a SyntaxError, notably.
Just that a set cannot be part of a set, as all set members would need to be hashable.

@nedbat
Copy link
Owner

nedbat commented May 13, 2023

OK, here is the full story. This code reproduces the problem:

# repro_1553.py

from pathlib import Path
import jinja2

Path("good.j2").write_text("""\
{{ data }}
line2
line3
""")
Path("bad.j2").write_text("""\
This is data: {{ data }}.
line 2
line 3
""")

loader = jinja2.FileSystemLoader(".")
env = jinja2.Environment(loader=loader)
for fname in ["good", "bad"]:
    template = env.get_template(f"{fname}.j2")
    text = template.render(data="DATA")
    print(f"{fname}: {text}")

Here we're making two Jinja templates: one (good.j2) can be compiled but not run as Python code, the other (bad.j2) is syntactically invalid Python.

Install jinja2 and coverage, then run it:

% coverage run repro_1553.py
good: DATA
line2
line3
bad: This is data: DATA.
line 2
line 3

You can look at the data that coverage has collected:

% coverage debug data
-- data ------------------------------------------------------
path: /System/Volumes/Data/root/src/bugs/bug1553/repro/.coverage
has_arcs: False
3 files:
/System/Volumes/Data/root/src/bugs/bug1553/repro/bad.j2: 15 lines
/System/Volumes/Data/root/src/bugs/bug1553/repro/good.j2: 14 lines
/System/Volumes/Data/root/src/bugs/bug1553/repro/repro_1553.py: 10 lines

Both bad.j2 and good.j2 are in the list, but with more lines that are in the files.

This is because when Jinja2 renders a template, it compiles it to a Python file, then runs the Python file. But when it runs it, it tells Python that the file name is the original template file name. So the Python code runs, but Python thinks the file name is "bad.j2" for example.

All of the reporting functions do something wrong with this data. coverage lcov does the worst:

% coverage lcov
Traceback (most recent call last):
  File "/System/Volumes/Data/root/src/bugs/bug1553/repro/venv/bin/coverage", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/System/Volumes/Data/root/src/bugs/bug1553/repro/venv/lib/python3.11/site-packages/coverage/cmdline.py", line 974, in main
    status = CoverageScript().command_line(argv)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/System/Volumes/Data/root/src/bugs/bug1553/repro/venv/lib/python3.11/site-packages/coverage/cmdline.py", line 746, in command_line
    total = self.coverage.lcov_report(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/System/Volumes/Data/root/src/bugs/bug1553/repro/venv/lib/python3.11/site-packages/coverage/control.py", line 1257, in lcov_report
    return render_report(self.config.lcov_output, LcovReporter(self), morfs, self._message)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/System/Volumes/Data/root/src/bugs/bug1553/repro/venv/lib/python3.11/site-packages/coverage/report.py", line 59, in render_report
    ret = reporter.report(morfs, outfile=outfile)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/System/Volumes/Data/root/src/bugs/bug1553/repro/venv/lib/python3.11/site-packages/coverage/lcovreport.py", line 45, in report
    self.get_lcov(fr, analysis, outfile)
  File "/System/Volumes/Data/root/src/bugs/bug1553/repro/venv/lib/python3.11/site-packages/coverage/lcovreport.py", line 72, in get_lcov
    line = source_lines[covered-1].encode("utf-8")
           ~~~~~~~~~~~~^^^^^^^^^^^
IndexError: list index out of range

This happens because the lcov format records a hash of each source line. To do this, we try to read the nth line from the source file. So we try to grab line 4 from good.j2, but there is no line 4, causing the IndexError.

But other reporting functions also do strange things. report, xml, and html all think the file has three lines, and only lines 1 and 2 were run:

% coverage report -m
Name            Stmts   Miss  Cover   Missing
---------------------------------------------
good.j2             3      1    67%   3
repro_1553.py      10      0   100%
---------------------------------------------
TOTAL              13      1    92%

All the reporting functions skip bad.j2 because it can't be parsed as Python code. Because good.j2 can be parsed, it causes the Jinja/Python confusion that leads to incorrect reporting.

The JSON report records line numbers for good.j2 that were run in the Python code, but don't exist in the good.j2 file:

{
  "files": {
    "good.j2": {
      "executed_lines": [ 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16 ],
      "summary": {
        "covered_lines": 2,
        "num_statements": 3,
        "percent_covered": 66.66666666666667,
        "percent_covered_display": "67",
        "missing_lines": 1,
        "excluded_lines": 0
      },
      "missing_lines": [ 3 ],
      "excluded_lines": []
    },
    "repro_1553.py": {
      "executed_lines": [ 3, 4, 6, 11, 17, 18, 19, 20, 21, 22 ],
      "summary": {
        "covered_lines": 10,
        "num_statements": 10,
        "percent_covered": 100,
        "percent_covered_display": "100",
        "missing_lines": 0,
        "excluded_lines": 0
      },
      "missing_lines": [],
      "excluded_lines": []
    }
  }
}

(Notice that good.j2 says num_statements is 3, but has 14 executed lines.)

So, what to do? There are a few options:

  1. Coverage.py can make the lcov report a bit more defensive, so that it doesn't crash. The file will still have nonsense results from Jinja-templated files, but so do all the other reports.

  2. Users can omit their template files by file pattern: [run] omit = **/*.html or whatever.

  3. I could write a plugin that would detect Jinja-templated files and exclude them from measurement. This wouldn't be hard, but I think needs some slight tweaks to the plugin support in coverage.py.

@nhoening
Copy link

Certainly 2) is a good idea for us users.

Maybe the docs can help us, by linking the error message to an explanation and possible fix. Hopefully that would also in time be found by searching the web for the error message.

@nedbat
Copy link
Owner

nedbat commented May 14, 2023

Option 1 (prevent the IndexError, and have the lcov report just as wrong as the other kinds of reports) is implemented in commit 610a56f. A new issue (#1623) is about Jinja templates appearing in reports.

@nedbat nedbat closed this as completed May 14, 2023
@nedbat nedbat added the fixed label May 14, 2023
nhoening added a commit to FlexMeasures/flexmeasures that referenced this issue May 19, 2023
…676)

* docs: improve developer tutorial on how to run tests, incl. coverage

* add a docker command for running a database to test against

* exclude jinja templates from coverage, see nedbat/coveragepy#1553

* use the new make command from PR #672

* correct syntax type for docker call

* add dollar signs

* small text improvements
@nedbat
Copy link
Owner

nedbat commented May 24, 2023

This is now released as part of coverage 7.2.6.

renovate bot referenced this issue in allenporter/flux-local May 25, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [coverage](https://github.com/nedbat/coveragepy) | `==7.2.5` ->
`==7.2.6` |
[![age](https://badges.renovateapi.com/packages/pypi/coverage/7.2.6/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/pypi/coverage/7.2.6/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/pypi/coverage/7.2.6/compatibility-slim/7.2.5)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/pypi/coverage/7.2.6/confidence-slim/7.2.5)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>nedbat/coveragepy</summary>

###
[`v7.2.6`](https://github.com/nedbat/coveragepy/blob/HEAD/CHANGES.rst#Version-726--2023-05-23)

[Compare
Source](https://github.com/nedbat/coveragepy/compare/7.2.5...7.2.6)

- Fix: the `lcov` command could raise an IndexError exception if a file
is
translated to Python but then executed under its own name. Jinja2 does
this
    when rendering templates.  Fixes `issue 1553`\_.

- Python 3.12 beta 1 now inlines comprehensions. Previously they were
compiled
as invisible functions and coverage.py would warn you if they weren't
    completely executed.  This no longer happens under Python 3.12.

- Fix: the `coverage debug sys` command includes some environment
variables
in its output. This could have included sensitive data. Those values are
    now hidden with asterisks, closing `issue 1628`\_.

.. \_issue
1553:[https://github.com/nedbat/coveragepy/issues/1553](https://github.com/nedbat/coveragepy/issues/1553)3
.. \_issue
1628[https://github.com/nedbat/coveragepy/issues/1628](https://github.com/nedbat/coveragepy/issues/1628)28

.. \_changes\_7-2-5:

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://app.renovatebot.com/dashboard#github/allenporter/flux-local).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS45OC40IiwidXBkYXRlZEluVmVyIjoiMzUuOTguNCIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@mdantonio
Copy link
Author

Just upgraded and I confirm that we are no longer experiencing this issue, thank you! 🙏

RobertCraigie referenced this issue in RobertCraigie/prisma-client-py Jul 21, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [coverage](https://github.com/nedbat/coveragepy) | `==7.2.5` ->
`==7.2.7` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/coverage/7.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/coverage/7.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/coverage/7.2.5/7.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/coverage/7.2.5/7.2.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [mkdocs-material](https://github.com/squidfunk/mkdocs-material) |
`==9.1.9` -> `==9.1.19` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/mkdocs-material/9.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/mkdocs-material/9.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/mkdocs-material/9.1.9/9.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/mkdocs-material/9.1.9/9.1.19?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [mock](http://mock.readthedocs.org/en/latest/)
([source](https://github.com/testing-cabal/mock)) | `==5.0.2` ->
`==5.1.0` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/mock/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/mock/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/mock/5.0.2/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/mock/5.0.2/5.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [pyright](https://github.com/RobertCraigie/pyright-python) |
`==1.1.306` -> `==1.1.317` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/pyright/1.1.317?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/pyright/1.1.317?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/pyright/1.1.306/1.1.317?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pyright/1.1.306/1.1.317?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [pytest](https://docs.pytest.org/en/latest/)
([source](https://github.com/pytest-dev/pytest),
[changelog](https://docs.pytest.org/en/stable/changelog.html)) |
`==7.3.1` -> `==7.4.0` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/pytest/7.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/pytest/7.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/pytest/7.3.1/7.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pytest/7.3.1/7.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio)
([changelog](https://pytest-asyncio.readthedocs.io/en/latest/reference/changelog.html))
| `==0.21.0` -> `==0.21.1` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/pytest-asyncio/0.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/pytest-asyncio/0.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/pytest-asyncio/0.21.0/0.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pytest-asyncio/0.21.0/0.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [pytest-mock](https://github.com/pytest-dev/pytest-mock)
([changelog](https://pytest-mock.readthedocs.io/en/latest/changelog.html))
| `==3.10.0` -> `==3.11.1` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/pytest-mock/3.11.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/pytest-mock/3.11.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/pytest-mock/3.10.0/3.11.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pytest-mock/3.10.0/3.11.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>nedbat/coveragepy (coverage)</summary>

###
[`v7.2.7`](https://github.com/nedbat/coveragepy/blob/HEAD/CHANGES.rst#Version-727--2023-05-29)

[Compare
Source](https://github.com/nedbat/coveragepy/compare/7.2.6...7.2.7)

- Fix: reverted a `change from 6.4.3 <pull 1347_>`\_ that helped Cython,
but
also increased the size of data files when using dynamic contexts, as
described in the now-fixed `issue 1586`*. The problem is now avoided due
to a
recent change (`issue 1538`*). Thanks to `Anders Kaseorg <pull 1629_>`\_
and David Szotten for persisting with problem reports and detailed
diagnoses.

-   Wheels are now provided for CPython 3.12.

.. \_issue
1586:[https://github.com/nedbat/coveragepy/issues/1586](https://github.com/nedbat/coveragepy/issues/1586)6
.. \_pull
1629[https://github.com/nedbat/coveragepy/pull/1629](https://github.com/nedbat/coveragepy/pull/1629)29

.. \_changes\_7-2-6:

###
[`v7.2.6`](https://github.com/nedbat/coveragepy/blob/HEAD/CHANGES.rst#Version-726--2023-05-23)

[Compare
Source](https://github.com/nedbat/coveragepy/compare/7.2.5...7.2.6)

- Fix: the `lcov` command could raise an IndexError exception if a file
is
translated to Python but then executed under its own name. Jinja2 does
this
    when rendering templates.  Fixes `issue 1553`\_.

- Python 3.12 beta 1 now inlines comprehensions. Previously they were
compiled
as invisible functions and coverage.py would warn you if they weren't
    completely executed.  This no longer happens under Python 3.12.

- Fix: the `coverage debug sys` command includes some environment
variables
in its output. This could have included sensitive data. Those values are
    now hidden with asterisks, closing `issue 1628`\_.

.. \_issue
1553:[https://github.com/nedbat/coveragepy/issues/1553](https://github.com/nedbat/coveragepy/issues/1553)3
.. \_issue
1628[https://github.com/nedbat/coveragepy/issues/1628](https://github.com/nedbat/coveragepy/issues/1628)28

.. \_changes\_7-2-5:

</details>

<details>
<summary>squidfunk/mkdocs-material (mkdocs-material)</summary>

###
[`v9.1.19`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.19):
mkdocs-material-9.1.19

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.18...9.1.19)

-   Added support for MkDocs 1.5+
- Fixed
[#&#8203;5699](https://github.com/squidfunk/mkdocs-material/issues/5699):
Improve error reporting in social plugin

###
[`v9.1.18`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.18):
mkdocs-material-9.1.18

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.17...9.1.18)

-   Updated Danish translations
-   Added support for installing user requirements in Docker image
- Fixed
[#&#8203;5655](https://github.com/squidfunk/mkdocs-material/issues/5655):
Search separator with lookbehind breaks highlighting

###
[`v9.1.17`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.17):
mkdocs-material-9.1.17

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.16...9.1.17)

- Fixed
[#&#8203;5633](https://github.com/squidfunk/mkdocs-material/issues/5633):
Code annotations with nested lists incorrectly mounted
- Fixed
[#&#8203;5628](https://github.com/squidfunk/mkdocs-material/issues/5628):
Regression in new social plugin configuration scheme

###
[`v9.1.16`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.16):
mkdocs-material-9.1.16

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.15...9.1.16)

-   Updated Indonesian translations
-   Ensure scroll bar follows color scheme of operating system

###
[`v9.1.15`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.15):
mkdocs-material-9.1.15

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.14...9.1.15)

- Fixed
[#&#8203;5566](https://github.com/squidfunk/mkdocs-material/issues/5566):
Indicate color scheme to operating system
- Fixed
[#&#8203;5565](https://github.com/squidfunk/mkdocs-material/issues/5565):
Update `Dockerfile` to latest version of base image
- Fixed
[#&#8203;5554](https://github.com/squidfunk/mkdocs-material/issues/5554):
Add additional version tags (`9`, `9.1`) to Docker image
- Fixed
[#&#8203;5536](https://github.com/squidfunk/mkdocs-material/issues/5536):
Strip tags of ARIA labels in table of contents

###
[`v9.1.14`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.14):
mkdocs-material-9.1.14

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.13...9.1.14)

-   Updated Armenian and Greek translations

###
[`v9.1.13`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.13):
mkdocs-material-9.1.13

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.12...9.1.13)

- Fixed
[#&#8203;5517](https://github.com/squidfunk/mkdocs-material/issues/5517):
Social plugin crashes for some fonts (e.g. Open Sans)

###
[`v9.1.12`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.12):
mkdocs-material-9.1.12

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.11...9.1.12)

-   Updated Bengali (Bangla) translations
- Fixed
[#&#8203;5503](https://github.com/squidfunk/mkdocs-material/issues/5503):
Docker image publish errors on uppercase characters
- Fixed
[#&#8203;5407](https://github.com/squidfunk/mkdocs-material/issues/5407):
Auto-pause media when in hidden content tabs

###
[`v9.1.11`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.11):
mkdocs-material-9.1.11

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.10...9.1.11)

- Fixed
[#&#8203;5487](https://github.com/squidfunk/mkdocs-material/issues/5487):
Social plugin crashes without options (9.1.10 regression)

###
[`v9.1.10`](https://github.com/squidfunk/mkdocs-material/releases/tag/9.1.10):
mkdocs-material-9.1.10

[Compare
Source](https://github.com/squidfunk/mkdocs-material/compare/9.1.9...9.1.10)

-   Added `cards_layout_options` setting for social cards
-   Deprecated `cards_color` and `cards_font` setting for social cards

</details>

<details>
<summary>testing-cabal/mock (mock)</summary>

###
[`v5.1.0`](https://github.com/testing-cabal/mock/blob/HEAD/CHANGELOG.rst#510)

[Compare
Source](https://github.com/testing-cabal/mock/compare/5.0.2...5.1.0)

- bpo-44185: :func:`unittest.mock.mock_open` will call the :func:`close`
    method of the file handle mock when it is exiting from the context
    manager. Patch by Samet Yaslan.

- [gh-94924](https://github.com/testing-cabal/mock/issues/94924):
:func:`unittest.mock.create_autospec` now properly returns
coroutine functions compatible with :func:`inspect.iscoroutinefunction`

- bpo-17013: Add `ThreadingMock` to :mod:`unittest.mock` that can be
used
    to create Mock objects that can wait until they are called. Patch by
    Karthikeyan Singaravelan and Mario Corchero.

- bpo-41768: :mod:`unittest.mock` speccing no longer calls class
properties.
    Patch by Melanie Witt.

</details>

<details>
<summary>RobertCraigie/pyright-python (pyright)</summary>

###
[`v1.1.317`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.316...v1.1.317)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.316...v1.1.317)

###
[`v1.1.316`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.315...v1.1.316)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.315...v1.1.316)

###
[`v1.1.315`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.314...v1.1.315)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.314...v1.1.315)

###
[`v1.1.314`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.313...v1.1.314)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.313...v1.1.314)

###
[`v1.1.313`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.312...v1.1.313)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.312...v1.1.313)

###
[`v1.1.312`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.311...v1.1.312)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.311...v1.1.312)

###
[`v1.1.311`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.310...v1.1.311)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.310...v1.1.311)

###
[`v1.1.310`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.309...v1.1.310)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.309...v1.1.310)

###
[`v1.1.309`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.308...v1.1.309)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.308...v1.1.309)

###
[`v1.1.308`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.307...v1.1.308)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.307...v1.1.308)

###
[`v1.1.307`](https://github.com/RobertCraigie/pyright-python/compare/v1.1.306...v1.1.307)

[Compare
Source](https://github.com/RobertCraigie/pyright-python/compare/v1.1.306...v1.1.307)

</details>

<details>
<summary>pytest-dev/pytest (pytest)</summary>

###
[`v7.4.0`](https://github.com/pytest-dev/pytest/releases/tag/7.4.0)

[Compare
Source](https://github.com/pytest-dev/pytest/compare/7.3.2...7.4.0)

# pytest 7.4.0 (2023-06-23)

## Features

- [#&#8203;10901](https://github.com/pytest-dev/pytest/issues/10901):
Added `ExceptionInfo.from_exception()
<pytest.ExceptionInfo.from_exception>`{.interpreted-text role="func"}, a
simpler way to create an `~pytest.ExceptionInfo`{.interpreted-text
role="class"} from an exception.
This can replace `ExceptionInfo.from_exc_info()
<pytest.ExceptionInfo.from_exc_info()>`{.interpreted-text role="func"}
for most uses.

## Improvements

- [#&#8203;10872](https://github.com/pytest-dev/pytest/issues/10872):
Update test log report annotation to named tuple and fixed inconsistency
in docs for `pytest_report_teststatus`{.interpreted-text role="hook"}
hook.

- [#&#8203;10907](https://github.com/pytest-dev/pytest/issues/10907):
When an exception traceback to be displayed is completely filtered out
(by mechanisms such as `__tracebackhide__`, internal frames, and
similar), now only the exception string and the following message are
shown:

"All traceback entries are hidden. Pass \[--full-trace]{.title-ref} to
see hidden and internal frames.".

Previously, the last frame of the traceback was shown, even though it
was hidden.

- [#&#8203;10940](https://github.com/pytest-dev/pytest/issues/10940):
Improved verbose output (`-vv`) of `skip` and `xfail` reasons by
performing text wrapping while leaving a clear margin for progress
output.

    Added `TerminalReporter.wrap_write()` as a helper for that.

- [#&#8203;10991](https://github.com/pytest-dev/pytest/issues/10991):
Added handling of `%f` directive to print microseconds in log format
options, such as `log-date-format`.

- [#&#8203;11005](https://github.com/pytest-dev/pytest/issues/11005):
Added the underlying exception to the cache provider's path creation and
write warning messages.

- [#&#8203;11013](https://github.com/pytest-dev/pytest/issues/11013):
Added warning when `testpaths`{.interpreted-text role="confval"} is set,
but paths are not found by glob. In this case, pytest will fall back to
searching from the current directory.

- [#&#8203;11043](https://github.com/pytest-dev/pytest/issues/11043):
When \[--confcutdir]{.title-ref} is not specified, and there is no
config file present, the conftest cutoff directory
(\[--confcutdir]{.title-ref}) is now set to the `rootdir
<rootdir>`{.interpreted-text role="ref"}.
Previously in such cases, \[conftest.py]{.title-ref} files would be
probed all the way to the root directory of the filesystem.
If you are badly affected by this change, consider adding an empty
config file to your desired cutoff directory, or explicitly set
\[--confcutdir]{.title-ref}.

- [#&#8203;11081](https://github.com/pytest-dev/pytest/issues/11081):
The `norecursedirs`{.interpreted-text role="confval"} check is now
performed in a `pytest_ignore_collect`{.interpreted-text role="hook"}
implementation, so plugins can affect it.

If after updating to this version you see that your
\[norecursedirs]{.title-ref} setting is not being respected,
it means that a conftest or a plugin you use has a bad
\[pytest_ignore_collect]{.title-ref} implementation.
Most likely, your hook returns \[False]{.title-ref} for paths it does
not want to ignore,
which ends the processing and doesn't allow other plugins, including
pytest itself, to ignore the path.
The fix is to return \[None]{.title-ref} instead of \[False]{.title-ref}
for paths your hook doesn't want to ignore.

- [#&#8203;8711](https://github.com/pytest-dev/pytest/issues/8711):
`caplog.set_level()
<pytest.LogCaptureFixture.set_level>`{.interpreted-text role="func"} and
`caplog.at_level()
<pytest.LogCaptureFixture.at_level>`{.interpreted-text role="func"}
will temporarily enable the requested `level` if `level` was disabled
globally via
    `logging.disable(LEVEL)`.

## Bug Fixes

- [#&#8203;10831](https://github.com/pytest-dev/pytest/issues/10831):
Terminal Reporting: Fixed bug when running in `--tb=line` mode where
`pytest.fail(pytrace=False)` tests report `None`.
- [#&#8203;11068](https://github.com/pytest-dev/pytest/issues/11068):
Fixed the `--last-failed` whole-file skipping functionality ("skipped N
files") for `non-python test files <non-python tests>`{.interpreted-text
role="ref"}.
- [#&#8203;11104](https://github.com/pytest-dev/pytest/issues/11104):
Fixed a regression in pytest 7.3.2 which caused to
`testpaths`{.interpreted-text role="confval"} to be considered for
loading initial conftests,
even when it was not utilized (e.g. when explicit paths were given on
the command line).
    Now the `testpaths` are only considered when they are in use.
- [#&#8203;1904](https://github.com/pytest-dev/pytest/issues/1904):
Fixed traceback entries hidden with `__tracebackhide__ = True` still
being shown for chained exceptions (parts after "... the above exception
..." message).
- [#&#8203;7781](https://github.com/pytest-dev/pytest/issues/7781):
Fix writing non-encodable text to log file when using `--debug`.

## Improved Documentation

- [#&#8203;9146](https://github.com/pytest-dev/pytest/issues/9146):
Improved documentation for `caplog.set_level()
<pytest.LogCaptureFixture.set_level>`{.interpreted-text role="func"}.

## Trivial/Internal Changes

- [#&#8203;11031](https://github.com/pytest-dev/pytest/issues/11031):
Enhanced the CLI flag for `-c` to now include `--config-file` to make it
clear that this flag applies to the usage of a custom config file.

###
[`v7.3.2`](https://github.com/pytest-dev/pytest/releases/tag/7.3.2)

[Compare
Source](https://github.com/pytest-dev/pytest/compare/7.3.1...7.3.2)

# pytest 7.3.2 (2023-06-10)

## Bug Fixes

- [#&#8203;10169](https://github.com/pytest-dev/pytest/issues/10169):
Fix bug where very long option names could cause pytest to break with
`OSError: [Errno 36] File name too long` on some systems.
- [#&#8203;10894](https://github.com/pytest-dev/pytest/issues/10894):
Support for Python 3.12 (beta at the time of writing).
- [#&#8203;10987](https://github.com/pytest-dev/pytest/issues/10987):
`testpaths`{.interpreted-text role="confval"} is now honored to load
root `conftests`.
- [#&#8203;10999](https://github.com/pytest-dev/pytest/issues/10999):
The \[monkeypatch]{.title-ref}
\[setitem]{.title-ref}/\[delitem]{.title-ref} type annotations now allow
\[TypedDict]{.title-ref} arguments.
- [#&#8203;11028](https://github.com/pytest-dev/pytest/issues/11028):
Fixed bug in assertion rewriting where a variable assigned with the
walrus operator could not be used later in a function call.
- [#&#8203;11054](https://github.com/pytest-dev/pytest/issues/11054):
Fixed `--last-failed`'s "(skipped N files)" functionality for files
inside of packages (directories with \[\__init\_\_.py]{.title-ref}
files).

</details>

<details>
<summary>pytest-dev/pytest-asyncio (pytest-asyncio)</summary>

###
[`v0.21.1`](https://github.com/pytest-dev/pytest-asyncio/releases/tag/v0.21.1):
pytest-asyncio 0.21.1

[Compare
Source](https://github.com/pytest-dev/pytest-asyncio/compare/v0.21.0...v0.21.1)

### 0.21.1 (2023-07-12)

- Output a proper error message when an invalid `asyncio_mode` is
selected.
- Extend warning message about unclosed event loops with additional
possible cause.

[#&#8203;531](https://github.com/pytest-dev/pytest-asyncio/issues/531)
- Previously, some tests reported "skipped" or "xfailed" as a result.
Now all tests report a "success" result.

</details>

<details>
<summary>pytest-dev/pytest-mock (pytest-mock)</summary>

###
[`v3.11.1`](https://github.com/pytest-dev/pytest-mock/blob/HEAD/CHANGELOG.rst#3111-2023-06-15)

[Compare
Source](https://github.com/pytest-dev/pytest-mock/compare/v3.11.0...v3.11.1)

(This release source code is identical to `3.11.0` except a small
internal fix to deployment/CI)

-   Fixed introspection for failed `assert_has_calls` (`#365`\_).

- Updated type annotations for `mocker.patch` and `mocker.spy`
(`#364`\_).

..
\_#365:[https://github.com/pytest-dev/pytest-mock/pull/365](https://github.com/pytest-dev/pytest-mock/pull/365)5
..
\_#364[https://github.com/pytest-dev/pytest-mock/pull/364](https://github.com/pytest-dev/pytest-mock/pull/364)64

###
[`v3.11.0`](https://github.com/pytest-dev/pytest-mock/blob/HEAD/CHANGELOG.rst#3110-2023-06-15)

[Compare
Source](https://github.com/pytest-dev/pytest-mock/compare/v3.10.0...v3.11.0)

-   Fixed introspection for failed `assert_has_calls` (`#365`\_).

- Updated type annotations for `mocker.patch` and `mocker.spy`
(`#364`\_).

..
\_#365:[https://github.com/pytest-dev/pytest-mock/pull/365](https://github.com/pytest-dev/pytest-mock/pull/365)5
..
\_#364[https://github.com/pytest-dev/pytest-mock/pull/364](https://github.com/pytest-dev/pytest-mock/pull/364)64

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/RobertCraigie/prisma-client-py).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS43NC4wIiwidXBkYXRlZEluVmVyIjoiMzYuOC4xMSIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Craigie <robert@craigie.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed
Projects
None yet
Development

No branches or pull requests

8 participants