Skip to content

Commit 9e20e9e

Browse files
joke1196sonartech
authored andcommitted
SONARPY-4604 Moved from tox to uv
GitOrigin-RevId: 387df7b0632f99c8e50cc172fc1fb3ea1842bcdb
1 parent 1b58330 commit 9e20e9e

11 files changed

Lines changed: 1690 additions & 217 deletions

File tree

python-frontend/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,12 @@
179179
</configuration>
180180
<executions>
181181
<execution>
182-
<id>tox-runner</id>
182+
<id>serializer-runner</id>
183183
<phase>generate-resources</phase>
184184
<configuration>
185185
<executable>python</executable>
186186
<arguments>
187-
<argument>runners/tox_runner.py</argument>
187+
<argument>runners/serializer_runner.py</argument>
188188
<argument>--skip_tests</argument>
189189
<argument>${skipTests}</argument>
190190
<argument>--fail_fast</argument>

python-frontend/typeshed_serializer/README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,48 @@ To run:
22

33
in `python-frontend/src/main/protobuf` directory, run: ```protoc -I=. --python_out=../../../typeshed_serializer/serializer/proto_out ./symbols.proto```
44

5-
```pip install -r requirements.txt```
5+
```uv sync```
66

7+
## Run the serializer
8+
9+
```bash
10+
uv run python runners/serializer_runner.py
11+
```
12+
13+
## Run the test suite
14+
15+
```bash
16+
uv run python -m pytest tests/
17+
```
718

819
## Rebuild only custom symbols
920

1021
```bash
11-
tox -e selective-serialize -- custom
22+
uv run python -m utils.folder_manager custom && uv run python -m serializer.typeshed_serializer custom
1223
```
1324

1425
## Run a custom test
1526

1627
```bash
17-
tox -e py314 -- tests/runners/test_tox_runner.py
28+
uv run python -m pytest tests/runners/test_serializer_runner.py
1829
```
1930
## Run one specific unit test
2031

2132
```bash
22-
tox -e py314 -- tests/runners/test_tox_runner.py::ToxRunnerTest::test_dry_run_unchanged_checksums -v
33+
uv run python -m pytest tests/runners/test_serializer_runner.py::RunnerTest::test_dry_run_unchanged_checksums -v
2334
```
2435

25-
## Dry run of tox_runner
36+
## Dry run of runner
2637

27-
- Use python, not tox.
28-
- Will show which calls to the `tox` module would have been triggered, depending on the checksums and file-system state.
38+
- Will show which calls would have been triggered, depending on the checksums and file-system state.
2939
- Will not perform any change.
3040

3141
```bash
32-
python runners/tox_runner.py --dry_run true
42+
uv run python runners/serializer_runner.py --dry_run true
3343
```
3444

3545
Can also be run in fail fast mode, to reflect the checksum validation used by the QA workflow
3646

3747
```bash
38-
python runners/tox_runner.py --dry_run true --fail_fast true
48+
uv run python runners/serializer_runner.py --dry_run true --fail_fast true
3949
```

python-frontend/typeshed_serializer/docker/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ RUN apt-get update && \
88
# This command will print the version of protoc, confirming its installation
99
RUN protoc --version
1010

11-
# Install tox
12-
RUN pip install --no-cache-dir tox
11+
# Install uv
12+
RUN pip install --no-cache-dir uv
1313

1414
# Add typeshed serializer to the image container
1515
COPY --chmod=777 ./docker/cmd.sh /sonar-python/cmd.sh
1616

1717
# Make run script executable
1818
RUN chmod +x /sonar-python/cmd.sh
1919

20-
# Run runners/tox_runner.py when the container launches
20+
# Run runners/runner.py when the container launches
2121
CMD ["/sonar-python/cmd.sh"]

python-frontend/typeshed_serializer/docker/cmd.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ cd /sonar-python/python-frontend/src/main/protobuf
77
protoc -I=. --python_out=../../../typeshed_serializer/serializer/proto_out ./symbols.proto
88

