pipu-cli 0.1.dev4__py3-none-any.whl → 0.1.dev6__py3-none-any.whl
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.
- pipu_cli/__init__.py +1 -1
- pipu_cli/cli.py +59 -20
- pipu_cli/internals.py +4 -4
- pipu_cli/ui/modal_dialogs.py +7 -13
- {pipu_cli-0.1.dev4.dist-info → pipu_cli-0.1.dev6.dist-info}/METADATA +1 -1
- {pipu_cli-0.1.dev4.dist-info → pipu_cli-0.1.dev6.dist-info}/RECORD +10 -10
- {pipu_cli-0.1.dev4.dist-info → pipu_cli-0.1.dev6.dist-info}/WHEEL +0 -0
- {pipu_cli-0.1.dev4.dist-info → pipu_cli-0.1.dev6.dist-info}/entry_points.txt +0 -0
- {pipu_cli-0.1.dev4.dist-info → pipu_cli-0.1.dev6.dist-info}/licenses/LICENSE +0 -0
- {pipu_cli-0.1.dev4.dist-info → pipu_cli-0.1.dev6.dist-info}/top_level.txt +0 -0
pipu_cli/__init__.py
CHANGED
pipu_cli/cli.py
CHANGED
|
@@ -7,16 +7,63 @@ from .common import console
|
|
|
7
7
|
from pip._internal.commands.install import InstallCommand
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def _install_packages(
|
|
10
|
+
def _install_packages(package_names: List[str], packages_being_updated: List[str] = None) -> int:
|
|
11
11
|
"""
|
|
12
|
-
Install packages using pip API.
|
|
12
|
+
Install packages using pip API with filtered constraints.
|
|
13
13
|
|
|
14
|
-
:param
|
|
14
|
+
:param package_names: List of package names to install
|
|
15
|
+
:param packages_being_updated: List of package names being updated (to exclude from constraints)
|
|
15
16
|
:returns: Exit code (0 for success, non-zero for failure)
|
|
16
17
|
"""
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
import tempfile
|
|
19
|
+
import os
|
|
20
|
+
from packaging.utils import canonicalize_name
|
|
21
|
+
|
|
22
|
+
# If packages_being_updated not provided, use package_names
|
|
23
|
+
if packages_being_updated is None:
|
|
24
|
+
packages_being_updated = package_names
|
|
25
|
+
|
|
26
|
+
# Get all current constraints and filter out packages being updated
|
|
27
|
+
from .package_constraints import read_constraints
|
|
28
|
+
all_constraints = read_constraints()
|
|
29
|
+
|
|
30
|
+
# Get canonical names of packages being updated
|
|
31
|
+
packages_being_updated_canonical = {canonicalize_name(pkg) for pkg in packages_being_updated}
|
|
32
|
+
|
|
33
|
+
# Filter out constraints for packages being updated to avoid conflicts
|
|
34
|
+
filtered_constraints = {
|
|
35
|
+
pkg: constraint
|
|
36
|
+
for pkg, constraint in all_constraints.items()
|
|
37
|
+
if pkg not in packages_being_updated_canonical
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Create a temporary constraints file if there are any constraints to apply
|
|
41
|
+
constraint_file_path = None
|
|
42
|
+
try:
|
|
43
|
+
if filtered_constraints:
|
|
44
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
|
|
45
|
+
constraint_file_path = f.name
|
|
46
|
+
for pkg, constraint in filtered_constraints.items():
|
|
47
|
+
f.write(f"{pkg}{constraint}\n")
|
|
48
|
+
|
|
49
|
+
# Set environment variable for pip to use the filtered constraints
|
|
50
|
+
os.environ['PIP_CONSTRAINT'] = constraint_file_path
|
|
51
|
+
console.print(f"[dim]Using filtered constraints (excluding {len(packages_being_updated_canonical)} package(s) being updated)[/dim]")
|
|
52
|
+
|
|
53
|
+
install_cmd = InstallCommand("install", "Install packages")
|
|
54
|
+
install_args = ["--upgrade"] + package_names
|
|
55
|
+
return install_cmd.main(install_args)
|
|
56
|
+
|
|
57
|
+
finally:
|
|
58
|
+
# Clean up: remove the constraint file and unset environment variable
|
|
59
|
+
if constraint_file_path:
|
|
60
|
+
if 'PIP_CONSTRAINT' in os.environ:
|
|
61
|
+
del os.environ['PIP_CONSTRAINT']
|
|
62
|
+
if os.path.exists(constraint_file_path):
|
|
63
|
+
try:
|
|
64
|
+
os.unlink(constraint_file_path)
|
|
65
|
+
except Exception:
|
|
66
|
+
pass # Best effort cleanup
|
|
20
67
|
|
|
21
68
|
|
|
22
69
|
def launch_tui() -> None:
|
|
@@ -202,21 +249,13 @@ def update(pre, yes):
|
|
|
202
249
|
console.print()
|
|
203
250
|
console.print("[bold green]Installing updates...[/bold green]")
|
|
204
251
|
|
|
205
|
-
# Create list of package
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
constraint = package.get('constraint')
|
|
210
|
-
if constraint:
|
|
211
|
-
# Apply the constraint instead of pinning to latest version
|
|
212
|
-
spec = f"{package['name']}{constraint}"
|
|
213
|
-
else:
|
|
214
|
-
# No constraint, use latest version
|
|
215
|
-
spec = f"{package['name']}=={package['latest_version']}"
|
|
216
|
-
package_specs.append(spec)
|
|
252
|
+
# Create list of package names to install
|
|
253
|
+
# Use --upgrade without version pinning to allow pip's dependency resolver
|
|
254
|
+
# to handle interdependent packages (e.g., pydantic and pydantic-core)
|
|
255
|
+
package_names = [package['name'] for package in packages_to_update]
|
|
217
256
|
|
|
218
|
-
# Install packages using pip API
|
|
219
|
-
exit_code = _install_packages(
|
|
257
|
+
# Install packages using pip API with filtered constraints
|
|
258
|
+
exit_code = _install_packages(package_names, packages_being_updated=package_names)
|
|
220
259
|
|
|
221
260
|
if exit_code == 0:
|
|
222
261
|
console.print("[bold green]✓ All packages updated successfully![/bold green]")
|
pipu_cli/internals.py
CHANGED
|
@@ -787,10 +787,10 @@ def update_packages_preserving_editable(
|
|
|
787
787
|
|
|
788
788
|
if not is_editable:
|
|
789
789
|
# Regular package update
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
790
|
+
# Use --upgrade instead of pinning to specific versions to allow pip's
|
|
791
|
+
# dependency resolver to handle interdependent packages correctly
|
|
792
|
+
# (e.g., pydantic and pydantic-core, boto3 and botocore)
|
|
793
|
+
install_cmd = [sys.executable, "-m", "pip", "install", "--upgrade", package_name]
|
|
794
794
|
|
|
795
795
|
returncode, stdout, stderr = run_with_cancel(install_cmd, timeout=timeout)
|
|
796
796
|
|
pipu_cli/ui/modal_dialogs.py
CHANGED
|
@@ -1020,20 +1020,12 @@ class PackageUpdateScreen(ModalScreen[None]):
|
|
|
1020
1020
|
constraint_file.close()
|
|
1021
1021
|
self.app.call_from_thread(self._log_message, f"[dim]Using filtered constraints (excluding {len(packages_being_updated)} package(s) being updated)[/dim]")
|
|
1022
1022
|
|
|
1023
|
-
# Build list of package
|
|
1024
|
-
|
|
1023
|
+
# Build list of package names to update
|
|
1024
|
+
# Use --upgrade instead of pinning versions to avoid dependency conflicts
|
|
1025
|
+
# when updating interdependent packages (e.g., pydantic and pydantic-core)
|
|
1025
1026
|
package_names = []
|
|
1026
1027
|
for pkg in self.selected_packages:
|
|
1027
1028
|
package_names.append(pkg["name"])
|
|
1028
|
-
# Check if package has a constraint that should be applied instead of latest version
|
|
1029
|
-
constraint = pkg.get('constraint')
|
|
1030
|
-
if constraint:
|
|
1031
|
-
# Apply the constraint instead of pinning to latest version
|
|
1032
|
-
spec = f"{pkg['name']}{constraint}"
|
|
1033
|
-
else:
|
|
1034
|
-
# No constraint, use latest version
|
|
1035
|
-
spec = f"{pkg['name']}=={pkg['latest_version']}"
|
|
1036
|
-
package_specs.append(spec)
|
|
1037
1029
|
|
|
1038
1030
|
self.app.call_from_thread(self._update_status, f"Updating {total_packages} packages...")
|
|
1039
1031
|
self.app.call_from_thread(self._log_message, f"{'='*70}")
|
|
@@ -1042,8 +1034,10 @@ class PackageUpdateScreen(ModalScreen[None]):
|
|
|
1042
1034
|
self.app.call_from_thread(self._log_message, f" ... and {len(package_names) - 5} more")
|
|
1043
1035
|
self.app.call_from_thread(self._log_message, f"{'='*70}\n")
|
|
1044
1036
|
|
|
1045
|
-
# Prepare pip command to install all packages
|
|
1046
|
-
|
|
1037
|
+
# Prepare pip command to install all packages with --upgrade
|
|
1038
|
+
# This allows pip's dependency resolver to find compatible versions
|
|
1039
|
+
# for interdependent packages (e.g., pydantic requires specific pydantic-core)
|
|
1040
|
+
pip_cmd = [sys.executable, "-m", "pip", "install", "--upgrade"] + package_names
|
|
1047
1041
|
|
|
1048
1042
|
# Set up environment with constraint file if available
|
|
1049
1043
|
env = os.environ.copy()
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
pipu_cli/__init__.py,sha256=
|
|
2
|
-
pipu_cli/cli.py,sha256=
|
|
1
|
+
pipu_cli/__init__.py,sha256=6tnAKZMPjf830m0TO279lIHtF7_B5gnWQTiYCidkeYU,1190
|
|
2
|
+
pipu_cli/cli.py,sha256=4pZh9kh0JO8FRbDBewVUJWt8iQrEC5w4AylOghYWkd4,41838
|
|
3
3
|
pipu_cli/common.py,sha256=g5krfXFsvVJpOf87Vw4DGi5WIduDgMlRuONKXqO328M,78
|
|
4
4
|
pipu_cli/config.py,sha256=xsfNU4ORAujla_FGfsMKpxy7QTpd_bJhRF_u4IPKLW0,3635
|
|
5
|
-
pipu_cli/internals.py,sha256=
|
|
5
|
+
pipu_cli/internals.py,sha256=m_aF-yrOT5UJt54vv6X2gEukgokFXkz0m9SAKRofir0,35101
|
|
6
6
|
pipu_cli/package_constraints.py,sha256=6LSFlC93HNIFym7dYkfYn0fsOic6QDe1ADyghK94Pk8,93052
|
|
7
7
|
pipu_cli/thread_safe.py,sha256=zdQyCoMVJW73MC-d1pL_4ZO-K4AwkI0JeVyQsd8x7nY,7545
|
|
8
8
|
pipu_cli/utils.py,sha256=ijSHKVuKbjmRbj2RwD9S1606PeY4oDiutzhutpX25wM,5842
|
|
9
9
|
pipu_cli/ui/__init__.py,sha256=nCb_3G_vZXy5_Or9z9r-3XhYV1ppUR1r7nMZ9_6Srwg,1432
|
|
10
10
|
pipu_cli/ui/apps.py,sha256=ltH24sg-3nqVpoomgCwhVYuAwq3hBUwYRH60JXtV2Yg,59771
|
|
11
11
|
pipu_cli/ui/constants.py,sha256=HBPf4KYWHiT18c7ciQ0HeI7gZE3VIFOT0uobLU8YxQA,445
|
|
12
|
-
pipu_cli/ui/modal_dialogs.py,sha256
|
|
12
|
+
pipu_cli/ui/modal_dialogs.py,sha256=-Trh60n2mev6Pr-aIvetJHnXqqoJaVDmA3c8xH_xePM,47974
|
|
13
13
|
pipu_cli/ui/table_widgets.py,sha256=PC0CqqrK3KgMbTCYRPG01lxkEtRBz9xr9PN8EzoObz8,14322
|
|
14
|
-
pipu_cli-0.1.
|
|
15
|
-
pipu_cli-0.1.
|
|
16
|
-
pipu_cli-0.1.
|
|
17
|
-
pipu_cli-0.1.
|
|
18
|
-
pipu_cli-0.1.
|
|
19
|
-
pipu_cli-0.1.
|
|
14
|
+
pipu_cli-0.1.dev6.dist-info/licenses/LICENSE,sha256=q6TxVbSI0WMB9ulF2V0FWQfeA5om3d-T9X7QwuhdiYE,1075
|
|
15
|
+
pipu_cli-0.1.dev6.dist-info/METADATA,sha256=JqoGCM76nI14oiMrjwdvm2HjNRbVWQagOuxa_Q5ybsM,13200
|
|
16
|
+
pipu_cli-0.1.dev6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
+
pipu_cli-0.1.dev6.dist-info/entry_points.txt,sha256=VSv6od00zOPblnFPflNLaci4jBtQIgLYJjL1BKxLz_o,42
|
|
18
|
+
pipu_cli-0.1.dev6.dist-info/top_level.txt,sha256=z3Yce93-jGQjGRpsGZUZvbS8osh3OyS7MVpzG0uBE5M,9
|
|
19
|
+
pipu_cli-0.1.dev6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|