summaryrefslogtreecommitdiffstats
path: root/Lib/venv
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2023-09-15 22:38:08 (GMT)
committerGitHub <noreply@github.com>2023-09-15 22:38:08 (GMT)
commite218e5022eef369573808a4f8dda9aeeab663750 (patch)
tree326b79a4ee92623e0beb4ccc773c8b324d8458cc /Lib/venv
parent6b179adb8c05801bf069121b360531d135ee3f44 (diff)
downloadcpython-e218e5022eef369573808a4f8dda9aeeab663750.zip
cpython-e218e5022eef369573808a4f8dda9aeeab663750.tar.gz
cpython-e218e5022eef369573808a4f8dda9aeeab663750.tar.bz2
GH-83417: Allow `venv` to add a `.gitignore` file to environments via a new `scm_ignore_file` parameter (GH-108125)
This feature is off by default via code but on by default via the CLI. The `.gitignore` file contains `*` which causes the entire directory to be ignored. Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
Diffstat (limited to 'Lib/venv')
-rw-r--r--Lib/venv/__init__.py36
-rw-r--r--Lib/venv/__main__.py2
2 files changed, 33 insertions, 5 deletions
diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py
index 2173c9b..d960bf3 100644
--- a/Lib/venv/__init__.py
+++ b/Lib/venv/__init__.py
@@ -41,11 +41,13 @@ class EnvBuilder:
environment
:param prompt: Alternative terminal prefix for the environment.
:param upgrade_deps: Update the base venv modules to the latest on PyPI
+ :param scm_ignore_files: Create ignore files for the SCMs specified by the
+ iterable.
"""
def __init__(self, system_site_packages=False, clear=False,
symlinks=False, upgrade=False, with_pip=False, prompt=None,
- upgrade_deps=False):
+ upgrade_deps=False, *, scm_ignore_files=frozenset()):
self.system_site_packages = system_site_packages
self.clear = clear
self.symlinks = symlinks
@@ -56,6 +58,7 @@ class EnvBuilder:
prompt = os.path.basename(os.getcwd())
self.prompt = prompt
self.upgrade_deps = upgrade_deps
+ self.scm_ignore_files = frozenset(map(str.lower, scm_ignore_files))
def create(self, env_dir):
"""
@@ -66,6 +69,8 @@ class EnvBuilder:
"""
env_dir = os.path.abspath(env_dir)
context = self.ensure_directories(env_dir)
+ for scm in self.scm_ignore_files:
+ getattr(self, f"create_{scm}_ignore_file")(context)
# See issue 24875. We need system_site_packages to be False
# until after pip is installed.
true_system_site_packages = self.system_site_packages
@@ -210,6 +215,8 @@ class EnvBuilder:
args.append('--upgrade-deps')
if self.orig_prompt is not None:
args.append(f'--prompt="{self.orig_prompt}"')
+ if not self.scm_ignore_files:
+ args.append('--without-scm-ignore-files')
args.append(context.env_dir)
args = ' '.join(args)
@@ -278,6 +285,19 @@ class EnvBuilder:
shutil.copyfile(src, dst)
+ def create_git_ignore_file(self, context):
+ """
+ Create a .gitignore file in the environment directory.
+
+ The contents of the file cause the entire environment directory to be
+ ignored by git.
+ """
+ gitignore_path = os.path.join(context.env_dir, '.gitignore')
+ with open(gitignore_path, 'w', encoding='utf-8') as file:
+ file.write('# Created by venv; '
+ 'see https://docs.python.org/3/library/venv.html\n')
+ file.write('*\n')
+
def setup_python(self, context):
"""
Set up a Python executable in the environment.
@@ -461,11 +481,13 @@ class EnvBuilder:
def create(env_dir, system_site_packages=False, clear=False,
- symlinks=False, with_pip=False, prompt=None, upgrade_deps=False):
+ symlinks=False, with_pip=False, prompt=None, upgrade_deps=False,
+ *, scm_ignore_files=frozenset()):
"""Create a virtual environment in a directory."""
builder = EnvBuilder(system_site_packages=system_site_packages,
clear=clear, symlinks=symlinks, with_pip=with_pip,
- prompt=prompt, upgrade_deps=upgrade_deps)
+ prompt=prompt, upgrade_deps=upgrade_deps,
+ scm_ignore_files=scm_ignore_files)
builder.create(env_dir)
@@ -525,6 +547,11 @@ def main(args=None):
dest='upgrade_deps',
help=f'Upgrade core dependencies ({", ".join(CORE_VENV_DEPS)}) '
'to the latest version in PyPI')
+ parser.add_argument('--without-scm-ignore-files', dest='scm_ignore_files',
+ action='store_const', const=frozenset(),
+ default=frozenset(['git']),
+ help='Skips adding SCM ignore files to the environment '
+ 'directory (Git is supported by default).')
options = parser.parse_args(args)
if options.upgrade and options.clear:
raise ValueError('you cannot supply --upgrade and --clear together.')
@@ -534,7 +561,8 @@ def main(args=None):
upgrade=options.upgrade,
with_pip=options.with_pip,
prompt=options.prompt,
- upgrade_deps=options.upgrade_deps)
+ upgrade_deps=options.upgrade_deps,
+ scm_ignore_files=options.scm_ignore_files)
for d in options.dirs:
builder.create(d)
diff --git a/Lib/venv/__main__.py b/Lib/venv/__main__.py
index 912423e..88f5543 100644
--- a/Lib/venv/__main__.py
+++ b/Lib/venv/__main__.py
@@ -6,5 +6,5 @@ try:
main()
rc = 0
except Exception as e:
- print('Error: %s' % e, file=sys.stderr)
+ print('Error:', e, file=sys.stderr)
sys.exit(rc)