bump-dependencies 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Corey Goldberg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: bump-dependencies
3
+ Version: 0.1.0
4
+ Summary: Bump Python package dependencies in pyproject.toml
5
+ Author: Corey Goldberg
6
+ Maintainer: Corey Goldberg
7
+ License-Expression: MIT
8
+ Project-URL: homepage, https://github.com/cgoldberg/bump-dependencies
9
+ Project-URL: source, https://github.com/cgoldberg/bump-dependencies
10
+ Project-URL: download, https://pypi.org/project/bump-dependencies
11
+ Keywords: package,dependencies,requirements,bump,upgrade
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: packaging==25.0
25
+ Requires-Dist: requests==2.32.4
26
+ Requires-Dist: rich==14.0.0
27
+ Requires-Dist: tomlkit==0.13.3
28
+ Requires-Dist: validate-pyproject==0.24.1
29
+ Dynamic: license-file
30
+
31
+ # bump-dependencies
32
+
33
+ ## Python - bump your package dependencies
34
+
35
+ *Update dependency specifiers in `pyproject.toml` to latest versions*
36
+
37
+ ---
38
+
39
+ - Copyright (c) 2025 [Corey Goldberg][github-home]
40
+ - Development: [GitHub][github-repo]
41
+ - Download/Install: [PyPI][pypi-bump-dependencies]
42
+ - License: [MIT][mit-license]
43
+
44
+ ----
45
+
46
+ ## Installation:
47
+
48
+ Install from [PyPI][pypi-bump-dependencies]:
49
+
50
+ ```
51
+ pip install bump-dependencies
52
+ ```
53
+ ----
54
+
55
+ ## Usage:
56
+
57
+ ```
58
+ usage: bump_dependencies [-h] [--dry-run] [--path PATH]
59
+
60
+ options:
61
+ -h, --help show this help message and exit
62
+ --dry-run don't write changes to pyproject.toml
63
+ --path PATH path to pyproject.toml (defaults to current directory)
64
+ ```
65
+
66
+ ## About:
67
+
68
+ `bump_dependencies` is a Python CLI program that generates a new packaging
69
+ configuration file (`pyproject.toml`) file with updated package dependencies.
70
+
71
+ - for more information on declaring dependencies in a configuration file, see the [PyPA pyproject.toml Spec][pypa-pyproject-dependencies]
72
+ - for more information on version specifiers, see [PEP 440][pep-440] and the [PyPA Version Specifiers Spec][pypa-version-specifiers]
73
+ - for more information on dependency specifiers, see [PEP 508][pep-508] and the [PyPA Dependency Specifiers Spec][pypa-dependency-specifiers]
74
+ - for more information on dependency groups, see [PEP 735][pep-735] and the [PyPA Dependency Groups Spec][pypa-dependency-groups]
75
+
76
+ #### Example:
77
+
78
+ If your `pyproject.toml` contains this:
79
+
80
+ ```
81
+ [project]
82
+ ... some metadata ...
83
+ dependencies = ["matplotlib~=3.9", "requests==2.29.0"]
84
+
85
+ [project.optional-dependencies]
86
+ socks = ["PySocks>=1.5.6"]
87
+
88
+ [dependency-groups]
89
+ dev = ["black==23.9.1", "ruff==0.9.5"]
90
+ test = ["pytest>8", "pytest-mock>=3.11"]
91
+ ```
92
+
93
+ It will update dependency specifiers to the latest versions available on [PyPI][pypi-home]:
94
+
95
+ ```
96
+ [project]
97
+ ... some metadata ...
98
+ dependencies = ["matplotlib~=3.10.3", "requests==2.32.4"]
99
+
100
+ [project.optional-dependencies]
101
+ socks = ["PySocks>=1.7.1"]
102
+
103
+ [dependency-groups]
104
+ dev = ["black==25.1.0", "ruff==0.12.1"]
105
+ test = ["pytest>8.4.1", "pytest-mock>=3.14.1"]
106
+ ```
107
+
108
+ #### Which sections of `pyproject.toml` will be updated?
109
+
110
+ It will update dependency specifiers listed in various sections of `pyproject.toml`:
111
+
112
+ - `dependencies` list from `[project]` section
113
+ - dependency lists from `[project.optional-dependencies]` section
114
+ - dependency lists from `[dependency-groups]` section
115
+
116
+ #### Which dependency specifiers will be updated?
117
+
118
+ - will only update dependency specifiers with version identifier
119
+ containing comparison operator: `==`, `===`, `~=`, `>`, `>=`
120
+ - example:
121
+ - `foo==1.0.0`
122
+ - `foo~=1.0`
123
+ - `foo>=1`
124
+ - will not update dependency specifiers with version identifier
125
+ containing comparison operator: `<`, `<=`, `!=`
126
+ - example:
127
+ - `foo<2.0`
128
+ - `foo>=1,<2`
129
+ - `foo > 1.0, != 1.0.1`
130
+ - will not update unversioned dependency specifiers
131
+ - example:
132
+ - `foo`
133
+ - `foo[bar]`
134
+ - will not update direct reference dependency specifiers
135
+ - example:
136
+ - `foo @ https://github.com/foo/foo/archive/1.0.0.zip`
137
+ - `foo @ file:///builds/foo-1.0.0-py3-none-any.whl`
138
+
139
+ #### Supported comparison operators in version identifiers:
140
+
141
+ - `==` : version matching
142
+ - `===` : arbitrary equality
143
+ - `~=` : compatible release
144
+ - `>` : exclusive ordered comparison
145
+ - `>=` : inclusive ordered comparison
146
+
147
+ #### Unsupported comparison operators in version identifiers:
148
+
149
+ - `<` : exclusive ordered comparison
150
+ - `<=` : inclusive ordered comparison
151
+ - `!=` : version exclusion
152
+
153
+
154
+ [github-home]: https://github.com/cgoldberg
155
+ [github-repo]: https://github.com/cgoldberg/bump-dependencies
156
+ [pypi-home]: https://pypi.org
157
+ [pypi-bump-dependencies]: https://pypi.org/project/bump-dependencies
158
+ [mit-license]: https://raw.githubusercontent.com/cgoldberg/bump-dependencies/refs/heads/master/LICENSE
159
+ [pep-440]: https://peps.python.org/pep-0440
160
+ [pep-508]: https://peps.python.org/pep-0508
161
+ [pep-735]: https://peps.python.org/pep-0735
162
+ [pypa-version-specifiers]: https://packaging.python.org/en/latest/specifications/version-specifiers
163
+ [pypa-dependency-specifiers]: https://packaging.python.org/en/latest/specifications/dependency-specifiers
164
+ [pypa-dependency-groups]: https://packaging.python.org/en/latest/specifications/dependency-groups
165
+ [pypa-pyproject-dependencies]: https://packaging.python.org/en/latest/specifications/pyproject-toml/#dependencies-optional-dependencies
@@ -0,0 +1,135 @@
1
+ # bump-dependencies
2
+
3
+ ## Python - bump your package dependencies
4
+
5
+ *Update dependency specifiers in `pyproject.toml` to latest versions*
6
+
7
+ ---
8
+
9
+ - Copyright (c) 2025 [Corey Goldberg][github-home]
10
+ - Development: [GitHub][github-repo]
11
+ - Download/Install: [PyPI][pypi-bump-dependencies]
12
+ - License: [MIT][mit-license]
13
+
14
+ ----
15
+
16
+ ## Installation:
17
+
18
+ Install from [PyPI][pypi-bump-dependencies]:
19
+
20
+ ```
21
+ pip install bump-dependencies
22
+ ```
23
+ ----
24
+
25
+ ## Usage:
26
+
27
+ ```
28
+ usage: bump_dependencies [-h] [--dry-run] [--path PATH]
29
+
30
+ options:
31
+ -h, --help show this help message and exit
32
+ --dry-run don't write changes to pyproject.toml
33
+ --path PATH path to pyproject.toml (defaults to current directory)
34
+ ```
35
+
36
+ ## About:
37
+
38
+ `bump_dependencies` is a Python CLI program that generates a new packaging
39
+ configuration file (`pyproject.toml`) file with updated package dependencies.
40
+
41
+ - for more information on declaring dependencies in a configuration file, see the [PyPA pyproject.toml Spec][pypa-pyproject-dependencies]
42
+ - for more information on version specifiers, see [PEP 440][pep-440] and the [PyPA Version Specifiers Spec][pypa-version-specifiers]
43
+ - for more information on dependency specifiers, see [PEP 508][pep-508] and the [PyPA Dependency Specifiers Spec][pypa-dependency-specifiers]
44
+ - for more information on dependency groups, see [PEP 735][pep-735] and the [PyPA Dependency Groups Spec][pypa-dependency-groups]
45
+
46
+ #### Example:
47
+
48
+ If your `pyproject.toml` contains this:
49
+
50
+ ```
51
+ [project]
52
+ ... some metadata ...
53
+ dependencies = ["matplotlib~=3.9", "requests==2.29.0"]
54
+
55
+ [project.optional-dependencies]
56
+ socks = ["PySocks>=1.5.6"]
57
+
58
+ [dependency-groups]
59
+ dev = ["black==23.9.1", "ruff==0.9.5"]
60
+ test = ["pytest>8", "pytest-mock>=3.11"]
61
+ ```
62
+
63
+ It will update dependency specifiers to the latest versions available on [PyPI][pypi-home]:
64
+
65
+ ```
66
+ [project]
67
+ ... some metadata ...
68
+ dependencies = ["matplotlib~=3.10.3", "requests==2.32.4"]
69
+
70
+ [project.optional-dependencies]
71
+ socks = ["PySocks>=1.7.1"]
72
+
73
+ [dependency-groups]
74
+ dev = ["black==25.1.0", "ruff==0.12.1"]
75
+ test = ["pytest>8.4.1", "pytest-mock>=3.14.1"]
76
+ ```
77
+
78
+ #### Which sections of `pyproject.toml` will be updated?
79
+
80
+ It will update dependency specifiers listed in various sections of `pyproject.toml`:
81
+
82
+ - `dependencies` list from `[project]` section
83
+ - dependency lists from `[project.optional-dependencies]` section
84
+ - dependency lists from `[dependency-groups]` section
85
+
86
+ #### Which dependency specifiers will be updated?
87
+
88
+ - will only update dependency specifiers with version identifier
89
+ containing comparison operator: `==`, `===`, `~=`, `>`, `>=`
90
+ - example:
91
+ - `foo==1.0.0`
92
+ - `foo~=1.0`
93
+ - `foo>=1`
94
+ - will not update dependency specifiers with version identifier
95
+ containing comparison operator: `<`, `<=`, `!=`
96
+ - example:
97
+ - `foo<2.0`
98
+ - `foo>=1,<2`
99
+ - `foo > 1.0, != 1.0.1`
100
+ - will not update unversioned dependency specifiers
101
+ - example:
102
+ - `foo`
103
+ - `foo[bar]`
104
+ - will not update direct reference dependency specifiers
105
+ - example:
106
+ - `foo @ https://github.com/foo/foo/archive/1.0.0.zip`
107
+ - `foo @ file:///builds/foo-1.0.0-py3-none-any.whl`
108
+
109
+ #### Supported comparison operators in version identifiers:
110
+
111
+ - `==` : version matching
112
+ - `===` : arbitrary equality
113
+ - `~=` : compatible release
114
+ - `>` : exclusive ordered comparison
115
+ - `>=` : inclusive ordered comparison
116
+
117
+ #### Unsupported comparison operators in version identifiers:
118
+
119
+ - `<` : exclusive ordered comparison
120
+ - `<=` : inclusive ordered comparison
121
+ - `!=` : version exclusion
122
+
123
+
124
+ [github-home]: https://github.com/cgoldberg
125
+ [github-repo]: https://github.com/cgoldberg/bump-dependencies
126
+ [pypi-home]: https://pypi.org
127
+ [pypi-bump-dependencies]: https://pypi.org/project/bump-dependencies
128
+ [mit-license]: https://raw.githubusercontent.com/cgoldberg/bump-dependencies/refs/heads/master/LICENSE
129
+ [pep-440]: https://peps.python.org/pep-0440
130
+ [pep-508]: https://peps.python.org/pep-0508
131
+ [pep-735]: https://peps.python.org/pep-0735
132
+ [pypa-version-specifiers]: https://packaging.python.org/en/latest/specifications/version-specifiers
133
+ [pypa-dependency-specifiers]: https://packaging.python.org/en/latest/specifications/dependency-specifiers
134
+ [pypa-dependency-groups]: https://packaging.python.org/en/latest/specifications/dependency-groups
135
+ [pypa-pyproject-dependencies]: https://packaging.python.org/en/latest/specifications/pyproject-toml/#dependencies-optional-dependencies
@@ -0,0 +1,64 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "bump-dependencies"
7
+ version = "0.1.0"
8
+ description = "Bump Python package dependencies in pyproject.toml"
9
+ license = "MIT"
10
+ license-files = ["LICENSE"]
11
+ authors = [{name = "Corey Goldberg"}]
12
+ maintainers = [{name = "Corey Goldberg"}]
13
+ readme = "README.md"
14
+ requires-python = ">=3.9"
15
+ keywords = ["package", "dependencies", "requirements", "bump", "upgrade"]
16
+ classifiers = [
17
+ "Environment :: Console",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ ]
27
+ dependencies = ["packaging==25.0", "requests==2.32.4", "rich==14.0.0", "tomlkit==0.13.3", "validate-pyproject==0.24.1"]
28
+
29
+ [project.scripts]
30
+ bump_dependencies = "bump_dependencies:main"
31
+
32
+ [project.urls]
33
+ homepage = "https://github.com/cgoldberg/bump-dependencies"
34
+ source = "https://github.com/cgoldberg/bump-dependencies"
35
+ download = "https://pypi.org/project/bump-dependencies"
36
+
37
+ [dependency-groups]
38
+ dev = ["tox"]
39
+ lint = ["black", "ruff"]
40
+ test = ["pytest==8.4.1", "pytest-sugar==1.0.0"]
41
+ validate = ["packaging==25.0", "validate-pyproject==0.24.1"]
42
+
43
+ [tool.setuptools]
44
+ package-dir = {"" = "src"}
45
+
46
+ [tool.pytest.ini_options]
47
+ addopts = "-vv" # extra verbose
48
+
49
+ [tool.black]
50
+ line-length = 120
51
+ target-version = ["py39"]
52
+
53
+ [tool.ruff]
54
+ line-length = 120
55
+ respect-gitignore = true
56
+ target-version = "py39"
57
+
58
+ [tool.ruff.lint]
59
+ extend-select = ["E4", "E7", "E9", "F", "I", "E501", "RUF022"]
60
+ fixable = ["ALL"]
61
+
62
+ [tool.ruff.format]
63
+ docstring-code-format = true
64
+ docstring-code-line-length = 120
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: bump-dependencies
3
+ Version: 0.1.0
4
+ Summary: Bump Python package dependencies in pyproject.toml
5
+ Author: Corey Goldberg
6
+ Maintainer: Corey Goldberg
7
+ License-Expression: MIT
8
+ Project-URL: homepage, https://github.com/cgoldberg/bump-dependencies
9
+ Project-URL: source, https://github.com/cgoldberg/bump-dependencies
10
+ Project-URL: download, https://pypi.org/project/bump-dependencies
11
+ Keywords: package,dependencies,requirements,bump,upgrade
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: packaging==25.0
25
+ Requires-Dist: requests==2.32.4
26
+ Requires-Dist: rich==14.0.0
27
+ Requires-Dist: tomlkit==0.13.3
28
+ Requires-Dist: validate-pyproject==0.24.1
29
+ Dynamic: license-file
30
+
31
+ # bump-dependencies
32
+
33
+ ## Python - bump your package dependencies
34
+
35
+ *Update dependency specifiers in `pyproject.toml` to latest versions*
36
+
37
+ ---
38
+
39
+ - Copyright (c) 2025 [Corey Goldberg][github-home]
40
+ - Development: [GitHub][github-repo]
41
+ - Download/Install: [PyPI][pypi-bump-dependencies]
42
+ - License: [MIT][mit-license]
43
+
44
+ ----
45
+
46
+ ## Installation:
47
+
48
+ Install from [PyPI][pypi-bump-dependencies]:
49
+
50
+ ```
51
+ pip install bump-dependencies
52
+ ```
53
+ ----
54
+
55
+ ## Usage:
56
+
57
+ ```
58
+ usage: bump_dependencies [-h] [--dry-run] [--path PATH]
59
+
60
+ options:
61
+ -h, --help show this help message and exit
62
+ --dry-run don't write changes to pyproject.toml
63
+ --path PATH path to pyproject.toml (defaults to current directory)
64
+ ```
65
+
66
+ ## About:
67
+
68
+ `bump_dependencies` is a Python CLI program that generates a new packaging
69
+ configuration file (`pyproject.toml`) file with updated package dependencies.
70
+
71
+ - for more information on declaring dependencies in a configuration file, see the [PyPA pyproject.toml Spec][pypa-pyproject-dependencies]
72
+ - for more information on version specifiers, see [PEP 440][pep-440] and the [PyPA Version Specifiers Spec][pypa-version-specifiers]
73
+ - for more information on dependency specifiers, see [PEP 508][pep-508] and the [PyPA Dependency Specifiers Spec][pypa-dependency-specifiers]
74
+ - for more information on dependency groups, see [PEP 735][pep-735] and the [PyPA Dependency Groups Spec][pypa-dependency-groups]
75
+
76
+ #### Example:
77
+
78
+ If your `pyproject.toml` contains this:
79
+
80
+ ```
81
+ [project]
82
+ ... some metadata ...
83
+ dependencies = ["matplotlib~=3.9", "requests==2.29.0"]
84
+
85
+ [project.optional-dependencies]
86
+ socks = ["PySocks>=1.5.6"]
87
+
88
+ [dependency-groups]
89
+ dev = ["black==23.9.1", "ruff==0.9.5"]
90
+ test = ["pytest>8", "pytest-mock>=3.11"]
91
+ ```
92
+
93
+ It will update dependency specifiers to the latest versions available on [PyPI][pypi-home]:
94
+
95
+ ```
96
+ [project]
97
+ ... some metadata ...
98
+ dependencies = ["matplotlib~=3.10.3", "requests==2.32.4"]
99
+
100
+ [project.optional-dependencies]
101
+ socks = ["PySocks>=1.7.1"]
102
+
103
+ [dependency-groups]
104
+ dev = ["black==25.1.0", "ruff==0.12.1"]
105
+ test = ["pytest>8.4.1", "pytest-mock>=3.14.1"]
106
+ ```
107
+
108
+ #### Which sections of `pyproject.toml` will be updated?
109
+
110
+ It will update dependency specifiers listed in various sections of `pyproject.toml`:
111
+
112
+ - `dependencies` list from `[project]` section
113
+ - dependency lists from `[project.optional-dependencies]` section
114
+ - dependency lists from `[dependency-groups]` section
115
+
116
+ #### Which dependency specifiers will be updated?
117
+
118
+ - will only update dependency specifiers with version identifier
119
+ containing comparison operator: `==`, `===`, `~=`, `>`, `>=`
120
+ - example:
121
+ - `foo==1.0.0`
122
+ - `foo~=1.0`
123
+ - `foo>=1`
124
+ - will not update dependency specifiers with version identifier
125
+ containing comparison operator: `<`, `<=`, `!=`
126
+ - example:
127
+ - `foo<2.0`
128
+ - `foo>=1,<2`
129
+ - `foo > 1.0, != 1.0.1`
130
+ - will not update unversioned dependency specifiers
131
+ - example:
132
+ - `foo`
133
+ - `foo[bar]`
134
+ - will not update direct reference dependency specifiers
135
+ - example:
136
+ - `foo @ https://github.com/foo/foo/archive/1.0.0.zip`
137
+ - `foo @ file:///builds/foo-1.0.0-py3-none-any.whl`
138
+
139
+ #### Supported comparison operators in version identifiers:
140
+
141
+ - `==` : version matching
142
+ - `===` : arbitrary equality
143
+ - `~=` : compatible release
144
+ - `>` : exclusive ordered comparison
145
+ - `>=` : inclusive ordered comparison
146
+
147
+ #### Unsupported comparison operators in version identifiers:
148
+
149
+ - `<` : exclusive ordered comparison
150
+ - `<=` : inclusive ordered comparison
151
+ - `!=` : version exclusion
152
+
153
+
154
+ [github-home]: https://github.com/cgoldberg
155
+ [github-repo]: https://github.com/cgoldberg/bump-dependencies
156
+ [pypi-home]: https://pypi.org
157
+ [pypi-bump-dependencies]: https://pypi.org/project/bump-dependencies
158
+ [mit-license]: https://raw.githubusercontent.com/cgoldberg/bump-dependencies/refs/heads/master/LICENSE
159
+ [pep-440]: https://peps.python.org/pep-0440
160
+ [pep-508]: https://peps.python.org/pep-0508
161
+ [pep-735]: https://peps.python.org/pep-0735
162
+ [pypa-version-specifiers]: https://packaging.python.org/en/latest/specifications/version-specifiers
163
+ [pypa-dependency-specifiers]: https://packaging.python.org/en/latest/specifications/dependency-specifiers
164
+ [pypa-dependency-groups]: https://packaging.python.org/en/latest/specifications/dependency-groups
165
+ [pypa-pyproject-dependencies]: https://packaging.python.org/en/latest/specifications/pyproject-toml/#dependencies-optional-dependencies
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/bump_dependencies.py
5
+ src/test_bump_dependencies.py
6
+ src/bump_dependencies.egg-info/PKG-INFO
7
+ src/bump_dependencies.egg-info/SOURCES.txt
8
+ src/bump_dependencies.egg-info/dependency_links.txt
9
+ src/bump_dependencies.egg-info/entry_points.txt
10
+ src/bump_dependencies.egg-info/requires.txt
11
+ src/bump_dependencies.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ bump_dependencies = bump_dependencies:main
@@ -0,0 +1,5 @@
1
+ packaging==25.0
2
+ requests==2.32.4
3
+ rich==14.0.0
4
+ tomlkit==0.13.3
5
+ validate-pyproject==0.24.1
@@ -0,0 +1,2 @@
1
+ bump_dependencies
2
+ test_bump_dependencies
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env python
2
+ # Corey Goldberg, 2025
3
+ # License: MIT
4
+
5
+ """Bump Python package dependencies in pyproject.toml"""
6
+
7
+ import argparse
8
+ import os
9
+ import re
10
+
11
+ import requests
12
+ import tomlkit
13
+ from rich.console import Console
14
+ from validate_pyproject import api as validate_pyproject_api
15
+ from validate_pyproject.errors import ValidationError
16
+
17
+
18
+ def get_dependency_name_and_operator(dependency_specifier):
19
+ illegal_chars = ("/", ":", "@")
20
+ if any(char in dependency_specifier for char in illegal_chars):
21
+ raise ValueError("can't handle direct reference dependency specifiers")
22
+ if ";" in dependency_specifier:
23
+ dependency_specifier = dependency_specifier.split(";")[0]
24
+ invalid_operators = ("!=", "<=", "<")
25
+ for op in invalid_operators:
26
+ if op in dependency_specifier:
27
+ raise ValueError(f"skipping unsupported '{op}' version identifier")
28
+ valid_operators = ("===", "==", "~=", ">=", ">")
29
+ operators = re.findall("|".join(valid_operators), dependency_specifier)
30
+ if not operators:
31
+ raise ValueError("no version specified")
32
+ elif len(operators) != 1:
33
+ raise ValueError("can't handle complex dependency specifiers")
34
+ operator = operators[0]
35
+ dependency_name = dependency_specifier.replace(" ", "").split(operator)[0].strip()
36
+ return dependency_name, operator
37
+
38
+
39
+ def get_dependencies_groups(pyproject_data):
40
+ """Map each dependency group name to a list of dependency specifiers
41
+
42
+ This includes:
43
+ - `dependencies` list from `[project]` section
44
+ - dependency lists from `[project.optional-dependencies]` section
45
+ - dependency lists from `[dependency-groups]` section
46
+ """
47
+ groups = {}
48
+ project_dependencies = list(pyproject_data["project"].get("dependencies", []))
49
+ if project_dependencies:
50
+ groups.update({"project": project_dependencies})
51
+ optional_dependencies = dict(pyproject_data["project"].get("optional-dependencies", {}))
52
+ if optional_dependencies:
53
+ groups.update({"optional_dependencies": optional_dependencies})
54
+ dependency_groups = dict(pyproject_data.get("dependency-groups", {}))
55
+ if dependency_groups:
56
+ groups.update({"dependency_groups": dependency_groups})
57
+ if not groups:
58
+ raise ValueError("no dependencies found")
59
+ return groups
60
+
61
+
62
+ def update_dependency(dependency_specifier):
63
+ dependency_name, operator = get_dependency_name_and_operator(dependency_specifier)
64
+ new_dependency_version = fetch_latest_package_version(get_package_base_name(dependency_name))
65
+ updated_dependency_specifier = None
66
+ if new_dependency_version is not None:
67
+ if ";" in dependency_specifier:
68
+ after_semi = "".join(dependency_specifier.split(";")[1:])
69
+ updated_dependency_specifier = f"{dependency_name}{operator}{new_dependency_version};{after_semi}"
70
+ else:
71
+ updated_dependency_specifier = f"{dependency_name}{operator}{new_dependency_version}"
72
+ return updated_dependency_specifier
73
+
74
+
75
+ def update_dependencies(dependency_specifiers):
76
+ updated_dependency_specifiers = []
77
+ for dependency_specifier in dependency_specifiers:
78
+ if isinstance(dependency_specifier, tomlkit.items.InlineTable):
79
+ print(f"- skipping inline table: '{dependency_specifier}'")
80
+ updated_dependency_specifiers.append(dependency_specifier)
81
+ continue
82
+ try:
83
+ get_dependency_name_and_operator(dependency_specifier)
84
+ except ValueError as e:
85
+ print(f"- not updating: '{dependency_specifier}' ({e})")
86
+ updated_dependency_specifiers.append(dependency_specifier)
87
+ continue
88
+ updated_dependency_specifier = update_dependency(dependency_specifier)
89
+ if updated_dependency_specifier is not None:
90
+ if dependency_specifier != updated_dependency_specifier:
91
+ print(f"- updating: '{dependency_specifier}' to '{updated_dependency_specifier}'")
92
+ updated_dependency_specifiers.append(updated_dependency_specifier)
93
+ else:
94
+ print(f"- not updating: '{dependency_specifier}' (no new version available)")
95
+ updated_dependency_specifiers.append(dependency_specifier)
96
+ else:
97
+ print(f"- not updating: '{dependency_specifier}' (error retrieving version from pypi.org)")
98
+ updated_dependency_specifiers.append(dependency_specifier)
99
+ return updated_dependency_specifiers
100
+
101
+
102
+ def get_package_base_name(package_name):
103
+ match = re.match(r"^(.*?)\[", package_name)
104
+ if match:
105
+ return match.group(1).strip()
106
+ return package_name.strip()
107
+
108
+
109
+ def fetch_latest_package_version(package_name):
110
+ url = f"https://pypi.org/pypi/{package_name}/json"
111
+ try:
112
+ response = requests.get(url)
113
+ except requests.exceptions.ConnectionError:
114
+ print("error connecting to pypi.org")
115
+ return None
116
+ try:
117
+ response.raise_for_status() # raise an exception for bad status codes
118
+ except requests.exceptions.HTTPError:
119
+ return None
120
+ return response.json()["info"]["version"]
121
+
122
+
123
+ def run(pyproject_toml_path, dry_run):
124
+ console = Console()
125
+ with console.status(""):
126
+ print(f"loading: {pyproject_toml_path}")
127
+ try:
128
+ with open(pyproject_toml_path) as f:
129
+ pyproject_data = tomlkit.load(f)
130
+ except FileNotFoundError:
131
+ exit("\nno pyproject.toml found")
132
+ except Exception as e:
133
+ exit(f"\ninvalid pyproject.toml: {e}")
134
+ print(f"validating: {os.path.basename(pyproject_toml_path)}\n")
135
+ validator = validate_pyproject_api.Validator()
136
+ try:
137
+ validator(pyproject_data)
138
+ except ValidationError as e:
139
+ exit(f"invalid pyproject.toml: {e.message}")
140
+ try:
141
+ dependencies_groups_map = get_dependencies_groups(pyproject_data)
142
+ except ValueError as e:
143
+ exit(e)
144
+
145
+ for key, value in dependencies_groups_map.items():
146
+ if key == "project":
147
+ pyproject_data["project"]["dependencies"] = update_dependencies(value)
148
+ if key == "optional_dependencies":
149
+ pyproject_data["project"]["optional-dependencies"] = {
150
+ dependency_group: update_dependencies(dependency_specifiers)
151
+ for dependency_group, dependency_specifiers in value.items()
152
+ }
153
+ if key == "dependency_groups":
154
+ pyproject_data["dependency-groups"] = {
155
+ dependency_group: update_dependencies(dependency_specifiers)
156
+ for dependency_group, dependency_specifiers in value.items()
157
+ }
158
+
159
+ if dry_run:
160
+ print("\nnot writing new pyproject.toml with updated dependencies")
161
+ else:
162
+ with open(pyproject_toml_path, "w") as f:
163
+ tomlkit.dump(pyproject_data, f)
164
+ print("\ngenerated new pyproject.toml with updated dependencies")
165
+
166
+
167
+ def main():
168
+ parser = argparse.ArgumentParser()
169
+ parser.add_argument(
170
+ "--dry-run",
171
+ action="store_true",
172
+ default=False,
173
+ dest="dry_run",
174
+ help="don't write changes to pyproject.toml",
175
+ )
176
+ parser.add_argument(
177
+ "--path",
178
+ default=os.path.join(os.getcwd(), "pyproject.toml"),
179
+ help="path to pyproject.toml (defaults to current directory)",
180
+ )
181
+ args = parser.parse_args()
182
+ run(args.path, args.dry_run)
183
+
184
+
185
+ if __name__ == "__main__":
186
+ main()
@@ -0,0 +1,171 @@
1
+ # Corey Goldberg, 2025
2
+ # License: MIT
3
+
4
+ """Tests for bump_dependencies"""
5
+
6
+ import pytest
7
+
8
+ import bump_dependencies as bd
9
+
10
+
11
+ @pytest.fixture(
12
+ params=[
13
+ ("foo==1.0.0", "foo"),
14
+ ("foo~=1.0", "foo"),
15
+ ("foo===1.0.0", "foo"),
16
+ ("foo==1.0.*", "foo"),
17
+ ("foo==1.0.1dev0", "foo"),
18
+ ("foo~=1.1a1", "foo"),
19
+ ("foo==1.1.*", "foo"),
20
+ ("foo>1", "foo"),
21
+ ("foo>=1.0", "foo"),
22
+ ("foo[bar] == 2012.4", "foo[bar]"),
23
+ ("foo==1.0.post2.dev3", "foo"),
24
+ ("foo[bar] >= 1.0dev1", "foo[bar]"),
25
+ ("foo>1.0; python_version < '4.0'", "foo"),
26
+ ("foo[bar]>=1.0", "foo[bar]"),
27
+ ("foo[bar,baz]==1.0.0", "foo[bar,baz]"),
28
+ ("foo[ bar, baz ] ~= 1.0.0", "foo[bar,baz]"),
29
+ ("foo > 1.0", "foo"),
30
+ ("foo[bar] == 1.0", "foo[bar]"),
31
+ ("foo== 1.0", "foo"),
32
+ ("foo ==1.0", "foo"),
33
+ ("foo == 1.0", "foo"),
34
+ (" foo==1.0 ", "foo"),
35
+ (" foo > 1.0 ", "foo"),
36
+ ("foo==1.0 ; python_version < '4.0'", "foo"),
37
+ ("foo~=1.0.0;python_version>'2.7'", "foo"),
38
+ ("foo[bar, baz, qux]==1.0.0;python_version>'2.7'", "foo[bar,baz,qux]"),
39
+ ("foo == 1.0; os_name=='a' or os_name=='b'", "foo"),
40
+ ]
41
+ )
42
+ def valid_specifier_name(request):
43
+ return request.param
44
+
45
+
46
+ @pytest.fixture(
47
+ params=[
48
+ "foo<1.0",
49
+ "foo<=1.0",
50
+ " foo <= 1.0.0 ",
51
+ "foo!=1.0",
52
+ "foo==1!1.0foo>=1,<2foo >= 1.0.1, <= 2.0.*",
53
+ "foo>1.0.0,<2.0.0",
54
+ "foo <=2.0, != 1.0.1",
55
+ "foo~=1.0.0,!=1.0.1foo ~=1.0.0, != 1.0.1foo>=1.0,<2.0,!=1.5.7",
56
+ ]
57
+ )
58
+ def unsupported_specifier(request):
59
+ return request.param
60
+
61
+
62
+ @pytest.fixture(
63
+ params=[
64
+ "foo",
65
+ "foo-bar2",
66
+ " foo ",
67
+ "foo[bar]",
68
+ "foo [bar,baz]",
69
+ "foo[bar, baz, qux] ;platform_version=='2'",
70
+ "foo; os_name=='a' or os_name=='b'",
71
+ ]
72
+ )
73
+ def unversioned_specifier(request):
74
+ return request.param
75
+
76
+
77
+ @pytest.fixture(
78
+ params=[
79
+ "foo >= 1.0.1, == 1.0.*",
80
+ "foo [bar,baz] >= 2.8.1, == 2.8.* ; python_version < '4.0'",
81
+ ]
82
+ )
83
+ def complex_specifier(request):
84
+ return request.param
85
+
86
+
87
+ @pytest.fixture(
88
+ params=[
89
+ "foo@http://foo.com",
90
+ "foo @ http://foo.com ; python_version=='2.7'",
91
+ "foo @ https://github.com/foo/foo/archive/1.0.0.zip",
92
+ "foo @ file:///builds/foo-1.0.0-py3-none-any.whl`",
93
+ ]
94
+ )
95
+ def direct_reference_specifier(request):
96
+ return request.param
97
+
98
+
99
+ @pytest.fixture(
100
+ params=[
101
+ "foo",
102
+ " foo ",
103
+ " foo",
104
+ "foo[",
105
+ "foo [",
106
+ "foo[bar]",
107
+ "foo[ bar ]",
108
+ "foo [bar]",
109
+ "foo[bar,baz]",
110
+ "foo[bar, baz]",
111
+ "foo [ bar , baz ]",
112
+ ]
113
+ )
114
+ def package_name(request):
115
+ return request.param
116
+
117
+
118
+ def test_name_and_operator(valid_specifier_name):
119
+ dependency_specifier, name = valid_specifier_name
120
+ valid_operators = ("===", "==", "~=", ">=", ">")
121
+ dependency_name, operator = bd.get_dependency_name_and_operator(dependency_specifier)
122
+ assert isinstance(operator, str)
123
+ assert operator in valid_operators
124
+ assert isinstance(dependency_name, str)
125
+ assert dependency_name == name
126
+
127
+
128
+ def test_name_and_operator_with_unsupported_operator(unsupported_specifier):
129
+ with pytest.raises(ValueError, match="skipping unsupported '.*' version identifier"):
130
+ bd.get_dependency_name_and_operator(unsupported_specifier)
131
+
132
+
133
+ def test_name_and_operator_with_unversioned_specifier(unversioned_specifier):
134
+ with pytest.raises(ValueError, match="no version specified"):
135
+ bd.get_dependency_name_and_operator(unversioned_specifier)
136
+
137
+
138
+ def test_name_and_operator_with_complex_specifier(complex_specifier):
139
+ with pytest.raises(ValueError, match="can't handle complex dependency specifiers"):
140
+ bd.get_dependency_name_and_operator(complex_specifier)
141
+
142
+
143
+ def test_name_and_operator_with_direct_reference_specifier(direct_reference_specifier):
144
+ with pytest.raises(ValueError, match="can't handle direct reference dependency specifiers"):
145
+ bd.get_dependency_name_and_operator(direct_reference_specifier)
146
+
147
+
148
+ def test_update_dependency(valid_specifier_name):
149
+ dependency_specifier, name = valid_specifier_name
150
+ dependency_name, operator = bd.get_dependency_name_and_operator(dependency_specifier)
151
+ updated_dependency_specifier = bd.update_dependency(dependency_specifier)
152
+ assert isinstance(updated_dependency_specifier, str)
153
+ assert operator in updated_dependency_specifier
154
+ assert dependency_specifier not in updated_dependency_specifier
155
+ assert name in updated_dependency_specifier
156
+
157
+
158
+ def test_fetch_latest_package_version():
159
+ version = bd.fetch_latest_package_version("requests")
160
+ assert isinstance(version, str)
161
+ assert version[0].isdigit()
162
+
163
+
164
+ def test_fetch_unavailable_package_version():
165
+ version = bd.fetch_latest_package_version("definitely-not-a-package-found-on-pypi-1234")
166
+ assert version is None
167
+
168
+
169
+ def test_package_base_name(package_name):
170
+ base_name = bd.get_package_base_name(package_name)
171
+ assert base_name == "foo"