7373import os
7474import builtins
7575import _sitebuiltins
76+ import io
7677
7778# Prefixes for site-packages; add additional prefixes like /usr/local here
7879PREFIXES = [sys .prefix , sys .exec_prefix ]
8788USER_BASE = None
8889
8990
91+ def _trace (message ):
92+ if sys .flags .verbose :
93+ print (message , file = sys .stderr )
94+
95+
9096def makepath (* paths ):
9197 dir = os .path .join (* paths )
9298 try :
@@ -99,8 +105,15 @@ def makepath(*paths):
99105def abs_paths ():
100106 """Set all module __file__ and __cached__ attributes to an absolute path"""
101107 for m in set (sys .modules .values ()):
102- if (getattr (getattr (m , '__loader__' , None ), '__module__' , None ) not in
103- ('_frozen_importlib' , '_frozen_importlib_external' )):
108+ loader_module = None
109+ try :
110+ loader_module = m .__loader__ .__module__
111+ except AttributeError :
112+ try :
113+ loader_module = m .__spec__ .loader .__module__
114+ except AttributeError :
115+ pass
116+ if loader_module not in {'_frozen_importlib' , '_frozen_importlib_external' }:
104117 continue # don't mess with a PEP 302-supplied __file__
105118 try :
106119 m .__file__ = os .path .abspath (m .__file__ )
@@ -155,14 +168,19 @@ def addpackage(sitedir, name, known_paths):
155168 else :
156169 reset = False
157170 fullname = os .path .join (sitedir , name )
171+ _trace (f"Processing .pth file: { fullname !r} " )
158172 try :
159- f = open (fullname , "r" )
173+ # locale encoding is not ideal especially on Windows. But we have used
174+ # it for a long time. setuptools uses the locale encoding too.
175+ f = io .TextIOWrapper (io .open_code (fullname ), encoding = "locale" )
160176 except OSError :
161177 return
162178 with f :
163179 for n , line in enumerate (f ):
164180 if line .startswith ("#" ):
165181 continue
182+ if line .strip () == "" :
183+ continue
166184 try :
167185 if line .startswith (("import " , "import\t " )):
168186 exec (line )
@@ -189,6 +207,7 @@ def addpackage(sitedir, name, known_paths):
189207def addsitedir (sitedir , known_paths = None ):
190208 """Add 'sitedir' argument to sys.path if missing and handle .pth files in
191209 'sitedir'"""
210+ _trace (f"Adding directory: { sitedir !r} " )
192211 if known_paths is None :
193212 known_paths = _init_pathinfo ()
194213 reset = True
@@ -247,6 +266,10 @@ def _getuserbase():
247266 if env_base :
248267 return env_base
249268
269+ # Emscripten, VxWorks, and WASI have no home directories
270+ if sys .platform in {"emscripten" , "vxworks" , "wasi" }:
271+ return None
272+
250273 def joinuser (* args ):
251274 return os .path .expanduser (os .path .join (* args ))
252275
@@ -265,9 +288,9 @@ def joinuser(*args):
265288def _get_path (userbase ):
266289 version = sys .version_info
267290
268- # XXX RUSTPYTHON: we replace pythonx.y with rustpythonx.y
269291 if os .name == 'nt' :
270- return f'{ userbase } \\ RustPython{ version [0 ]} { version [1 ]} \\ site-packages'
292+ ver_nodot = sys .winver .replace ('.' , '' )
293+ return f'{ userbase } \\ RustPython{ ver_nodot } \\ site-packages'
271294
272295 if sys .platform == 'darwin' and sys ._framework :
273296 return f'{ userbase } /lib/rustpython/site-packages'
@@ -294,11 +317,14 @@ def getusersitepackages():
294317 If the global variable ``USER_SITE`` is not initialized yet, this
295318 function will also set it.
296319 """
297- global USER_SITE
320+ global USER_SITE , ENABLE_USER_SITE
298321 userbase = getuserbase () # this will also set USER_BASE
299322
300323 if USER_SITE is None :
301- USER_SITE = _get_path (userbase )
324+ if userbase is None :
325+ ENABLE_USER_SITE = False # disable user site and return None
326+ else :
327+ USER_SITE = _get_path (userbase )
302328
303329 return USER_SITE
304330
@@ -310,6 +336,7 @@ def addusersitepackages(known_paths):
310336 """
311337 # get the per user site-package path
312338 # this call will also make sure USER_BASE and USER_SITE are set
339+ _trace ("Processing user site-packages" )
313340 user_site = getusersitepackages ()
314341
315342 if ENABLE_USER_SITE and os .path .isdir (user_site ):
@@ -335,17 +362,23 @@ def getsitepackages(prefixes=None):
335362 seen .add (prefix )
336363
337364 if os .sep == '/' :
338- sitepackages .append (os .path .join (prefix , "lib" ,
339- # XXX changed for RustPython
340- "rustpython%d.%d" % sys .version_info [:2 ],
341- "site-packages" ))
365+ libdirs = [sys .platlibdir ]
366+ if sys .platlibdir != "lib" :
367+ libdirs .append ("lib" )
368+
369+ for libdir in libdirs :
370+ path = os .path .join (prefix , libdir ,
371+ "python%d.%d" % sys .version_info [:2 ],
372+ "site-packages" )
373+ sitepackages .append (path )
342374 else :
343375 sitepackages .append (prefix )
344- sitepackages .append (os .path .join (prefix , "lib " , "site-packages" ))
376+ sitepackages .append (os .path .join (prefix , "Lib " , "site-packages" ))
345377 return sitepackages
346378
347379def addsitepackages (known_paths , prefixes = None ):
348380 """Add site-packages to sys.path"""
381+ _trace ("Processing global site-packages" )
349382 for sitedir in getsitepackages (prefixes ):
350383 if os .path .isdir (sitedir ):
351384 addsitedir (sitedir , known_paths )
@@ -382,8 +415,10 @@ def setcopyright():
382415 files , dirs = [], []
383416 # Not all modules are required to have a __file__ attribute. See
384417 # PEP 420 for more details.
385- if hasattr (os , '__file__' ):
418+ here = getattr (sys , '_stdlib_dir' , None )
419+ if not here and hasattr (os , '__file__' ):
386420 here = os .path .dirname (os .__file__ )
421+ if here :
387422 files .extend (["LICENSE.txt" , "LICENSE" ])
388423 dirs .extend ([os .path .join (here , os .pardir ), here , os .curdir ])
389424 builtins .license = _sitebuiltins ._Printer (
@@ -441,7 +476,16 @@ def register_readline():
441476 readline .read_history_file (history )
442477 except OSError :
443478 pass
444- atexit .register (readline .write_history_file , history )
479+
480+ def write_history ():
481+ try :
482+ readline .write_history_file (history )
483+ except OSError :
484+ # bpo-19891, bpo-41193: Home directory does not exist
485+ # or is not writable, or the filesystem is read-only.
486+ pass
487+
488+ atexit .register (write_history )
445489
446490 sys .__interactivehook__ = register_readline
447491
@@ -450,7 +494,7 @@ def venv(known_paths):
450494
451495 env = os .environ
452496 if sys .platform == 'darwin' and '__PYVENV_LAUNCHER__' in env :
453- executable = os .environ ['__PYVENV_LAUNCHER__' ]
497+ executable = sys . _base_executable = os .environ ['__PYVENV_LAUNCHER__' ]
454498 else :
455499 executable = sys .executable
456500 exe_dir , _ = os .path .split (os .path .abspath (executable ))
@@ -582,7 +626,7 @@ def _script():
582626 Exit codes with --user-base or --user-site:
583627 0 - user site directory is enabled
584628 1 - user site directory is disabled by user
585- 2 - uses site directory is disabled by super user
629+ 2 - user site directory is disabled by super user
586630 or for security reasons
587631 >2 - unknown error
588632 """
@@ -594,11 +638,14 @@ def _script():
594638 for dir in sys .path :
595639 print (" %r," % (dir ,))
596640 print ("]" )
597- print ("USER_BASE: %r (%s)" % (user_base ,
598- "exists" if os .path .isdir (user_base ) else "doesn't exist" ))
599- print ("USER_SITE: %r (%s)" % (user_site ,
600- "exists" if os .path .isdir (user_site ) else "doesn't exist" ))
601- print ("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE )
641+ def exists (path ):
642+ if path is not None and os .path .isdir (path ):
643+ return "exists"
644+ else :
645+ return "doesn't exist"
646+ print (f"USER_BASE: { user_base !r} ({ exists (user_base )} )" )
647+ print (f"USER_SITE: { user_site !r} ({ exists (user_site )} )" )
648+ print (f"ENABLE_USER_SITE: { ENABLE_USER_SITE !r} " )
602649 sys .exit (0 )
603650
604651 buffer = []
0 commit comments