Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 31278f2

Browse files
chore: Remove requirement for pytest (#273)
* chore: Remove requirement for pytest pytest was required only by the `PythonStandardRunner`, and only in the `strict_mode`. No one uses that. At first it was develop because we were concerned that users would be picky by us running pytest with `subprocess.run`, so `strict_mode` was an alternative. Since then people are starting to use ATS and that hasn't been an issue. Plus with custom runners we can solve this problem without the complications of requiring pytest. And there's a possibility (although I think it's very unlikely) that importing pytest from the CLI might cause some of the issues we were seeing when running tests from it in ATS. Who knows. In any case, removing pytest and all code associated with it. * remove _wait_pytest from the PythonStandardRunner
1 parent 40483bb commit 31278f2

File tree

8 files changed

+41
-350
lines changed

8 files changed

+41
-350
lines changed

.github/workflows/push_flow.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ jobs:
6262
python -m pip install --upgrade pip
6363
pip install -r requirements.txt
6464
python setup.py develop
65+
pip install -r tests/requirements.txt
6566
- name: Test with pytest
6667
run: |
6768
pytest --cov
@@ -96,7 +97,7 @@ jobs:
9697
- uses: actions/setup-python@v3
9798
- name: Install CLI
9899
run: |
99-
pip install -r requirements.txt
100+
pip install -r requirements.txt -r tests/requirements.txt
100101
pip install codecov-cli
101102
- name: Label Analysis
102103
run: |
Lines changed: 3 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
import logging
22
import random
33
import subprocess
4-
from contextlib import redirect_stdout
5-
from io import StringIO, TextIOWrapper
6-
from multiprocessing import Process, Queue, get_context
7-
from os import getcwd
8-
from queue import Empty
94
from subprocess import CalledProcessError
10-
from sys import path, stdout
5+
from sys import stdout
116
from typing import List, Optional
127

138
import click
14-
import pytest
159

1610
from codecov_cli.runners.types import (
1711
LabelAnalysisRequestResult,
@@ -43,58 +37,6 @@ def coverage_root(self) -> str:
4337
"""
4438
return self.get("coverage_root", "./")
4539

46-
@property
47-
def strict_mode(self) -> bool:
48-
"""
49-
Run pytest from within Python instead of using subprocess.run
50-
This is potentailly safer than using subprocess.run because it guarantees better that
51-
the program running is indeed pytest.
52-
But it might not work everytime due to import issues related to Python caching modules.
53-
"""
54-
return self.get("strict_mode", False)
55-
56-
57-
def _include_curr_dir(method):
58-
"""
59-
Account for the difference 'pytest' vs 'python -m pytest'
60-
https://docs.pytest.org/en/7.1.x/how-to/usage.html#calling-pytest-through-python-m-pytest
61-
Used only in strict_mode
62-
"""
63-
64-
def call_method(self, *args, **kwargs):
65-
curr_dir = getcwd()
66-
path.append(curr_dir)
67-
68-
result = method(self, *args, **kwargs)
69-
70-
path.remove(curr_dir)
71-
return result
72-
73-
return call_method
74-
75-
76-
def _execute_pytest_subprocess(
77-
pytest_args: List[str],
78-
queue: Queue,
79-
parent_stdout: TextIOWrapper,
80-
capture_output: bool = True,
81-
):
82-
"""Runs pytest from python in a subprocess.
83-
This is because we call it twice in the label-analysis process,
84-
so we might have import errors if calling it directly.
85-
Check the warning: https://docs.pytest.org/en/7.1.x/how-to/usage.html#calling-pytest-from-python-code
86-
87-
Returns the output value and pytest exit code via queue
88-
"""
89-
subproces_stdout = parent_stdout
90-
if capture_output:
91-
subproces_stdout = StringIO()
92-
with redirect_stdout(subproces_stdout):
93-
result = pytest.main(pytest_args)
94-
if capture_output:
95-
queue.put({"output": subproces_stdout.getvalue()})
96-
queue.put({"result": result})
97-
9840

9941
class PythonStandardRunner(LabelAnalysisRunnerInterface):
10042

@@ -106,54 +48,6 @@ def __init__(self, config_params: Optional[dict] = None) -> None:
10648
config_params = {}
10749
self.params = PythonStandardRunnerConfigParams(config_params)
10850

109-
def _wait_pytest(self, pytest_process: Process, queue: Queue):
110-
pytest_process.start()
111-
result = None
112-
output = None
113-
while pytest_process.exitcode == 0 or pytest_process.exitcode == None:
114-
from_queue = None
115-
try:
116-
from_queue = queue.get(timeout=1)
117-
except Empty:
118-
pass
119-
if from_queue and "output" in from_queue:
120-
output = from_queue["output"]
121-
if from_queue and "result" in from_queue:
122-
result = from_queue["result"]
123-
if result is not None:
124-
break
125-
pytest_process.join()
126-
return result, output
127-
128-
@_include_curr_dir
129-
def _execute_pytest_strict(
130-
self, pytest_args: List[str], capture_output: bool = True
131-
) -> str:
132-
"""Handles calling pytest from Python in a subprocess.
133-
Raises Exception if pytest fails
134-
Returns the complete pytest output
135-
"""
136-
ctx = get_context(method="fork")
137-
queue = ctx.Queue(2)
138-
p = ctx.Process(
139-
target=_execute_pytest_subprocess,
140-
args=[pytest_args, queue, stdout, capture_output],
141-
)
142-
result, output = self._wait_pytest(p, queue)
143-
144-
if p.exitcode != 0 or (result != pytest.ExitCode.OK and result != 0):
145-
message = f"Pytest exited with non-zero code {result}."
146-
message += "\nThis is likely not a problem with label-analysis. Check pytest's output and options."
147-
if capture_output:
148-
# If pytest failed but we captured its output the user won't know what's wrong
149-
# So we need to include that in the error message
150-
message += "\nPYTEST OUTPUT:"
151-
message += "\n" + output
152-
else:
153-
message += "\n(you can check pytest options on the logs before the test session start)"
154-
raise click.ClickException(message)
155-
return output
156-
15751
def parse_captured_output_error(self, exp: CalledProcessError) -> str:
15852
result = ""
15953
for out_stream in [exp.stdout, exp.stderr]:
@@ -202,10 +96,7 @@ def collect_tests(self):
20296
),
20397
)
20498

205-
if self.params.strict_mode:
206-
output = self._execute_pytest_strict(options_to_use)
207-
else:
208-
output = self._execute_pytest(options_to_use)
99+
output = self._execute_pytest(options_to_use)
209100
lines = output.split(sep="\n")
210101
test_names = list(line for line in lines if ("::" in line and "test" in line))
211102
return test_names
@@ -254,10 +145,7 @@ def process_labelanalysis_result(self, result: LabelAnalysisRequestResult):
254145
"List of tests executed",
255146
extra=dict(extra_log_attributes=dict(executed_tests=tests_to_run)),
256147
)
257-
if self.params.strict_mode:
258-
output = self._execute_pytest_strict(command_array, capture_output=False)
259-
else:
260-
output = self._execute_pytest(command_array, capture_output=False)
148+
output = self._execute_pytest(command_array, capture_output=False)
261149
logger.info(f"Finished running {len(tests_to_run)} tests successfully")
262150
logger.info(f" pytest options: \"{' '.join(default_options)}\"")
263151
logger.debug(output)

requirements.txt

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,19 @@
22
# This file is autogenerated by pip-compile with Python 3.10
33
# by the following command:
44
#
5-
# pip-compile --output-file=requirements.txt requirements.in setup.py
5+
# pip-compile setup.py
66
#
77
anyio==4.0.0
88
# via httpcore
9-
attrs==21.4.0
10-
# via pytest
119
certifi==2023.7.22
1210
# via
1311
# httpcore
1412
# httpx
1513
# requests
16-
charset-normalizer==3.2.0
14+
charset-normalizer==3.3.0
1715
# via requests
1816
click==8.1.7
1917
# via codecov-cli (setup.py)
20-
coverage[toml]==7.3.1
21-
# via pytest-cov
2218
exceptiongroup==1.1.3
2319
# via anyio
2420
h11==0.14.0
@@ -34,28 +30,6 @@ idna==3.4
3430
# rfc3986
3531
ijson==3.2.3
3632
# via codecov-cli (setup.py)
37-
iniconfig==1.1.1
38-
# via pytest
39-
packaging==21.3
40-
# via pytest
41-
pluggy==1.0.0
42-
# via pytest
43-
py==1.11.0
44-
# via pytest
45-
pyparsing==3.0.9
46-
# via packaging
47-
pytest==7.1.2
48-
# via
49-
# codecov-cli (setup.py)
50-
# pytest-asyncio
51-
# pytest-cov
52-
# pytest-mock
53-
pytest-asyncio==0.21.1
54-
# via -r requirements.in
55-
pytest-cov==4.1.0
56-
# via codecov-cli (setup.py)
57-
pytest-mock==3.11.1
58-
# via -r requirements.in
5933
pyyaml==6.0.1
6034
# via codecov-cli (setup.py)
6135
requests==2.31.0
@@ -71,13 +45,9 @@ sniffio==1.3.0
7145
# anyio
7246
# httpcore
7347
# httpx
74-
tomli==2.0.1
75-
# via
76-
# coverage
77-
# pytest
7848
tree-sitter==0.20.2
7949
# via codecov-cli (setup.py)
80-
urllib3==2.0.4
50+
urllib3==2.0.6
8151
# via
8252
# requests
8353
# responses

setup.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
"click==8.*",
2525
"httpx==0.23.*",
2626
"ijson==3.*",
27-
"pytest==7.*",
28-
"pytest-cov>=3",
2927
"pyyaml==6.*",
3028
"responses==0.21.*",
3129
"smart-open==6.*",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
pytest
2+
pytest-cov
13
pytest-mock
24
pytest-asyncio

tests/requirements.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.10
3+
# by the following command:
4+
#
5+
# pip-compile tests/requirements.in
6+
#
7+
coverage[toml]==7.3.1
8+
# via pytest-cov
9+
exceptiongroup==1.1.3
10+
# via pytest
11+
iniconfig==2.0.0
12+
# via pytest
13+
packaging==23.2
14+
# via pytest
15+
pluggy==1.3.0
16+
# via pytest
17+
pytest==7.4.2
18+
# via
19+
# -r tests/requirements.in
20+
# pytest-asyncio
21+
# pytest-cov
22+
# pytest-mock
23+
pytest-asyncio==0.21.1
24+
# via -r tests/requirements.in
25+
pytest-cov==4.1.0
26+
# via -r tests/requirements.in
27+
pytest-mock==3.11.1
28+
# via -r tests/requirements.in
29+
tomli==2.0.1
30+
# via pytest

0 commit comments

Comments
 (0)