99
cd /sonar-python/python-frontend/typeshed_serializer
10-
# Recreate the env to make sure that latest dependencies will be downloaded
11-
tox --recreate --notest
12-
python runners/tox_runner.py --skip_tests=false
10+
# Sync dependencies from uv.lock
11+
uv sync
12+
uv run python runners/serializer_runner.py --skip_tests=false
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#
2+
# SonarQube Python Plugin
3+
# Copyright (C) SonarSource Sàrl
4+
# mailto:info AT sonarsource DOT com
5+
#
6+
# You can redistribute and/or modify this program under the terms of
7+
# the Sonar Source-Available License Version 1, as published by SonarSource Sàrl.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
# See the Sonar Source-Available License for more details.
13+
#
14+
# You should have received a copy of the Sonar Source-Available License
15+
# along with this program; if not, see https://sonarsource.com/license/ssal/
16+
#
17+
18+
[project]
19+
name = "typeshed-serializer"
20+
version = "0.1.0"
21+
requires-python = ">=3.14"
22+
dependencies = [
23+
# Keep the mypy 2.x semantic-model migration separate from the Python 3.14 host upgrade.
24+
"mypy==1.19.1",
25+
"mypy-extensions==1.1.0",
26+
"protobuf==5.29.3",
27+
"six==1.16.0",
28+
"toml==0.10.2",
29+
"typing-extensions==4.16.0",
30+
"pytest==9.1.1",
31+
"pytest-cov==7.1.0",
32+
33+
# Stub dependencies
34+
"atomicwrites==1.4.1",
35+
"backports-abc==0.5",
36+
"certifi==2023.5.7",
37+
"characteristic==14.3.0",
38+
"click==8.1.3",
39+
"cryptography==36.0.1",
40+
"dataclasses==0.6",
41+
"emoji==2.1.0",
42+
"types-emoji==2.1.0.3",
43+
"enum34==1.1.10",
44+
"filelock==3.4.0",
45+
"first==2.0.2",
46+
"Flask==2.3.2",
47+
"Flask-Cors==3.0.10",
48+
"types-Flask-Cors==3.0.10.5",
49+
"freezegun==1.2.2",
50+
"frozenlist==1.4.1",
51+
"geoip2==4.7.0",
52+
"ipaddress==1.0.23",
53+
"itsdangerous==2.1.2",
54+
"Jinja2==3.1.2",
55+
"kazoo==2.9.0",
56+
"MarkupSafe==2.1.2",
57+
"maxminddb==2.3.0",
58+
"orjson==3.12.0",
59+
"pandas==2.3.3",
60+
"pandas-stubs==2.2.3.241009",
61+
"pathlib==1.0.1",
62+
"PyJWT==2.7.0",
63+
"PyYAML==6.0.1",
64+
"pyspark==3.5.4",
65+
"types-PyYAML==6.0.12.20240311",
66+
"requests==2.30.0",
67+
"types-requests==2.30.0.0",
68+
"Routes==2.5.1",
69+
"termcolor==2.3.0",
70+
"tornado==6.3.1",
71+
"Werkzeug==2.3.4",
72+
"xxhash==3.2.0",
73+
# These versions preserve the FastAPI/Starlette APIs modeled by existing rules.
74+
# They are build-only dependencies; the analyzer does not ship or execute them.
75+
"fastapi==0.98.0",
76+
# FastAPI requires Pydantic v1. Custom Pydantic modules are serialized separately
77+
# and take precedence over imported modules when the analyzer loads descriptors.
78+
"pydantic==1.10.26",
79+
"starlette==0.27.0",
80+
81+
# Lock the transitive dependency from pandas and pandas-stubs. NumPy 2.5 stubs
82+
# use Python 3.12 type statements, while the serializer also targets Python 3.10.
83+
"numpy==2.4.2",
84+
]
85+
86+
[tool.pytest.ini_options]
87+
addopts = "--cov=serializer --cov=runners --cov-report xml:cov.xml --ignore=resources --cov-branch"
88+
89+
[[tool.uv.index]]
90+
name = "repox"
91+
url = "https://repox.jfrog.io/artifactory/api/pypi/sonarsource-pypi/simple"
92+
default = true

python-frontend/typeshed_serializer/requirements.txt

Lines changed: 0 additions & 61 deletions
This file was deleted.

python-frontend/typeshed_serializer/runners/tox_runner.py renamed to python-frontend/typeshed_serializer/runners/serializer_runner.py

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
},
6666
}
6767

