Skip to content

Commit a1710b2

Browse files
Introduce uv for Project Management (#547)
1 parent e5fb741 commit a1710b2

File tree

14 files changed

+1198
-253
lines changed

14 files changed

+1198
-253
lines changed

Diff for: .github/workflows/ci.yml

+26-20
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@v4
1717

18-
- name: set up python
19-
uses: actions/setup-python@v5
18+
- name: set up uv
19+
uses: astral-sh/setup-uv@v5
2020
with:
21-
python-version: '3.10'
21+
python-version: '3.12'
2222

23-
- run: pip install -r requirements/linting.txt -r requirements/pyproject.txt
23+
- name: Install dependencies
24+
# Installing pip is required for the pre-commit action:
25+
run: |
26+
uv sync --group linting --all-extras
27+
uv pip install pip
2428
25-
- uses: pre-commit/[email protected].0
29+
- uses: pre-commit/[email protected].1
2630
with:
2731
extra_args: --all-files
2832

@@ -37,18 +41,21 @@ jobs:
3741
env:
3842
PYTHON: ${{ matrix.python }}
3943
OS: ${{ matrix.os }}
44+
UV_PYTHON_PREFERENCE: only-managed
4045

4146
runs-on: ${{ matrix.os }}
4247

4348
steps:
4449
- uses: actions/checkout@v4
4550

46-
- name: set up python
47-
uses: actions/setup-python@v5
51+
- name: set up uv
52+
uses: astral-sh/setup-uv@v5
4853
with:
4954
python-version: ${{ matrix.python }}
5055

51-
- run: pip install -r requirements/testing.txt -r requirements/pyproject.txt
56+
- name: Install dependencies
57+
run: |
58+
uv sync --group testing --all-extras
5259
5360
- name: test
5461
run: make test
@@ -57,16 +64,16 @@ jobs:
5764
CONTEXT: ${{ runner.os }}-py${{ matrix.python }}
5865

5966
- name: uninstall deps
60-
run: pip uninstall -y PyYAML
67+
run: uv pip uninstall PyYAML
6168

6269
- name: test without deps
6370
run: make test
6471
env:
6572
COVERAGE_FILE: .coverage.${{ runner.os }}-py${{ matrix.python }}-without-deps
6673
CONTEXT: ${{ runner.os }}-py${{ matrix.python }}-without-deps
6774

68-
- run: coverage combine
69-
- run: coverage xml
75+
- run: uv run coverage combine
76+
- run: uv run coverage xml
7077

7178
- uses: codecov/codecov-action@v4
7279
with:
@@ -86,9 +93,8 @@ jobs:
8693
jobs: ${{ toJSON(needs) }}
8794

8895
release:
89-
name: Release
9096
needs: [check]
91-
if: "success() && startsWith(github.ref, 'refs/tags/')"
97+
if: needs.check.outputs.result == 'success' && startsWith(github.ref, 'refs/tags/')
9298
runs-on: ubuntu-latest
9399
environment: release
94100

@@ -98,20 +104,20 @@ jobs:
98104
steps:
99105
- uses: actions/checkout@v4
100106

101-
- name: set up python
102-
uses: actions/setup-python@v5
107+
- uses: actions/setup-python@v5
103108
with:
104-
python-version: '3.10'
109+
python-version: '3.12'
105110

106-
- name: install
111+
- name: Install 'build' library
107112
run: pip install -U build
108113

109-
- name: check GITHUB_REF matches package version
110-
uses: samuelcolvin/[email protected]
114+
- name: Check version
115+
id: check-tag
116+
uses: samuelcolvin/[email protected]
111117
with:
112118
version_file_path: pydantic_settings/version.py
113119

114-
- name: build
120+
- name: Build library
115121
run: python -m build
116122

117123
- name: Upload package to PyPI

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ venv/
66
env3*/
77
Pipfile
88
*.lock
9+
!uv.lock
910
*.py[cod]
1011
*.egg-info/
1112
/build/

Diff for: Makefile

+10-16
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,35 @@ sources = pydantic_settings tests
33

44
.PHONY: install
55
install:
6-
python -m pip install -U pip
7-
pip install -r requirements/all.txt
8-
pip install -e .
6+
uv sync --all-extras --all-groups
97

108
.PHONY: refresh-lockfiles
119
refresh-lockfiles:
12-
@echo "Updating requirements/*.txt files using pip-compile"
13-
find requirements/ -name '*.txt' ! -name 'all.txt' -type f -delete
14-
pip-compile -q --no-emit-index-url --resolver backtracking -o requirements/linting.txt requirements/linting.in
15-
pip-compile -q --no-emit-index-url --resolver backtracking -o requirements/testing.txt requirements/testing.in
16-
pip-compile -q --no-emit-index-url --resolver backtracking --extra toml --extra yaml --extra azure-key-vault -o requirements/pyproject.txt pyproject.toml
17-
pip install --dry-run -r requirements/all.txt
10+
@echo "Updating uv.lock file"
11+
uv lock -U
1812

1913
.PHONY: format
2014
format:
21-
ruff check --fix $(sources)
22-
ruff format $(sources)
15+
uv run ruff check --fix $(sources)
16+
uv run ruff format $(sources)
2317

2418
.PHONY: lint
2519
lint:
26-
ruff check $(sources)
27-
ruff format --check $(sources)
20+
uv run ruff check $(sources)
21+
uv run ruff format --check $(sources)
2822

2923
.PHONY: mypy
3024
mypy:
31-
mypy pydantic_settings
25+
uv run mypy pydantic_settings
3226

3327
.PHONY: test
3428
test:
35-
coverage run -m pytest --durations=10
29+
uv run coverage run -m pytest --durations=10
3630

3731
.PHONY: testcov
3832
testcov: test
3933
@echo "building coverage html"
40-
@coverage html
34+
@uv run coverage html
4135

4236
.PHONY: all
4337
all: lint mypy testcov

Diff for: docs/index.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ print(Settings().model_dump())
7373
{
7474
'auth_key': 'xxx',
7575
'api_key': 'xxx',
76-
'redis_dsn': Url('redis://user:pass@localhost:6379/1'),
77-
'pg_dsn': MultiHostUrl('postgres://user:pass@localhost:5432/foobar'),
78-
'amqp_dsn': Url('amqp://user:pass@localhost:5672/'),
76+
'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1'),
77+
'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar'),
78+
'amqp_dsn': AmqpDsn('amqp://user:pass@localhost:5672/'),
7979
'special_function': math.cos,
8080
'domains': set(),
8181
'more_settings': {'foo': 'bar', 'apple': 1},
@@ -2055,7 +2055,7 @@ class Settings(BaseSettings):
20552055

