@@ -103,8 +103,6 @@ def _venv_path(self, env_dir, name):
103103 vars = {
104104 'base' : env_dir ,
105105 'platbase' : env_dir ,
106- 'installed_base' : env_dir ,
107- 'installed_platbase' : env_dir ,
108106 }
109107 return sysconfig .get_path (name , scheme = 'venv' , vars = vars )
110108
@@ -175,9 +173,20 @@ def create_if_needed(d):
175173 context .python_dir = dirname
176174 context .python_exe = exename
177175 binpath = self ._venv_path (env_dir , 'scripts' )
178- incpath = self ._venv_path (env_dir , 'include' )
179176 libpath = self ._venv_path (env_dir , 'purelib' )
180177
178+ # PEP 405 says venvs should create a local include directory.
179+ # See https://peps.python.org/pep-0405/#include-files
180+ # XXX: This directory is not exposed in sysconfig or anywhere else, and
181+ # doesn't seem to be utilized by modern packaging tools. We keep it
182+ # for backwards-compatibility, and to follow the PEP, but I would
183+ # recommend against using it, as most tooling does not pass it to
184+ # compilers. Instead, until we standardize a site-specific include
185+ # directory, I would recommend installing headers as package data,
186+ # and providing some sort of API to get the include directories.
187+ # Example: https://numpy.org/doc/2.1/reference/generated/numpy.get_include.html
188+ incpath = os .path .join (env_dir , 'Include' if os .name == 'nt' else 'include' )
189+
181190 context .inc_path = incpath
182191 create_if_needed (incpath )
183192 context .lib_path = libpath
@@ -304,8 +313,11 @@ def setup_python(self, context):
304313 copier (context .executable , path )
305314 if not os .path .islink (path ):
306315 os .chmod (path , 0o755 )
307- for suffix in ('python' , 'python3' ,
308- f'python3.{ sys .version_info [1 ]} ' ):
316+
317+ suffixes = ['python' , 'python3' , f'python3.{ sys .version_info [1 ]} ' ]
318+ if sys .version_info [:2 ] == (3 , 14 ) and sys .getfilesystemencoding () == 'utf-8' :
319+ suffixes .append ('𝜋thon' )
320+ for suffix in suffixes :
309321 path = os .path .join (binpath , suffix )
310322 if not os .path .exists (path ):
311323 # Issue 18807: make copies if
@@ -576,7 +588,7 @@ def skip_file(f):
576588 'may be binary: %s' , srcfile , e )
577589 continue
578590 if new_data == data :
579- shutil .copy2 (srcfile , dstfile )
591+ shutil .copy (srcfile , dstfile )
580592 else :
581593 with open (dstfile , 'wb' ) as f :
582594 f .write (new_data )
@@ -604,16 +616,17 @@ def create(env_dir, system_site_packages=False, clear=False,
604616def main (args = None ):
605617 import argparse
606618
607- parser = argparse .ArgumentParser (prog = __name__ ,
608- description = 'Creates virtual Python '
619+ parser = argparse .ArgumentParser (description = 'Creates virtual Python '
609620 'environments in one or '
610621 'more target '
611622 'directories.' ,
612623 epilog = 'Once an environment has been '
613624 'created, you may wish to '
614625 'activate it, e.g. by '
615626 'sourcing an activate script '
616- 'in its bin directory.' )
627+ 'in its bin directory.' ,
628+ color = True ,
629+ )
617630 parser .add_argument ('dirs' , metavar = 'ENV_DIR' , nargs = '+' ,
618631 help = 'A directory to create the environment in.' )
619632 parser .add_argument ('--system-site-packages' , default = False ,
0 commit comments