68-
logger = logging.getLogger('tox_runner')
68+
logger = logging.getLogger('runner')
6969
handler = logging.StreamHandler(sys.stdout)
7070
log_formatter = logging.Formatter(fmt='%(name)s [%(levelname)s] --- %(message)s ---')
7171
logger.setLevel(logging.INFO)
@@ -91,7 +91,7 @@ def fetch_resource_file_names(folder_name: str, file_extension: str) -> list[str
9191

9292

9393
def fetch_config_file_names() -> list[str]:
94-
return [os.path.join(CURRENT_PATH, '../requirements.txt'), os.path.join(CURRENT_PATH, '../tox.ini')]
94+
return [os.path.join(CURRENT_PATH, '../pyproject.toml'), os.path.join(CURRENT_PATH, '../uv.lock')]
9595

9696
def fetch_source_file_names(folder_path: str) -> list[str]:
9797
filenames = fetch_python_file_names(folder_path)
@@ -238,26 +238,31 @@ def compute_and_compare_checksums(check_type: str, folder_name: str, folder_file
238238

239239

240240

241-
def get_serialize_command_to_run(previous_source_checksum: Optional[str], current_sources_checksum: str, changed_serializers: List[str]) -> Optional[List[str]]:
242-
"""Determine the serialization command to run based on checksums and changed serializers.
241+
def get_serialize_command_to_run(previous_source_checksum: Optional[str], current_sources_checksum: str, changed_serializers: List[str]) -> Optional[List[List[str]]]:
242+
"""Determine the serialization commands to run based on checksums and changed serializers.
243243
244244
Args:
245245
previous_source_checksum: Previous checksum of source files
246246
current_sources_checksum: Current checksum of source files
247247
changed_serializers: List of serializers that have changed
248248
249249
Returns:
250-
Command to run as list of strings, or None if no serialization needed
250+
List of commands to run sequentially as list of string lists, or None if no serialization needed
251251
"""
252252
if previous_source_checksum != current_sources_checksum:
253253
# Serializer code has changed - run full serialization
254254
logger.info('SERIALIZER CODE HAS CHANGED - STARTING FULL TYPESHED SERIALIZATION')
255-
return ['tox', '-e', 'serialize']
255+
return [
256+
['uv', 'run', 'python', '-m', 'utils.folder_manager'],
257+
['uv', 'run', 'python', '-m', 'serializer.typeshed_serializer'],
258+
]
256259
elif changed_serializers:
257260
logger.info(f"STARTING SELECTIVE TYPESHED SERIALIZATION FOR: {','.join(changed_serializers)}")
258-
# Run selective serialization through tox environment
259261
serializers_arg = ','.join(changed_serializers)
260-
return ['tox', '-e', 'selective-serialize', '--', serializers_arg]
262+
return [
263+
['uv', 'run', 'python', '-m', 'utils.folder_manager', serializers_arg],
264+
['uv', 'run', 'python', '-m', 'serializer.typeshed_serializer', serializers_arg],
265+
]
261266
else:
262267
logger.info('SKIPPING TYPESHED SERIALIZATION')
263268
return None
@@ -276,33 +281,45 @@ def update_folder_checksums_for_changed_serializers(changed_serializers: List[st
276281
write_folder_checksum(folder_name, source_checksum, binary_checksum)
277282

278283

284+
def _run_serialize(commands: List[List[str]], full_serialization: bool, changed_serializers: List[str], dry_run: bool) -> None:
285+
if dry_run:
286+
for cmd in commands:
287+
logger.info(f'DRY RUN: Would execute: {" ".join(cmd)}')
288+
return
289+
for cmd in commands:
290+
subprocess.run(cmd, check=True)
291+
if full_serialization:
292+
update_all_checksums()
293+
else:
294+
update_folder_checksums_for_changed_serializers(changed_serializers)
295+
296+
297+
def _run_tests(dry_run: bool) -> None:
298+
test_cmd = ['uv', 'run', 'python', '-m', 'pytest', 'tests/']
299+
if dry_run:
300+
logger.info(f'DRY RUN: Would run: {" ".join(test_cmd)}')
301+
else:
302+
subprocess.run(test_cmd, check=True)
303+
304+
279305
def main(skip_tests=False, fail_fast=False, dry_run=False):
280-
# Check if serializer source code has changed
281306
source_files = fetch_source_file_names(SERIALIZER_PATH)
282307
current_sources_checksum = compute_checksum(source_files, normalize_text_files)
283308
previous_sources_checksum = read_previous_checksum(SERIALIZER_SOURCE_CHECKSUM_FILE)
284-
serializer_sources_changed = compute_and_compare_checksums("SERIALIZER_SOURCE", SERIALIZER_PATH, source_files, normalize_text_files, previous_sources_checksum)
309+
compute_and_compare_checksums("SERIALIZER_SOURCE", SERIALIZER_PATH, source_files, normalize_text_files, previous_sources_checksum)
285310

286-
if serializer_sources_changed and fail_fast :
311+
if previous_sources_checksum != current_sources_checksum and fail_fast:
287312
raise RuntimeError('INCONSISTENT SOURCES CHECKSUMS')
288313

289314
changed_serializers = detect_required_serializations(fail_fast)
290-
serialize_command_to_run = get_serialize_command_to_run(previous_sources_checksum, current_sources_checksum, changed_serializers)
315+
full_serialization = previous_sources_checksum != current_sources_checksum
316+
serialize_commands = get_serialize_command_to_run(previous_sources_checksum, current_sources_checksum, changed_serializers)
291317

292-
# Execute or display the serialize command
293-
if serialize_command_to_run:
294-
if dry_run:
295-
logger.info(f'DRY RUN: Would execute: {" ".join(serialize_command_to_run)}')
296-
else:
297-
_ = subprocess.run(serialize_command_to_run, check=True)
298-
update_folder_checksums_for_changed_serializers(changed_serializers)
318+
if serialize_commands:
319+
_run_serialize(serialize_commands, full_serialization, changed_serializers, dry_run)
299320

300-
# Run tests after serialization (unless skip_tests=True)
301321
if not skip_tests:
302-
if dry_run:
303-
logger.info('DRY RUN: Would run test')
304-
else:
305-
_ = subprocess.run(['tox', '-e', 'py314'], check=True)
322+
_run_tests(dry_run)
306323

307324

308325
if __name__ == '__main__':
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6f00fdc8583bdda94825a556205a538829ee31371722518613d50800d2ddf380
1+
4384976d2c4b1c24d007d635f81e8080d05481397e998148f379151591d510f7

0 commit comments

Comments
 (0)