Skip to content

Commit e04f466

Browse files
committed
Add tests
1 parent 0601cc5 commit e04f466

1 file changed

Lines changed: 220 additions & 0 deletions

File tree

Lib/test/test_venv.py

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,226 @@ def test_sysconfig(self):
310310
out, err = check_output(cmd, encoding='utf-8')
311311
self.assertEqual(out.strip(), expected, err)
312312

313+
@requireVenvCreate
314+
def test_version_mismatch_warning(self):
315+
"""
316+
Test that a warning is emitted when running a venv created for a
317+
different minor Python version.
318+
"""
319+
rmtree(self.env_dir)
320+
321+
wrong_minor = sys.version_info.minor + 1
322+
self.run_with_capture(venv.create, self.env_dir, with_pip=False)
323+
324+
cfg_path = self.get_env_file('pyvenv.cfg')
325+
with open(cfg_path, 'r', encoding='utf-8') as f:
326+
cfg_content = f.read()
327+
328+
new_version = f"{sys.version_info.major}.{wrong_minor}"
329+
if 'version =' in cfg_content:
330+
cfg_content = re.sub(r'version = \d+\.\d+', f'version = {new_version}', cfg_content)
331+
332+
cfg_content += f'\nversion_info = {new_version}\n'
333+
334+
with open(cfg_path, 'w', encoding='utf-8') as f:
335+
f.write(cfg_content)
336+
337+
envpy = self.envpy(real_env_dir=True)
338+
339+
proc = subprocess.run(
340+
[envpy, '-c', 'import sys; print("done")'],
341+
capture_output=True,
342+
text=True,
343+
env={**os.environ, "PYTHONHOME": ""}
344+
)
345+
346+
self.assertIn(f"Python {sys.version_info.major}.{wrong_minor}", proc.stderr)
347+
self.assertIn("Consider running `python -m venv --upgrade`", proc.stderr)
348+
349+
@requireVenvCreate
350+
def test_version_info_mismatch_warning(self):
351+
"""
352+
Test that a warning is emitted when version_info (used by virtualenv)
353+
indicates a different minor version.
354+
"""
355+
rmtree(self.env_dir)
356+
wrong_minor = sys.version_info.minor + 1
357+
self.run_with_capture(venv.create, self.env_dir, with_pip=False)
358+
359+
cfg_path = self.get_env_file('pyvenv.cfg')
360+
with open(cfg_path, 'r', encoding='utf-8') as f:
361+
cfg_content = f.read()
362+
363+
# Add only version_info, don't modify version
364+
new_version = f"{sys.version_info.major}.{wrong_minor}"
365+
cfg_content += f'\nversion_info = {new_version}\n'
366+
367+
with open(cfg_path, 'w', encoding='utf-8') as f:
368+
f.write(cfg_content)
369+
370+
envpy = self.envpy(real_env_dir=True)
371+
proc = subprocess.run(
372+
[envpy, '-c', 'import sys; print("done")'],
373+
capture_output=True,
374+
text=True,
375+
env={**os.environ, "PYTHONHOME": ""}
376+
)
377+
378+
self.assertIn(f"Python {sys.version_info.major}.{wrong_minor}", proc.stderr)
379+
self.assertIn("Consider running `python -m venv --upgrade`", proc.stderr)
380+
381+
@requireVenvCreate
382+
def test_version_match_no_warning(self):
383+
"""
384+
Test that no warning is emitted when the venv version matches.
385+
"""
386+
rmtree(self.env_dir)
387+
388+
self.run_with_capture(venv.create, self.env_dir, with_pip=False)
389+
cfg_path = self.get_env_file('pyvenv.cfg')
390+
with open(cfg_path, 'r', encoding='utf-8') as f:
391+
cfg_content = f.read()
392+
expected_version = f"{sys.version_info.major}.{sys.version_info.minor}"
393+
394+
with open(cfg_path, 'w', encoding='utf-8') as f:
395+
f.write(cfg_content)
396+
envpy = self.envpy(real_env_dir=True)
397+
proc = subprocess.run(
398+
[envpy, '-c', 'import sys; print("done")'],
399+
capture_output=True,
400+
text=True,
401+
env={**os.environ, "PYTHONHOME": ""}
402+
)
403+
404+
self.assertNotIn("Consider running `python -m venv --upgrade`", proc.stderr)
405+
406+
@requireVenvCreate
407+
def test_malformed_version_warning(self):
408+
"""
409+
Test that a warning is emitted on malformed version string
410+
in pyenv.cfg
411+
"""
412+
rmtree(self.env_dir)
413+
414+
self.run_with_capture(venv.create, self.env_dir, with_pip=False)
415+
416+
cfg_path = self.get_env_file('pyvenv.cfg')
417+
with open(cfg_path, 'r', encoding='utf-8') as f:
418+
cfg_content = f.read()
419+
420+
malformed_version = "not.a.version"
421+
if 'version =' in cfg_content:
422+
cfg_content = re.sub(r'version = .+', f'version = {malformed_version}', cfg_content)
423+
424+
with open(cfg_path, 'w', encoding='utf-8') as f:
425+
f.write(cfg_content)
426+
427+
envpy = self.envpy(real_env_dir=True)
428+
proc = subprocess.run(
429+
[envpy, '-c', 'import sys; print("done")'],
430+
capture_output=True,
431+
text=True,
432+
env={**os.environ, "PYTHONHOME": ""}
433+
)
434+
self.assertIn("Malformed version string", proc.stderr)
435+
self.assertIn(malformed_version, proc.stderr)
436+
437+
@requireVenvCreate
438+
def test_malformed_version_info_warning(self):
439+
"""
440+
Test that a warning is emitted on malformed version_info string
441+
in pyenv.cfg
442+
"""
443+
rmtree(self.env_dir)
444+
self.run_with_capture(venv.create, self.env_dir, with_pip=False)
445+
446+
cfg_path = self.get_env_file('pyvenv.cfg')
447+
with open(cfg_path, 'r', encoding='utf-8') as f:
448+
cfg_content = f.read()
449+
450+
malformed_version = "invalid.version"
451+
cfg_content += f'\nversion_info = {malformed_version}\n'
452+
453+
with open(cfg_path, 'w', encoding='utf-8') as f:
454+
f.write(cfg_content)
455+
456+
envpy = self.envpy(real_env_dir=True)
457+
proc = subprocess.run(
458+
[envpy, '-c', 'import sys; print("done")'],
459+
capture_output=True,
460+
text=True,
461+
env={**os.environ, "PYTHONHOME": ""}
462+
)
463+
464+
self.assertIn("Malformed version_info string", proc.stderr)
465+
self.assertIn(malformed_version, proc.stderr)
466+
467+
@requireVenvCreate
468+
def test_conflicting_version_fields(self):
469+
"""
470+
Test behavior when both version and version_info are present
471+
but contain different values. Should warn based on first mismatch found.
472+
"""
473+
rmtree(self.env_dir)
474+
wrong_minor = sys.version_info.minor + 1
475+
self.run_with_capture(venv.create, self.env_dir, with_pip=False)
476+
477+
cfg_path = self.get_env_file('pyvenv.cfg')
478+
with open(cfg_path, 'r', encoding='utf-8') as f:
479+
cfg_content = f.read()
480+
481+
version_wrong = f"{sys.version_info.major}.{wrong_minor}"
482+
if 'version =' in cfg_content:
483+
cfg_content = re.sub(r'version = \d+\.\d+', f'version = {version_wrong}', cfg_content)
484+
485+
version_info_wrong = f"{sys.version_info.major}.{wrong_minor + 1}"
486+
cfg_content += f'\nversion_info = {version_info_wrong}\n'
487+
488+
with open(cfg_path, 'w', encoding='utf-8') as f:
489+
f.write(cfg_content)
490+
491+
envpy = self.envpy(real_env_dir=True)
492+
proc = subprocess.run(
493+
[envpy, '-c', 'import sys; print("done")'],
494+
capture_output=True,
495+
text=True,
496+
env={**os.environ, "PYTHONHOME": ""}
497+
)
498+
499+
self.assertIn("Consider running `python -m venv --upgrade`", proc.stderr)
500+
self.assertEqual(proc.stderr.count("Consider running `python -m venv --upgrade`"), 1)
501+
502+
@requireVenvCreate
503+
def test_different_major_version_no_warning(self):
504+
"""
505+
Test that no warning is emitted when major version differs.
506+
The warning should only trigger for same major, different minor.
507+
"""
508+
rmtree(self.env_dir)
509+
self.run_with_capture(venv.create, self.env_dir, with_pip=False)
510+
511+
cfg_path = self.get_env_file('pyvenv.cfg')
512+
with open(cfg_path, 'r', encoding='utf-8') as f:
513+
cfg_content = f.read()
514+
515+
different_major = sys.version_info.major + 1
516+
new_version = f"{different_major}.{sys.version_info.minor}"
517+
518+
if 'version =' in cfg_content:
519+
cfg_content = re.sub(r'version = \d+\.\d+', f'version = {new_version}', cfg_content)
520+
with open(cfg_path, 'w', encoding='utf-8') as f:
521+
f.write(cfg_content)
522+
523+
envpy = self.envpy(real_env_dir=True)
524+
proc = subprocess.run(
525+
[envpy, '-c', 'import sys; print("done")'],
526+
capture_output=True,
527+
text=True,
528+
env={**os.environ, "PYTHONHOME": ""}
529+
)
530+
531+
self.assertNotIn("Consider running `python -m venv --upgrade`", proc.stderr)
532+
313533
@requireVenvCreate
314534
@unittest.skipUnless(can_symlink(), 'Needs symlinks')
315535
def test_sysconfig_symlinks(self):

0 commit comments

Comments
 (0)