11import logging
22from pathlib import Path
33from typing import List
4+ import time
5+ import datetime
46
57from pipx .animate import animate
68from pipx .constants import DEFAULT_PYTHON , PIPX_SHARED_LIBS , WINDOWS
79from pipx .util import get_site_packages , get_venv_paths , run
810
11+ SHARED_LIBS_MAX_AGE_SEC = datetime .timedelta (days = 30 ).total_seconds ()
12+
913
1014class _SharedLibs :
1115 def __init__ (self ):
1216 self .root = PIPX_SHARED_LIBS
1317 self .bin_path , self .python_path = get_venv_paths (self .root )
18+ self .pip_path = self .bin_path / ("pip" if not WINDOWS else "pip.exe" )
1419 # i.e. bin_path is ~/.local/pipx/shared/bin
1520 # i.e. python_path is ~/.local/pipx/shared/python
1621 self ._site_packages = None
@@ -31,10 +36,23 @@ def create(self, pip_args: List[str], verbose: bool = False):
3136
3237 @property
3338 def is_valid (self ):
34- return (
35- self .python_path .is_file ()
36- and (self .bin_path / ("pip" if not WINDOWS else "pip.exe" )).is_file ()
39+ return self .python_path .is_file () and self .pip_path .is_file ()
40+
41+ @property
42+ def needs_upgrade (self ):
43+ if self .has_been_updated_this_run :
44+ return False
45+
46+ if not self .pip_path .is_file ():
47+ return True
48+
49+ now = time .time ()
50+ time_since_last_update_sec = now - self .pip_path .stat ().st_mtime
51+ logging .info (
52+ f"Time since last upgrade of shared libs, in seconds: { time_since_last_update_sec } . "
53+ f"Upgrade will be run by pipx if greater than { SHARED_LIBS_MAX_AGE_SEC } ."
3754 )
55+ return time_since_last_update_sec > SHARED_LIBS_MAX_AGE_SEC
3856
3957 def upgrade (self , pip_args : List [str ], verbose : bool = False ):
4058 # Don't try to upgrade multiple times per run
@@ -64,6 +82,8 @@ def upgrade(self, pip_args: List[str], verbose: bool = False):
6482 ]
6583 )
6684 self .has_been_updated_this_run = True
85+ self .pip_path .touch ()
86+
6787 except Exception :
6888 logging .error ("Failed to upgrade shared libraries" , exc_info = True )
6989
0 commit comments