python-update-checker 0.9.0__tar.gz → 0.11.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.
Files changed (25) hide show
  1. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/PKG-INFO +4 -3
  2. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/README.md +3 -2
  3. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/pyproject.toml +1 -1
  4. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/pyproject.toml.orig +1 -1
  5. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/src/puc/__init__.py +1 -1
  6. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/src/puc/cli.py +15 -0
  7. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/src/puc/pyprojecttoml.py +9 -0
  8. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/src/puc/requirementstxt.py +7 -0
  9. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/src/puc/uvlock.py +14 -6
  10. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/data/pyproject.toml +2 -0
  11. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/data/requirements.txt +2 -0
  12. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/data/uv.lock +15 -0
  13. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/test_pyproject_toml.py +20 -2
  14. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/test_uv_lock.py +23 -4
  15. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/.gitignore +0 -0
  16. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/.ruff.toml +0 -0
  17. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/Makefile +0 -0
  18. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/scripts/install_dev.sh +0 -0
  19. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/src/puc/dependencies.py +0 -0
  20. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/src/puc/logging.py +0 -0
  21. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/__init__.py +0 -0
  22. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/data/other-requirements.txt +0 -0
  23. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/data/pyproject_compatible.toml +0 -0
  24. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/test_latest.py +0 -0
  25. {python_update_checker-0.9.0 → python_update_checker-0.11.0}/tests/test_requirements_txt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-update-checker
3
- Version: 0.9.0
3
+ Version: 0.11.0
4
4
  License-Expression: GPL-3.0-only
5
5
  Classifier: Development Status :: 4 - Beta
6
6
  Classifier: Environment :: Console
@@ -46,8 +46,9 @@ about different pinning strategies.
46
46
  ## Quickstart
47
47
 
48
48
  ```bash
49
-
50
- uvx --from python-update-checker puc --exclude-newer "1 day" update pyproject.toml
49
+ # update dependencies in pyproject.toml to the latest version
50
+ uvx --from python-update-checker puc --exclude-newer="1 day" update pyproject.toml
51
+ # install updated dependencies in virtual environment
51
52
  uv sync
52
53
  ```
53
54
 
@@ -28,8 +28,9 @@ about different pinning strategies.
28
28
  ## Quickstart
29
29
 
30
30
  ```bash
31
-
32
- uvx --from python-update-checker puc --exclude-newer "1 day" update pyproject.toml
31
+ # update dependencies in pyproject.toml to the latest version
32
+ uvx --from python-update-checker puc --exclude-newer="1 day" update pyproject.toml
33
+ # install updated dependencies in virtual environment
33
34
  uv sync
34
35
  ```
35
36
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-update-checker"
3
- version = "0.9.0"
3
+ version = "0.11.0"
4
4
  readme = "README.md"
5
5
  requires-python = ">=3.11"
6
6
  license = "GPL-3.0-only"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-update-checker"
3
- version = "0.9.0"
3
+ version = "0.11.0"
4
4
  readme = "README.md"
5
5
  requires-python = ">=3.11"
6
6
  license = "GPL-3.0-only"
@@ -2,4 +2,4 @@
2
2
  # Copyright: GPL-v3
3
3
  """module file"""
4
4
 
5
- __version__ = "0.9.0"
5
+ __version__ = "0.11.0"
@@ -70,6 +70,12 @@ def get_option_parser() -> argparse.ArgumentParser:
70
70
  dest="exclude_newer_package",
71
71
  help="Limit candidate packages for specific packages to those that were uploaded prior to the given date. Accepts package-date pairs in the format PACKAGE=DATE.",
72
72
  )
