Skip to content

Commit c42ddba

Browse files
jashparekhJash Parekh
andauthored
Major upgrade: Python 3.14, Pydantic v2, Ruff linter, and library updates (#572)
Co-authored-by: Jash Parekh <jparekh1@wayfair.com>
1 parent fc8954f commit c42ddba

22 files changed

+426
-335
lines changed

.bandit

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

.flake8

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

.github/workflows/main.yml

Lines changed: 12 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,10 @@ on:
88
branches: ["main"]
99

1010
env:
11-
PYTHON_VERSION: "3.12"
11+
PYTHON_VERSION: "3.13"
1212

1313
jobs:
14-
bandit:
15-
runs-on: ubuntu-latest
16-
steps:
17-
- name: Check out code
18-
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
19-
- uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
20-
with:
21-
python-version: ${{ env.PYTHON_VERSION }}
22-
- name: Install dependencies
23-
uses: ./.github/actions/install-dependencies
24-
with:
25-
test-requirements: "true"
26-
27-
- name: Run bandit
28-
run: bandit --ini .bandit -r gbq
29-
30-
black:
14+
ruff:
3115
runs-on: ubuntu-latest
3216
steps:
3317
- name: Check out code
@@ -41,26 +25,13 @@ jobs:
4125
with:
4226
test-requirements: "true"
4327

44-
- name: Run black
45-
run: black --check gbq tests
46-
47-
flake8:
48-
runs-on: ubuntu-latest
49-
steps:
50-
- name: Check out code
51-
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
52-
- uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
53-
with:
54-
python-version: ${{ env.PYTHON_VERSION }}
55-
- name: Install dependencies
56-
uses: ./.github/actions/install-dependencies
57-
with:
58-
test-requirements: "true"
28+
- name: Run ruff linter
29+
run: ruff check gbq tests
5930

60-
- name: Run flake8
61-
run: flake8 gbq tests
31+
- name: Run ruff formatter
32+
run: ruff format --check gbq tests
6233

63-
isort:
34+
bandit:
6435
runs-on: ubuntu-latest
6536
steps:
6637
- name: Check out code
@@ -73,8 +44,8 @@ jobs:
7344
with:
7445
test-requirements: "true"
7546

76-
- name: Run isort
77-
run: isort --check-only gbq tests
47+
- name: Run bandit
48+
run: bandit -c pyproject.toml -r gbq
7849

7950
mypy:
8051
runs-on: ubuntu-latest
@@ -90,7 +61,7 @@ jobs:
9061
runs-on: ubuntu-latest
9162
strategy:
9263
matrix:
93-
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
64+
python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
9465
steps:
9566
- name: Check out code
9667
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
@@ -133,7 +104,7 @@ jobs:
133104
runs-on: ubuntu-latest
134105
strategy:
135106
matrix:
136-
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
107+
python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
137108
steps:
138109
- name: Check out code
139110
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
@@ -153,7 +124,7 @@ jobs:
153124
- name: Check out code
154125
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
155126
- name: Build devbox image
156-
run: "docker-compose build devbox"
127+
run: "docker compose build devbox"
157128

158129
build-docs:
159130
runs-on: ubuntu-latest

CHANGELOG.md

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,50 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [Unreleased]
8+
9+
## [1.1.0] - 2025-11-02
10+
11+
### Added
12+
- Support for Python 3.10, 3.11, 3.12, 3.13, and 3.14
13+
- Replaced `pip` with `uv` package manager for faster dependency resolution
14+
- Replaced `black`, `isort`, `flake8`, and `autoflake` with `ruff` for unified linting and formatting
15+
716
### Changed
8-
- Fixed get_bq_schema_from_json_schema() SchemaField parameters
17+
- Upgraded Pydantic from v1 to v2.12.3
18+
- Upgraded all core dependencies to latest versions:
19+
- `google-cloud-bigquery` to 3.38.0
20+
- `google-api-core` to 2.28.1
21+
- `google-auth` to 2.42.1
22+
- `google-cloud-core` to 2.5.0
23+
- `google-crc32c` to 1.7.1
24+
- `google-resumable-media` to 2.7.2
25+
- `googleapis-common-protos` to 1.71.0
26+
- Updated documentation dependencies for Python 3.14 compatibility:
27+
- `mkdocs` to 1.6.1
28+
- `mkdocs-material` to 9.5.49
29+
- `mkdocstrings[python]` to 0.27.0
30+
- `mike` to 2.1.1
31+
- Updated CI workflow to use Docker Compose V2 (`docker compose` instead of `docker-compose`)
32+
- Moved bandit configuration from `.bandit` file to `pyproject.toml`
33+
- Updated `pyproject.toml` with ruff configuration for linting and formatting
34+
35+
### Removed
36+
- Support for Python 3.8 and 3.9
37+
- Individual linter configurations (`.flake8`, `[tool.black]`, `[tool.isort]`)
938

10-
## [Unreleased]
39+
### Fixed
40+
- Fixed `SchemaField` API compatibility with google-cloud-bigquery 3.x
41+
- Fixed `QueryJob` instantiation in tests for google-cloud-bigquery 3.x compatibility
42+
- Fixed REPEATED mode detection for list-based schema fields in `get_bq_schema_from_record()`
43+
- Fixed Pydantic v2 `model_validator` compatibility issues
44+
- Fixed Docker Compose V2 compatibility in CI workflows
45+
46+
### Internal
47+
- Updated Dockerfile to use Python 3.14
48+
- Installed `uv` in Docker images for package management
49+
- Updated test fixtures and helpers for new API compatibility
50+
- Regenerated `requirements.lock` with updated dependencies
1151

1252
## [1.0.5] - 2024-08-01
1353

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/gbq)][pypi]
44
[![codecov](https://codecov.io/gh/wayfair-incubator/gbq/branch/main/graph/badge.svg)][codecov]
55
[![Checked with mypy](https://img.shields.io/badge/mypy-checked-blue)][mypy-home]
6-
[![Code style: black](https://img.shields.io/badge/code%20style-black-black.svg)][black-home]
6+
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)][ruff-home]
77

88

99
# GBQ
@@ -46,16 +46,14 @@ Check out the [project documentation](https://wayfair-incubator.github.io/gbq/)
4646
[ci]: https://github.com/wayfair-incubator/gbq/actions
4747
[codecov]: https://codecov.io/gh/wayfair-incubator/gbq
4848
[mypy-home]: http://mypy-lang.org/
49-
[black-home]: https://github.com/psf/black
49+
[ruff-home]: https://github.com/astral-sh/ruff
5050
[install-docker]: https://docs.docker.com/install/
5151
[pdbpp-home]: https://github.com/pdbpp/pdbpp
5252
[pdb-docs]: https://docs.python.org/3/library/pdb.html
5353
[pdbpp-docs]: https://github.com/pdbpp/pdbpp#usage
5454
[pytest-docs]: https://docs.pytest.org/en/latest/
5555
[mypy-docs]: https://mypy.readthedocs.io/en/stable/
56-
[black-docs]: https://black.readthedocs.io/en/stable/
57-
[isort-docs]: https://pycqa.github.io/isort/
58-
[flake8-docs]: http://flake8.pycqa.org/en/stable/
56+
[ruff-docs]: https://docs.astral.sh/ruff/
5957
[bandit-docs]: https://bandit.readthedocs.io/en/stable/
6058
[sem-ver]: https://semver.org/
6159
[pypi]: https://semver.org/

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "3.4"
1+
version: "3.9"
22

33
x-mount-app-and-user-git-config: &mount-app-and-user-git-config
44
volumes:

docker/devbox.dockerfile

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,42 @@
1-
FROM python:3.12-bookworm
1+
FROM python:3.14-bookworm
22

33
ARG _USER="gbq"
44
ARG _UID="1000"
55
ARG _GID="100"
66
ARG _SHELL="/bin/bash"
77

8+
# Install uv as root before creating the user
9+
ENV UV_NO_CACHE="true"
10+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \
11+
cp /root/.local/bin/uv /usr/local/bin/uv && \
12+
cp /root/.local/bin/uvx /usr/local/bin/uvx
13+
814
RUN useradd -m -s "${_SHELL}" -N -u "${_UID}" "${_USER}"
915

10-
ENV USER ${_USER}
11-
ENV UID ${_UID}
12-
ENV GID ${_GID}
13-
ENV HOME /home/${_USER}
14-
ENV PATH "${HOME}/.local/bin/:${PATH}"
15-
ENV PIP_NO_CACHE_DIR "true"
16+
ENV USER=${_USER}
17+
ENV UID=${_UID}
18+
ENV GID=${_GID}
19+
ENV HOME=/home/${_USER}
20+
ENV PATH="${HOME}/.local/bin/:${PATH}"
1621

1722
RUN mkdir /app && chown ${UID}:${GID} /app
1823

19-
USER ${_USER}
20-
21-
COPY --chown=${UID}:${GID} ./requirements* /app/
24+
# Copy requirements files as root since we'll install as root
25+
COPY ./requirements* /app/
2226
WORKDIR /app
2327

24-
RUN pip install -r requirements.lock -r requirements-test.txt -r requirements-docs.txt
28+
# Install from requirements.txt first, then add test and docs requirements
29+
# Skip lock file if it's empty or just a comment
30+
# Install as root since --system requires write access to system site-packages
31+
RUN if [ -s requirements.lock ] && [ "$(grep -v '^#' requirements.lock | wc -l)" -gt 0 ]; then \
32+
uv pip install --system -r requirements.lock -r requirements-test.txt -r requirements-docs.txt; \
33+
else \
34+
uv pip install --system -r requirements.txt -r requirements-test.txt -r requirements-docs.txt; \
35+
fi
36+
37+
# Change ownership of app directory to user
38+
RUN chown -R ${UID}:${GID} /app
39+
40+
USER ${_USER}
2541

2642
CMD bash

docker/lock_requirements.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env bash
22

3-
pip uninstall -y -r <(pip freeze)
4-
pip install -r requirements.txt
3+
uv pip uninstall --system -r <(uv pip freeze --system)
4+
uv pip install --system -r requirements.txt
55
printf "# THIS IS AN AUTOGENERATED LOCKFILE. DO NOT EDIT MANUALLY.\n" > requirements.lock
6-
pip freeze --disable-pip-version-check --all >> requirements.lock
6+
uv pip freeze --system >> requirements.lock
77

8-
echo "Rebuild containers to verify there are no conflicts."
8+
echo "Rebuild containers to verify there are no conflicts."

docker/run_tests.sh

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
set -eo pipefail
44

5-
BLACK_ACTION="--check"
6-
ISORT_ACTION="--check-only"
5+
RUFF_FIX=""
76

87
function usage
98
{
@@ -17,8 +16,7 @@ while [[ $# -gt 0 ]]; do
1716
arg="$1"
1817
case $arg in
1918
--format-code)
20-
BLACK_ACTION="--quiet"
21-
ISORT_ACTION=""
19+
RUFF_FIX="--fix"
2220
;;
2321
-h|--help)
2422
usage
@@ -37,20 +35,18 @@ done
3735
# only generate html locally
3836
pytest tests --cov-report html
3937

40-
echo "Running autoflake..."
41-
autoflake -irv --remove-all-unused-import gbq tests
38+
echo "Running ruff linter..."
39+
ruff check ${RUFF_FIX} gbq tests
4240

43-
echo "Running isort..."
44-
isort ${ISORT_ACTION} gbq tests
45-
46-
echo "Running black..."
47-
black ${BLACK_ACTION} gbq tests
48-
49-
echo "Running flake8..."
50-
flake8 gbq tests
41+
echo "Running ruff formatter..."
42+
if [ -z "${RUFF_FIX}" ]; then
43+
ruff format --check gbq tests
44+
else
45+
ruff format gbq tests
46+
fi
5147

5248
echo "Running mypy..."
5349
mypy gbq
5450

5551
echo "Running bandit..."
56-
bandit --ini .bandit --quiet -r gbq
52+
bandit -c pyproject.toml --quiet -r gbq

docs/development-guide.md

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ details on how to [install docker][install-docker] on your computer.
1616
Once that is configured, the test suite can be run locally:
1717

1818
```bash
19-
docker-compose run --rm test
19+
docker compose run --rm test
2020
```
2121

2222
If you want to be able to execute code in the container:
2323

2424
```bash
25-
docker-compose run --rm devbox
25+
docker compose run --rm devbox
2626
(your code here)
2727
```
2828

@@ -50,11 +50,11 @@ See the documentation on [pdb][pdb-docs] and [pdb++][pdbpp-docs] for more inform
5050
You'll be unable to merge code unless the linting and tests pass. You can run these in your container via:
5151

5252
```bash
53-
docker-compose run --rm test
53+
docker compose run --rm test
5454
```
5555

5656
This will run the same tests, linting, and code coverage that are run by the CI pipeline. The only difference is that,
57-
when run locally, `black` and `isort` are configured to automatically correct issues they detect.
57+
when run locally, `ruff` is configured to automatically fix issues it detects (with the `--format-code` flag).
5858

5959
Generally we should endeavor to write tests for every feature. Every new feature branch should increase the test
6060
coverage rather than decreasing it.
@@ -67,10 +67,8 @@ To customize / override a specific testing stage, please read the documentation
6767

6868
1. [PyTest][pytest-docs]
6969
2. [MyPy][mypy-docs]
70-
3. [Black][black-docs]
71-
4. [Isort][isort-docs]
72-
5. [Flake8][flake8-docs]
73-
6. [Bandit][bandit-docs]
70+
3. [Ruff][ruff-docs]
71+
4. [Bandit][bandit-docs]
7472

7573
### Building the Library
7674

@@ -119,8 +117,8 @@ This same pipeline also runs on the default branch when a maintainer merges a pu
119117

120118
### Lints
121119

122-
The first set of jobs that run as part of the CI pipline are linters that perform static analysis on the code. This
123-
includes: [MyPy][mypy-docs], [Black][black-docs], [Isort][isort-docs], [Flake8][flake8-docs], and [Bandit][bandit-docs].
120+
The first set of jobs that run as part of the CI pipeline are linters that perform static analysis on the code. This
121+
includes: [MyPy][mypy-docs], [Ruff][ruff-docs], and [Bandit][bandit-docs].
124122

125123
### Tests
126124

@@ -145,9 +143,7 @@ The pipeline runs the tests cases across each supported version of Python to ens
145143
[pdbpp-docs]: https://github.com/pdbpp/pdbpp#usage
146144
[pytest-docs]: https://docs.pytest.org/en/latest/
147145
[mypy-docs]: https://mypy.readthedocs.io/en/stable/
148-
[black-docs]: https://black.readthedocs.io/en/stable/
149-
[isort-docs]: https://pycqa.github.io/isort/
150-
[flake8-docs]: http://flake8.pycqa.org/en/stable/
146+
[ruff-docs]: https://docs.astral.sh/ruff/
151147
[bandit-docs]: https://bandit.readthedocs.io/en/stable/
152148
[sem-ver]: https://semver.org/
153149
[pep-517]: https://www.python.org/dev/peps/pep-0517

0 commit comments

Comments
 (0)