20562056

20572057
print(Settings(database_dsn='postgres://postgres@localhost:5432/kwargs_db'))
2058-
#> database_dsn=MultiHostUrl('postgres://postgres@localhost:5432/kwargs_db')
2058+
#> database_dsn=PostgresDsn('postgres://postgres@localhost:5432/kwargs_db')
20592059
```
20602060

20612061
By flipping `env_settings` and `init_settings`, environment variables now have precedence over `__init__` kwargs.

Diff for: pydantic_settings/sources.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ class Cfg(BaseSettings):
894894
type_has_key = self.next_field(type_, key, case_sensitive)
895895
if type_has_key:
896896
return type_has_key
897-
if is_model_class(annotation) or is_pydantic_dataclass(annotation):
897+
if is_model_class(annotation) or is_pydantic_dataclass(annotation): # type: ignore[arg-type]
898898
fields = _get_model_fields(annotation)
899899
# `case_sensitive is None` is here to be compatible with the old behavior.
900900
# Has to be removed in V3.
@@ -1793,11 +1793,13 @@ def _add_parser_args(
17931793
if isinstance(group, dict):
17941794
group = self._add_group(parser, **group)
17951795
added_args += list(arg_names)
1796-
self._add_argument(group, *(f'{flag_prefix[:len(name)]}{name}' for name in arg_names), **kwargs)
1796+
self._add_argument(
1797+
group, *(f'{flag_prefix[: len(name)]}{name}' for name in arg_names), **kwargs
1798+
)
17971799
else:
17981800
added_args += list(arg_names)
17991801
self._add_argument(
1800-
parser, *(f'{flag_prefix[:len(name)]}{name}' for name in arg_names), **kwargs
1802+
parser, *(f'{flag_prefix[: len(name)]}{name}' for name in arg_names), **kwargs
18011803
)
18021804

18031805
self._add_parser_alias_paths(parser, alias_path_args, added_args, arg_prefix, subcommand_prefix, group)
@@ -2247,7 +2249,7 @@ def _load_env_vars(self) -> Mapping[str, Optional[str]]:
22472249
return AzureKeyVaultMapping(secret_client)
22482250

22492251
def __repr__(self) -> str:
2250-
return f'{self.__class__.__name__}(url={self._url!r}, ' f'env_nested_delimiter={self.env_nested_delimiter!r})'
2252+
return f'{self.__class__.__name__}(url={self._url!r}, env_nested_delimiter={self.env_nested_delimiter!r})'
22512253

22522254

22532255
def _get_env_var_key(key: str, case_sensitive: bool = False) -> str:

Diff for: pyproject.toml

+17
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ Source = 'https://github.com/pydantic/pydantic-settings'
5858
Changelog = 'https://github.com/pydantic/pydantic-settings/releases'
5959
Documentation = 'https://docs.pydantic.dev/dev-v2/concepts/pydantic_settings/'
6060

61+
[dependency-groups]
62+
linting = [
63+
"black",
64+
"mypy",
65+
"pre-commit",
66+
"pyyaml",
67+
"ruff",
68+
"types-pyyaml",
69+
]
70+
testing = [
71+
"coverage[toml]",
72+
"pytest",
73+
"pytest-examples",
74+
"pytest-mock",
75+
"pytest-pretty",
76+
]
77+
6178
[tool.pytest.ini_options]
6279
testpaths = 'tests'
6380
filterwarnings = [

Diff for: requirements/all.txt

-3
This file was deleted.

Diff for: requirements/linting.in

-7
This file was deleted.

Diff for: requirements/linting.txt

-58
This file was deleted.

Diff for: requirements/pyproject.txt

-75
This file was deleted.

0 commit comments

Comments
 (0)