73
+ parser.add_argument(
74
+ "--exclude-package",
75
+ dest="exclude_packages",
76
+ action="append",
77
+ help="Ignore given package. Can be used multiple times.",
78
+ )
73
79
  parser.add_argument(
74
80
  "--constraints",
75
81
  dest="constraints",
@@ -140,6 +146,12 @@ def handle_dependency_file(dep_file: str, optargs, constraint_file):
140
146
  packages = [canonicalize_name(name) for name in optargs.packages]
141
147
  else:
142
148
  packages = None
149
+ if optargs.exclude_packages:
150
+ exclude_packages = [
151
+ canonicalize_name(name) for name in optargs.exclude_packages
152
+ ]
153
+ else:
154
+ exclude_packages = None
143
155
  if dep_file_normalized == "pyproject.toml":
144
156
  # pyproject.toml format
145
157
  updatable = handle_pyproject_toml(
@@ -148,6 +160,7 @@ def handle_dependency_file(dep_file: str, optargs, constraint_file):
148
160
  command=optargs.command,
149
161
  exclude_newer=optargs.exclude_newer,
150
162
  exclude_newer_package=optargs.exclude_newer_package,
163
+ exclude_packages=exclude_packages,
151
164
  constraint_file=constraint_file,
152
165
  color=optargs.color,
153
166
  )
@@ -159,6 +172,7 @@ def handle_dependency_file(dep_file: str, optargs, constraint_file):
159
172
  command=optargs.command,
160
173
  exclude_newer=optargs.exclude_newer,
161
174
  exclude_newer_package=optargs.exclude_newer_package,
175
+ exclude_packages=exclude_packages,
162
176
  constraint_file=constraint_file,
163
177
  color=optargs.color,
164
178
  )
@@ -170,6 +184,7 @@ def handle_dependency_file(dep_file: str, optargs, constraint_file):
170
184
  command=optargs.command,
171
185
  exclude_newer=optargs.exclude_newer,
172
186
  exclude_newer_package=optargs.exclude_newer_package,
187
+ exclude_packages=exclude_packages,
173
188
  constraint_file=constraint_file,
174
189
  color=optargs.color,
175
190
  )
@@ -25,6 +25,7 @@ def handle_pyproject_toml(
25
25
  packages=None,
26
26
  exclude_newer: str | None = None,
27
27
  exclude_newer_package: str | None = None,
28
+ exclude_packages=None,
28
29
  constraint_file: str | None = None,
29
30
  color: bool = True,
30
31
  ) -> int:
@@ -57,6 +58,7 @@ def handle_pyproject_toml(
57
58
  packages=packages,
58
59
  exclude_newer=exclude_newer,
59
60
  exclude_newer_package=exclude_newer_package,
61
+ exclude_packages=exclude_packages,
60
62
  constraint_file=constraint_file,
61
63
  color=color,
62
64
  )
@@ -72,6 +74,7 @@ def handle_pyproject_toml(
72
74
  packages=packages,
73
75
  exclude_newer=exclude_newer,
74
76
  exclude_newer_package=exclude_newer_package,
77
+ exclude_packages=exclude_packages,
75
78
  constraint_file=constraint_file,
76
79
  color=color,
77
80
  )
@@ -86,6 +89,7 @@ def handle_pyproject_toml(
86
89
  packages=packages,
87
90
  exclude_newer=exclude_newer,
88
91
  exclude_newer_package=exclude_newer_package,
92
+ exclude_packages=exclude_packages,
89
93
  constraint_file=constraint_file,
90
94
  color=color,
91
95
  )
@@ -104,6 +108,7 @@ def update_pyproject_dependencies(
104
108
  packages=None,
105
109
  exclude_newer: str | None = None,
106
110
  exclude_newer_package: str | None = None,
111
+ exclude_packages=None,
107
112
  constraint_file: str | None = None,
108
113
  color: bool = True,
109
114
  ) -> int:
@@ -124,6 +129,10 @@ def update_pyproject_dependencies(
124
129
 
125
130
  # respect optional package filter
126
131
  if packages and canonicalize_name(pkg_req.name) not in packages:
132
+ logger.info(f"skip filtered package {pkg_req.name!r}")
133
+ continue
134
+ if exclude_packages and canonicalize_name(pkg_req.name) in exclude_packages:
135
+ logger.info(f"skip excluded package {pkg_req.name!r}")
127
136
  continue
128
137
  try:
129
138
  latest_version = get_latest_version(
@@ -28,6 +28,7 @@ def handle_requirements_txt(
28
28
  packages=None,
29
29
  exclude_newer: str | None = None,
30
30
  exclude_newer_package: str | None = None,
31
+ exclude_packages=None,
31
32
  constraint_file: str | None = None,
32
33
  color: bool = True,
33
34
  rec_level: int = 0,
@@ -65,6 +66,7 @@ def handle_requirements_txt(
65
66
  packages=packages,
66
67
  exclude_newer=exclude_newer,
67
68
  exclude_newer_package=exclude_newer_package,
69
+ exclude_packages=exclude_packages,
68
70
  constraint_file=constraint_file,
69
71
  color=color,
70
72
  rec_level=rec_level + 1,
@@ -90,6 +92,11 @@ def handle_requirements_txt(
90
92
  spec = next(s for s in pkg_req.specifier)
91
93
  if packages and canonicalize_name(pkg_req.name) not in packages:
92
94
  output.write(line)
95
+ elif (
96
+ exclude_packages
97
+ and canonicalize_name(pkg_req.name) in exclude_packages
98
+ ):
99
+ output.write(line)
93
100
  elif latest_version is not None and latest_version != spec.version:
94
101
  updatable += 1
95
102
  if not is_newer_version(spec.version, latest_version):
@@ -20,6 +20,7 @@ def handle_uv_lock(
20
20
  packages=None,
21
21
  exclude_newer: str | None = None,
22
22
  exclude_newer_package: str | None = None,
23
+ exclude_packages=None,
23
24
  constraint_file: str | None = None,
24
25
  color: bool = True,
25
26
  ) -> int:
@@ -51,17 +52,24 @@ def handle_uv_lock(
51
52
  continue
52
53
  # respect package filter
53
54
  if packages and canonicalize_name(name) not in packages:
54
- logger.info(f"skip package {name} due to package filter")
55
+ logger.info(f"skip filtered package {name!r}")
55
56
  continue
56
- # skip virtual packages (ie. the project itself)
57
+ if exclude_packages and canonicalize_name(name) in exclude_packages:
58
+ logger.info(f"skip excluded package {name!r}")
59
+ continue
60
+ # check package source for skip reasons
57
61
  source = uvpackage.get("source", {})
58
- # skip virtual packages (ie. the project itself)
59
62
  if "virtual" in source:
60
- logger.info(f"skip virtual package {name}")
63
+ # skip virtual packages (ie. the project itself)
64
+ logger.info(f"skip virtual package {name!r}")
61
65
  continue
62
- # skip editable packages
63
66
  if "editable" in source:
64
- logger.info(f"skip editable package {name}")
67
+ # skip editable packages
68
+ logger.info(f"skip editable package {name!r}")
69
+ continue
70
+ if "path" in source:
71
+ # skip local packages provided by file path
72
+ logger.info(f"skip path package {name!r}")
65
73
  continue
66
74
  updatable += update_uvlock_dependency(
67
75
  name,
@@ -9,6 +9,8 @@ dependencies = [
9
9
  "pywin32==310; os_name=='nt'",
10
10
  # arbitrary equality
11
11
  "certifi===2026.1.4",
12
+ # ignore this
13
+ "fragilicous==1.0",
12
14
 
13
15
  # unpinned
14
16
  "requests",
@@ -6,6 +6,8 @@ ruff ==0.15.9
6
6
  pywin32==310; os_name=='nt'
7
7
  # arbitrary equality
8
8
  certifi===2026.1.4
9
+ # ignore this
10
+ fragilicous==1.0
9
11
 
10
12
  # unpinned
11
13
  requests
@@ -60,3 +60,18 @@ source = { virtual = "." }
60
60
  name = "imabellend"
61
61
  version = "1.1.1"
62
62
  source = { editable = "." }
63
+
64
+ [[package]]
65
+ name = "fragilicous"
66
+ version = "0.0.29"
67
+ source = { registry = "https://pypi.org/simple" }
68
+ sdist = { url = "https://files.pythonhosted.org/packages/47/d5/853561de49fae38c519e905b2d8da9c531219608f1fccc47a0fc2c896980/ty-0.0.29.tar.gz", hash = "sha256:e7936cca2f691eeda631876c92809688dbbab68687c3473f526cd83b6a9228d8", size = 5469221, upload-time = "2026-04-05T15:01:21.328Z" }
69
+ wheels = [
70
+ { url = "https://files.pythonhosted.org/packages/2c/55/87280a994d6a2d2647c65e12abbc997ed49835794366153c04c4d9304d76/ty-0.0.29-py3-none-win_arm64.whl", hash = "sha256:f9794bbd1bb3ce13f78c191d0c89ae4c63f52c12b6daa0c6fe220b90d019d12c", size = 10428165, upload-time = "2026-04-05T15:01:34.665Z" },
71
+ ]
72
+
73
+ [[package]]
74
+ name = "superfragilicous"
75
+ version = "1"
76
+ source = { path = "third_party/superfragilicous-1.tar.gz" }
77
+ dependencies = [ ]
@@ -28,7 +28,15 @@ class PyprojectTomlTest(unittest.TestCase):
28
28
  def test_pyproject_check(self):
29
29
  """Run puc check"""
30
30
  filename = os.path.join(datadir, "pyproject.toml")
31
- cmd = ["uv", "run", "puc", "check", filename]
31
+ cmd = [
32
+ "uv",
33
+ "run",
34
+ "puc",
35
+ "--exclude-package",
36
+ "fragilicous",
37
+ "check",
38
+ filename,
39
+ ]
32
40
  result = subprocess.run(cmd, check=False, text=True, capture_output=True)
33
41
  output = result.stdout.strip()
34
42
  self.assertTrue(result.returncode > 0)
@@ -37,6 +45,7 @@ class PyprojectTomlTest(unittest.TestCase):
37
45
  self.assertIn("found update 'ruff ==", output)
38
46
  self.assertIn("found update 'tensorflow==", output)
39
47
  self.assertIn("found update 'certifi===", output)
48
+ self.assertIn("skip excluded package 'fragilicous'", output)
40
49
 
41
50
  @needs_program('uv')
42
51
  def test_pyproject_check_package(self):
@@ -72,7 +81,15 @@ class PyprojectTomlTest(unittest.TestCase):
72
81
  content = f.read()
73
82
  for dep in packagedeps:
74
83
  self.assertIn(dep, content)
75
- cmd = ["uv", "run", "puc", "update", filename]
84
+ cmd = [
85
+ "uv",
86
+ "run",
87
+ "puc",
88
+ "--exclude-package",
89
+ "fragilicous",
90
+ "update",
91
+ filename,
92
+ ]
76
93
  result = subprocess.run(cmd, check=True, text=True, capture_output=True)
77
94
  output = result.stdout.strip()
78
95
  self.assertIn("updating 'argcomplete==", output)
@@ -80,6 +97,7 @@ class PyprojectTomlTest(unittest.TestCase):
80
97
  self.assertIn("updating 'ruff ==", output)
81
98
  self.assertIn("updating 'tensorflow==", output)
82
99
  self.assertIn("updating 'certifi===", output)
100
+ self.assertIn("skip excluded package 'fragilicous'", output)
83
101
  # check that old package versions have been updated
84
102
  with open(filename) as f:
85
103
  content = f.read()
@@ -28,14 +28,24 @@ class UvLockTest(unittest.TestCase):
28
28
  def test_uvlock_check(self):
29
29
  """Run puc check"""
30
30
  filename = os.path.join(datadir, "uv.lock")
31
- cmd = ["uv", "run", "puc", "check", filename]
31
+ cmd = [
32
+ "uv",
33
+ "run",
34
+ "puc",
35
+ "--exclude-package",
36
+ "fragilicous",
37
+ "check",
38
+ filename,
39
+ ]
32
40
  result = subprocess.run(cmd, check=False, text=True, capture_output=True)
33
41
  output = result.stdout.strip()
34
42
  self.assertTrue(result.returncode > 0)
35
43
  self.assertIn("found update 'ty==", output)
36
44
  self.assertIn("found update 'ruff==", output)
37
- self.assertIn("skip virtual package imadoofus", output)
38
- self.assertIn("skip editable package imabellend", output)
45
+ self.assertIn("skip virtual package 'imadoofus'", output)
46
+ self.assertIn("skip editable package 'imabellend'", output)
47
+ self.assertIn("skip excluded package 'fragilicous'", output)
48
+ self.assertIn("skip path package 'superfragilicous'", output)
39
49
 
40
50
  @needs_program('uv')
41
51
  def test_uvlock_check_package(self):
@@ -59,10 +69,19 @@ class UvLockTest(unittest.TestCase):
59
69
  shutil.copy(projectfile, os.path.join(tmpdir, "pyproject.toml"))
60
70
  try:
61
71
  filename = os.path.join(tmpdir, "uv.lock")
62
- cmd = ["uv", "run", "puc", "update", filename]
72
+ cmd = [
73
+ "uv",
74
+ "run",
75
+ "puc",
76
+ "--exclude-package",
77
+ "fragilicous",
78
+ "update",
79
+ filename,
80
+ ]
63
81
  result = subprocess.run(cmd, check=True, text=True, capture_output=True)
64
82
  output = result.stdout.strip()
65
83
  self.assertIn("updating 'ty==", output)
66
84
  self.assertIn("updating 'ruff==", output)
85
+ self.assertIn("skip excluded package 'fragilicous'", output)
67
86
  finally:
68
87
  shutil.rmtree(tmpdir)