| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213 |
- import copy
- import ntpath
- import pathlib
- import posixpath
- import sys
- import unittest
- from test.support import verbose
- try:
- # If we are in a source tree, use the original source file for tests
- SOURCE = (pathlib.Path(__file__).absolute().parent.parent.parent / "Modules/getpath.py").read_bytes()
- except FileNotFoundError:
- # Try from _testcapimodule instead
- from _testinternalcapi import get_getpath_codeobject
- SOURCE = get_getpath_codeobject()
- class MockGetPathTests(unittest.TestCase):
- def __init__(self, *a, **kw):
- super().__init__(*a, **kw)
- self.maxDiff = None
- def test_normal_win32(self):
- "Test a 'standard' install layout on Windows."
- ns = MockNTNamespace(
- argv0=r"C:\Python\python.exe",
- real_executable=r"C:\Python\python.exe",
- )
- ns.add_known_xfile(r"C:\Python\python.exe")
- ns.add_known_file(r"C:\Python\Lib\os.py")
- ns.add_known_dir(r"C:\Python\DLLs")
- expected = dict(
- executable=r"C:\Python\python.exe",
- base_executable=r"C:\Python\python.exe",
- prefix=r"C:\Python",
- exec_prefix=r"C:\Python",
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\Python\python98.zip",
- r"C:\Python\DLLs",
- r"C:\Python\Lib",
- r"C:\Python",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_buildtree_win32(self):
- "Test an in-build-tree layout on Windows."
- ns = MockNTNamespace(
- argv0=r"C:\CPython\PCbuild\amd64\python.exe",
- real_executable=r"C:\CPython\PCbuild\amd64\python.exe",
- )
- ns.add_known_xfile(r"C:\CPython\PCbuild\amd64\python.exe")
- ns.add_known_file(r"C:\CPython\Lib\os.py")
- ns.add_known_file(r"C:\CPython\PCbuild\amd64\pybuilddir.txt", [""])
- expected = dict(
- executable=r"C:\CPython\PCbuild\amd64\python.exe",
- base_executable=r"C:\CPython\PCbuild\amd64\python.exe",
- prefix=r"C:\CPython",
- exec_prefix=r"C:\CPython",
- build_prefix=r"C:\CPython",
- _is_python_build=1,
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\CPython\PCbuild\amd64\python98.zip",
- r"C:\CPython\PCbuild\amd64",
- r"C:\CPython\Lib",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_win32(self):
- """Test a venv layout on Windows.
- This layout is discovered by the presence of %__PYVENV_LAUNCHER__%,
- specifying the original launcher executable. site.py is responsible
- for updating prefix and exec_prefix.
- """
- ns = MockNTNamespace(
- argv0=r"C:\Python\python.exe",
- ENV___PYVENV_LAUNCHER__=r"C:\venv\Scripts\python.exe",
- real_executable=r"C:\Python\python.exe",
- )
- ns.add_known_xfile(r"C:\Python\python.exe")
- ns.add_known_xfile(r"C:\venv\Scripts\python.exe")
- ns.add_known_file(r"C:\Python\Lib\os.py")
- ns.add_known_dir(r"C:\Python\DLLs")
- ns.add_known_file(r"C:\venv\pyvenv.cfg", [
- r"home = C:\Python"
- ])
- expected = dict(
- executable=r"C:\venv\Scripts\python.exe",
- prefix=r"C:\Python",
- exec_prefix=r"C:\Python",
- base_executable=r"C:\Python\python.exe",
- base_prefix=r"C:\Python",
- base_exec_prefix=r"C:\Python",
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\Python\python98.zip",
- r"C:\Python\DLLs",
- r"C:\Python\Lib",
- r"C:\Python",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_registry_win32(self):
- """Test registry lookup on Windows.
- On Windows there are registry entries that are intended for other
- applications to register search paths.
- """
- hkey = rf"HKLM\Software\Python\PythonCore\9.8-XY\PythonPath"
- winreg = MockWinreg({
- hkey: None,
- f"{hkey}\\Path1": "path1-dir",
- f"{hkey}\\Path1\\Subdir": "not-subdirs",
- })
- ns = MockNTNamespace(
- argv0=r"C:\Python\python.exe",
- real_executable=r"C:\Python\python.exe",
- winreg=winreg,
- )
- ns.add_known_xfile(r"C:\Python\python.exe")
- ns.add_known_file(r"C:\Python\Lib\os.py")
- ns.add_known_dir(r"C:\Python\DLLs")
- expected = dict(
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\Python\python98.zip",
- "path1-dir",
- # should not contain not-subdirs
- r"C:\Python\DLLs",
- r"C:\Python\Lib",
- r"C:\Python",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- ns["config"]["use_environment"] = 0
- ns["config"]["module_search_paths_set"] = 0
- ns["config"]["module_search_paths"] = None
- expected = dict(
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\Python\python98.zip",
- r"C:\Python\DLLs",
- r"C:\Python\Lib",
- r"C:\Python",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_symlink_normal_win32(self):
- "Test a 'standard' install layout via symlink on Windows."
- ns = MockNTNamespace(
- argv0=r"C:\LinkedFrom\python.exe",
- real_executable=r"C:\Python\python.exe",
- )
- ns.add_known_xfile(r"C:\LinkedFrom\python.exe")
- ns.add_known_xfile(r"C:\Python\python.exe")
- ns.add_known_link(r"C:\LinkedFrom\python.exe", r"C:\Python\python.exe")
- ns.add_known_file(r"C:\Python\Lib\os.py")
- ns.add_known_dir(r"C:\Python\DLLs")
- expected = dict(
- executable=r"C:\LinkedFrom\python.exe",
- base_executable=r"C:\LinkedFrom\python.exe",
- prefix=r"C:\Python",
- exec_prefix=r"C:\Python",
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\Python\python98.zip",
- r"C:\Python\DLLs",
- r"C:\Python\Lib",
- r"C:\Python",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_symlink_buildtree_win32(self):
- "Test an in-build-tree layout via symlink on Windows."
- ns = MockNTNamespace(
- argv0=r"C:\LinkedFrom\python.exe",
- real_executable=r"C:\CPython\PCbuild\amd64\python.exe",
- )
- ns.add_known_xfile(r"C:\LinkedFrom\python.exe")
- ns.add_known_xfile(r"C:\CPython\PCbuild\amd64\python.exe")
- ns.add_known_link(r"C:\LinkedFrom\python.exe", r"C:\CPython\PCbuild\amd64\python.exe")
- ns.add_known_file(r"C:\CPython\Lib\os.py")
- ns.add_known_file(r"C:\CPython\PCbuild\amd64\pybuilddir.txt", [""])
- expected = dict(
- executable=r"C:\LinkedFrom\python.exe",
- base_executable=r"C:\LinkedFrom\python.exe",
- prefix=r"C:\CPython",
- exec_prefix=r"C:\CPython",
- build_prefix=r"C:\CPython",
- _is_python_build=1,
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\CPython\PCbuild\amd64\python98.zip",
- r"C:\CPython\PCbuild\amd64",
- r"C:\CPython\Lib",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_buildtree_pythonhome_win32(self):
- "Test an out-of-build-tree layout on Windows with PYTHONHOME override."
- ns = MockNTNamespace(
- argv0=r"C:\Out\python.exe",
- real_executable=r"C:\Out\python.exe",
- ENV_PYTHONHOME=r"C:\CPython",
- )
- ns.add_known_xfile(r"C:\Out\python.exe")
- ns.add_known_file(r"C:\CPython\Lib\os.py")
- ns.add_known_file(r"C:\Out\pybuilddir.txt", [""])
- expected = dict(
- executable=r"C:\Out\python.exe",
- base_executable=r"C:\Out\python.exe",
- prefix=r"C:\CPython",
- exec_prefix=r"C:\CPython",
- # This build_prefix is a miscalculation, because we have
- # moved the output direction out of the prefix.
- # Specify PYTHONHOME to get the correct prefix/exec_prefix
- build_prefix="C:\\",
- _is_python_build=1,
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\Out\python98.zip",
- r"C:\Out",
- r"C:\CPython\Lib",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_no_dlls_win32(self):
- "Test a layout on Windows with no DLLs directory."
- ns = MockNTNamespace(
- argv0=r"C:\Python\python.exe",
- real_executable=r"C:\Python\python.exe",
- )
- ns.add_known_xfile(r"C:\Python\python.exe")
- ns.add_known_file(r"C:\Python\Lib\os.py")
- expected = dict(
- executable=r"C:\Python\python.exe",
- base_executable=r"C:\Python\python.exe",
- prefix=r"C:\Python",
- exec_prefix=r"C:\Python",
- module_search_paths_set=1,
- module_search_paths=[
- r"C:\Python\python98.zip",
- r"C:\Python",
- r"C:\Python\Lib",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_normal_posix(self):
- "Test a 'standard' install layout on *nix"
- ns = MockPosixNamespace(
- PREFIX="/usr",
- argv0="python",
- ENV_PATH="/usr/bin",
- )
- ns.add_known_xfile("/usr/bin/python")
- ns.add_known_file("/usr/lib/python9.8/os.py")
- ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
- expected = dict(
- executable="/usr/bin/python",
- base_executable="/usr/bin/python",
- prefix="/usr",
- exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib/python98.zip",
- "/usr/lib/python9.8",
- "/usr/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_buildpath_posix(self):
- """Test an in-build-tree layout on POSIX.
- This layout is discovered from the presence of pybuilddir.txt, which
- contains the relative path from the executable's directory to the
- platstdlib path.
- """
- ns = MockPosixNamespace(
- argv0=r"/home/cpython/python",
- PREFIX="/usr/local",
- )
- ns.add_known_xfile("/home/cpython/python")
- ns.add_known_xfile("/usr/local/bin/python")
- ns.add_known_file("/home/cpython/pybuilddir.txt", ["build/lib.linux-x86_64-9.8"])
- ns.add_known_file("/home/cpython/Lib/os.py")
- ns.add_known_dir("/home/cpython/lib-dynload")
- expected = dict(
- executable="/home/cpython/python",
- prefix="/usr/local",
- exec_prefix="/usr/local",
- base_executable="/home/cpython/python",
- build_prefix="/home/cpython",
- _is_python_build=1,
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/local/lib/python98.zip",
- "/home/cpython/Lib",
- "/home/cpython/build/lib.linux-x86_64-9.8",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_posix(self):
- "Test a venv layout on *nix."
- ns = MockPosixNamespace(
- argv0="python",
- PREFIX="/usr",
- ENV_PATH="/venv/bin:/usr/bin",
- )
- ns.add_known_xfile("/usr/bin/python")
- ns.add_known_xfile("/venv/bin/python")
- ns.add_known_file("/usr/lib/python9.8/os.py")
- ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
- ns.add_known_file("/venv/pyvenv.cfg", [
- r"home = /usr/bin"
- ])
- expected = dict(
- executable="/venv/bin/python",
- prefix="/usr",
- exec_prefix="/usr",
- base_executable="/usr/bin/python",
- base_prefix="/usr",
- base_exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib/python98.zip",
- "/usr/lib/python9.8",
- "/usr/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_changed_name_posix(self):
- "Test a venv layout on *nix."
- ns = MockPosixNamespace(
- argv0="python",
- PREFIX="/usr",
- ENV_PATH="/venv/bin:/usr/bin",
- )
- ns.add_known_xfile("/usr/bin/python3")
- ns.add_known_xfile("/venv/bin/python")
- ns.add_known_link("/venv/bin/python", "/usr/bin/python3")
- ns.add_known_file("/usr/lib/python9.8/os.py")
- ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
- ns.add_known_file("/venv/pyvenv.cfg", [
- r"home = /usr/bin"
- ])
- expected = dict(
- executable="/venv/bin/python",
- prefix="/usr",
- exec_prefix="/usr",
- base_executable="/usr/bin/python3",
- base_prefix="/usr",
- base_exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib/python98.zip",
- "/usr/lib/python9.8",
- "/usr/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_non_installed_zip_path_posix(self):
- "Test a venv created from non-installed python has correct zip path."""
- ns = MockPosixNamespace(
- argv0="/venv/bin/python",
- PREFIX="/usr",
- ENV_PATH="/venv/bin:/usr/bin",
- )
- ns.add_known_xfile("/path/to/non-installed/bin/python")
- ns.add_known_xfile("/venv/bin/python")
- ns.add_known_link("/venv/bin/python",
- "/path/to/non-installed/bin/python")
- ns.add_known_file("/path/to/non-installed/lib/python9.8/os.py")
- ns.add_known_dir("/path/to/non-installed/lib/python9.8/lib-dynload")
- ns.add_known_file("/venv/pyvenv.cfg", [
- r"home = /path/to/non-installed"
- ])
- expected = dict(
- executable="/venv/bin/python",
- prefix="/path/to/non-installed",
- exec_prefix="/path/to/non-installed",
- base_executable="/path/to/non-installed/bin/python",
- base_prefix="/path/to/non-installed",
- base_exec_prefix="/path/to/non-installed",
- module_search_paths_set=1,
- module_search_paths=[
- "/path/to/non-installed/lib/python98.zip",
- "/path/to/non-installed/lib/python9.8",
- "/path/to/non-installed/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_changed_name_copy_posix(self):
- "Test a venv --copies layout on *nix that lacks a distributed 'python'"
- ns = MockPosixNamespace(
- argv0="python",
- PREFIX="/usr",
- ENV_PATH="/venv/bin:/usr/bin",
- )
- ns.add_known_xfile("/usr/bin/python9")
- ns.add_known_xfile("/venv/bin/python")
- ns.add_known_file("/usr/lib/python9.8/os.py")
- ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
- ns.add_known_file("/venv/pyvenv.cfg", [
- r"home = /usr/bin"
- ])
- expected = dict(
- executable="/venv/bin/python",
- prefix="/usr",
- exec_prefix="/usr",
- base_executable="/usr/bin/python9",
- base_prefix="/usr",
- base_exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib/python98.zip",
- "/usr/lib/python9.8",
- "/usr/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_symlink_normal_posix(self):
- "Test a 'standard' install layout via symlink on *nix"
- ns = MockPosixNamespace(
- PREFIX="/usr",
- argv0="/linkfrom/python",
- )
- ns.add_known_xfile("/linkfrom/python")
- ns.add_known_xfile("/usr/bin/python")
- ns.add_known_link("/linkfrom/python", "/usr/bin/python")
- ns.add_known_file("/usr/lib/python9.8/os.py")
- ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
- expected = dict(
- executable="/linkfrom/python",
- base_executable="/linkfrom/python",
- prefix="/usr",
- exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib/python98.zip",
- "/usr/lib/python9.8",
- "/usr/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_symlink_buildpath_posix(self):
- """Test an in-build-tree layout on POSIX.
- This layout is discovered from the presence of pybuilddir.txt, which
- contains the relative path from the executable's directory to the
- platstdlib path.
- """
- ns = MockPosixNamespace(
- argv0=r"/linkfrom/python",
- PREFIX="/usr/local",
- )
- ns.add_known_xfile("/linkfrom/python")
- ns.add_known_xfile("/home/cpython/python")
- ns.add_known_link("/linkfrom/python", "/home/cpython/python")
- ns.add_known_xfile("/usr/local/bin/python")
- ns.add_known_file("/home/cpython/pybuilddir.txt", ["build/lib.linux-x86_64-9.8"])
- ns.add_known_file("/home/cpython/Lib/os.py")
- ns.add_known_dir("/home/cpython/lib-dynload")
- expected = dict(
- executable="/linkfrom/python",
- prefix="/usr/local",
- exec_prefix="/usr/local",
- base_executable="/linkfrom/python",
- build_prefix="/home/cpython",
- _is_python_build=1,
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/local/lib/python98.zip",
- "/home/cpython/Lib",
- "/home/cpython/build/lib.linux-x86_64-9.8",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_custom_platlibdir_posix(self):
- "Test an install with custom platlibdir on *nix"
- ns = MockPosixNamespace(
- PREFIX="/usr",
- argv0="/linkfrom/python",
- PLATLIBDIR="lib64",
- )
- ns.add_known_xfile("/usr/bin/python")
- ns.add_known_file("/usr/lib64/python9.8/os.py")
- ns.add_known_dir("/usr/lib64/python9.8/lib-dynload")
- expected = dict(
- executable="/linkfrom/python",
- base_executable="/linkfrom/python",
- prefix="/usr",
- exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib64/python98.zip",
- "/usr/lib64/python9.8",
- "/usr/lib64/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_framework_macos(self):
- """ Test framework layout on macOS
- This layout is primarily detected using a compile-time option
- (WITH_NEXT_FRAMEWORK).
- """
- ns = MockPosixNamespace(
- os_name="darwin",
- argv0="/Library/Frameworks/Python.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/Python",
- WITH_NEXT_FRAMEWORK=1,
- PREFIX="/Library/Frameworks/Python.framework/Versions/9.8",
- EXEC_PREFIX="/Library/Frameworks/Python.framework/Versions/9.8",
- ENV___PYVENV_LAUNCHER__="/Library/Frameworks/Python.framework/Versions/9.8/bin/python9.8",
- real_executable="/Library/Frameworks/Python.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/Python",
- library="/Library/Frameworks/Python.framework/Versions/9.8/Python",
- )
- ns.add_known_xfile("/Library/Frameworks/Python.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/Python")
- ns.add_known_xfile("/Library/Frameworks/Python.framework/Versions/9.8/bin/python9.8")
- ns.add_known_dir("/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8/lib-dynload")
- ns.add_known_file("/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8/os.py")
- # This is definitely not the stdlib (see discusion in bpo-46890)
- #ns.add_known_file("/Library/Frameworks/lib/python98.zip")
- expected = dict(
- executable="/Library/Frameworks/Python.framework/Versions/9.8/bin/python9.8",
- prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- exec_prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- base_executable="/Library/Frameworks/Python.framework/Versions/9.8/bin/python9.8",
- base_prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- base_exec_prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- module_search_paths_set=1,
- module_search_paths=[
- "/Library/Frameworks/Python.framework/Versions/9.8/lib/python98.zip",
- "/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8",
- "/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_alt_framework_macos(self):
- """ Test framework layout on macOS with alternate framework name
- ``--with-framework-name=DebugPython``
- This layout is primarily detected using a compile-time option
- (WITH_NEXT_FRAMEWORK).
- """
- ns = MockPosixNamespace(
- argv0="/Library/Frameworks/DebugPython.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/DebugPython",
- os_name="darwin",
- WITH_NEXT_FRAMEWORK=1,
- PREFIX="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- EXEC_PREFIX="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- ENV___PYVENV_LAUNCHER__="/Library/Frameworks/DebugPython.framework/Versions/9.8/bin/python9.8",
- real_executable="/Library/Frameworks/DebugPython.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/DebugPython",
- library="/Library/Frameworks/DebugPython.framework/Versions/9.8/DebugPython",
- PYTHONPATH=None,
- ENV_PYTHONHOME=None,
- ENV_PYTHONEXECUTABLE=None,
- executable_dir=None,
- py_setpath=None,
- )
- ns.add_known_xfile("/Library/Frameworks/DebugPython.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/DebugPython")
- ns.add_known_xfile("/Library/Frameworks/DebugPython.framework/Versions/9.8/bin/python9.8")
- ns.add_known_dir("/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8/lib-dynload")
- ns.add_known_xfile("/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8/os.py")
- # This is definitely not the stdlib (see discusion in bpo-46890)
- #ns.add_known_xfile("/Library/lib/python98.zip")
- expected = dict(
- executable="/Library/Frameworks/DebugPython.framework/Versions/9.8/bin/python9.8",
- prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- exec_prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- base_executable="/Library/Frameworks/DebugPython.framework/Versions/9.8/bin/python9.8",
- base_prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- base_exec_prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- module_search_paths_set=1,
- module_search_paths=[
- "/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python98.zip",
- "/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8",
- "/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_framework_macos(self):
- """Test a venv layout on macOS using a framework build
- """
- venv_path = "/tmp/workdir/venv"
- ns = MockPosixNamespace(
- os_name="darwin",
- argv0="/Library/Frameworks/Python.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/Python",
- WITH_NEXT_FRAMEWORK=1,
- PREFIX="/Library/Frameworks/Python.framework/Versions/9.8",
- EXEC_PREFIX="/Library/Frameworks/Python.framework/Versions/9.8",
- ENV___PYVENV_LAUNCHER__=f"{venv_path}/bin/python",
- real_executable="/Library/Frameworks/Python.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/Python",
- library="/Library/Frameworks/Python.framework/Versions/9.8/Python",
- )
- ns.add_known_dir(venv_path)
- ns.add_known_dir(f"{venv_path}/bin")
- ns.add_known_dir(f"{venv_path}/lib")
- ns.add_known_dir(f"{venv_path}/lib/python9.8")
- ns.add_known_xfile(f"{venv_path}/bin/python")
- ns.add_known_xfile("/Library/Frameworks/Python.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/Python")
- ns.add_known_xfile("/Library/Frameworks/Python.framework/Versions/9.8/bin/python9.8")
- ns.add_known_dir("/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8/lib-dynload")
- ns.add_known_xfile("/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8/os.py")
- ns.add_known_file(f"{venv_path}/pyvenv.cfg", [
- "home = /Library/Frameworks/Python.framework/Versions/9.8/bin"
- ])
- expected = dict(
- executable=f"{venv_path}/bin/python",
- prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- exec_prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- base_executable="/Library/Frameworks/Python.framework/Versions/9.8/bin/python9.8",
- base_prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- base_exec_prefix="/Library/Frameworks/Python.framework/Versions/9.8",
- module_search_paths_set=1,
- module_search_paths=[
- "/Library/Frameworks/Python.framework/Versions/9.8/lib/python98.zip",
- "/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8",
- "/Library/Frameworks/Python.framework/Versions/9.8/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_alt_framework_macos(self):
- """Test a venv layout on macOS using a framework build
- ``--with-framework-name=DebugPython``
- """
- venv_path = "/tmp/workdir/venv"
- ns = MockPosixNamespace(
- os_name="darwin",
- argv0="/Library/Frameworks/DebugPython.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/DebugPython",
- WITH_NEXT_FRAMEWORK=1,
- PREFIX="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- EXEC_PREFIX="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- ENV___PYVENV_LAUNCHER__=f"{venv_path}/bin/python",
- real_executable="/Library/Frameworks/DebugPython.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/DebugPython",
- library="/Library/Frameworks/DebugPython.framework/Versions/9.8/DebugPython",
- )
- ns.add_known_dir(venv_path)
- ns.add_known_dir(f"{venv_path}/bin")
- ns.add_known_dir(f"{venv_path}/lib")
- ns.add_known_dir(f"{venv_path}/lib/python9.8")
- ns.add_known_xfile(f"{venv_path}/bin/python")
- ns.add_known_xfile("/Library/Frameworks/DebugPython.framework/Versions/9.8/Resources/Python.app/Contents/MacOS/DebugPython")
- ns.add_known_xfile("/Library/Frameworks/DebugPython.framework/Versions/9.8/bin/python9.8")
- ns.add_known_dir("/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8/lib-dynload")
- ns.add_known_xfile("/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8/os.py")
- ns.add_known_file(f"{venv_path}/pyvenv.cfg", [
- "home = /Library/Frameworks/DebugPython.framework/Versions/9.8/bin"
- ])
- expected = dict(
- executable=f"{venv_path}/bin/python",
- prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- exec_prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- base_executable="/Library/Frameworks/DebugPython.framework/Versions/9.8/bin/python9.8",
- base_prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- base_exec_prefix="/Library/Frameworks/DebugPython.framework/Versions/9.8",
- module_search_paths_set=1,
- module_search_paths=[
- "/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python98.zip",
- "/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8",
- "/Library/Frameworks/DebugPython.framework/Versions/9.8/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_venv_macos(self):
- """Test a venv layout on macOS.
- This layout is discovered when 'executable' and 'real_executable' match,
- but $__PYVENV_LAUNCHER__ has been set to the original process.
- """
- ns = MockPosixNamespace(
- os_name="darwin",
- argv0="/usr/bin/python",
- PREFIX="/usr",
- ENV___PYVENV_LAUNCHER__="/framework/Python9.8/python",
- real_executable="/usr/bin/python",
- )
- ns.add_known_xfile("/usr/bin/python")
- ns.add_known_xfile("/framework/Python9.8/python")
- ns.add_known_file("/usr/lib/python9.8/os.py")
- ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
- ns.add_known_file("/framework/Python9.8/pyvenv.cfg", [
- "home = /usr/bin"
- ])
- expected = dict(
- executable="/framework/Python9.8/python",
- prefix="/usr",
- exec_prefix="/usr",
- base_executable="/usr/bin/python",
- base_prefix="/usr",
- base_exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib/python98.zip",
- "/usr/lib/python9.8",
- "/usr/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_symlink_normal_macos(self):
- "Test a 'standard' install layout via symlink on macOS"
- ns = MockPosixNamespace(
- os_name="darwin",
- PREFIX="/usr",
- argv0="python",
- ENV_PATH="/linkfrom:/usr/bin",
- # real_executable on macOS matches the invocation path
- real_executable="/linkfrom/python",
- )
- ns.add_known_xfile("/linkfrom/python")
- ns.add_known_xfile("/usr/bin/python")
- ns.add_known_link("/linkfrom/python", "/usr/bin/python")
- ns.add_known_file("/usr/lib/python9.8/os.py")
- ns.add_known_dir("/usr/lib/python9.8/lib-dynload")
- expected = dict(
- executable="/linkfrom/python",
- base_executable="/linkfrom/python",
- prefix="/usr",
- exec_prefix="/usr",
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/lib/python98.zip",
- "/usr/lib/python9.8",
- "/usr/lib/python9.8/lib-dynload",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- def test_symlink_buildpath_macos(self):
- """Test an in-build-tree layout via symlink on macOS.
- This layout is discovered from the presence of pybuilddir.txt, which
- contains the relative path from the executable's directory to the
- platstdlib path.
- """
- ns = MockPosixNamespace(
- os_name="darwin",
- argv0=r"python",
- ENV_PATH="/linkfrom:/usr/bin",
- PREFIX="/usr/local",
- # real_executable on macOS matches the invocation path
- real_executable="/linkfrom/python",
- )
- ns.add_known_xfile("/linkfrom/python")
- ns.add_known_xfile("/home/cpython/python")
- ns.add_known_link("/linkfrom/python", "/home/cpython/python")
- ns.add_known_xfile("/usr/local/bin/python")
- ns.add_known_file("/home/cpython/pybuilddir.txt", ["build/lib.macos-9.8"])
- ns.add_known_file("/home/cpython/Lib/os.py")
- ns.add_known_dir("/home/cpython/lib-dynload")
- expected = dict(
- executable="/linkfrom/python",
- prefix="/usr/local",
- exec_prefix="/usr/local",
- base_executable="/linkfrom/python",
- build_prefix="/home/cpython",
- _is_python_build=1,
- module_search_paths_set=1,
- module_search_paths=[
- "/usr/local/lib/python98.zip",
- "/home/cpython/Lib",
- "/home/cpython/build/lib.macos-9.8",
- ],
- )
- actual = getpath(ns, expected)
- self.assertEqual(expected, actual)
- # ******************************************************************************
- DEFAULT_NAMESPACE = dict(
- PREFIX="",
- EXEC_PREFIX="",
- PYTHONPATH="",
- VPATH="",
- PLATLIBDIR="",
- PYDEBUGEXT="",
- VERSION_MAJOR=9, # fixed version number for ease
- VERSION_MINOR=8, # of testing
- PYWINVER=None,
- EXE_SUFFIX=None,
- ENV_PATH="",
- ENV_PYTHONHOME="",
- ENV_PYTHONEXECUTABLE="",
- ENV___PYVENV_LAUNCHER__="",
- argv0="",
- py_setpath="",
- real_executable="",
- executable_dir="",
- library="",
- winreg=None,
- build_prefix=None,
- venv_prefix=None,
- )
- DEFAULT_CONFIG = dict(
- home=None,
- platlibdir=None,
- pythonpath=None,
- program_name=None,
- prefix=None,
- exec_prefix=None,
- base_prefix=None,
- base_exec_prefix=None,
- executable=None,
- base_executable="",
- stdlib_dir=None,
- platstdlib_dir=None,
- module_search_paths=None,
- module_search_paths_set=0,
- pythonpath_env=None,
- argv=None,
- orig_argv=None,
- isolated=0,
- use_environment=1,
- use_site=1,
- )
- class MockNTNamespace(dict):
- def __init__(self, *a, argv0=None, config=None, **kw):
- self.update(DEFAULT_NAMESPACE)
- self["config"] = DEFAULT_CONFIG.copy()
- self["os_name"] = "nt"
- self["PLATLIBDIR"] = "DLLs"
- self["PYWINVER"] = "9.8-XY"
- self["VPATH"] = r"..\.."
- super().__init__(*a, **kw)
- if argv0:
- self["config"]["orig_argv"] = [argv0]
- if config:
- self["config"].update(config)
- self._files = {}
- self._links = {}
- self._dirs = set()
- self._warnings = []
- def add_known_file(self, path, lines=None):
- self._files[path.casefold()] = list(lines or ())
- self.add_known_dir(path.rpartition("\\")[0])
- def add_known_xfile(self, path):
- self.add_known_file(path)
- def add_known_link(self, path, target):
- self._links[path.casefold()] = target
- def add_known_dir(self, path):
- p = path.rstrip("\\").casefold()
- while p:
- self._dirs.add(p)
- p = p.rpartition("\\")[0]
- def __missing__(self, key):
- try:
- return getattr(self, key)
- except AttributeError:
- raise KeyError(key) from None
- def abspath(self, path):
- if self.isabs(path):
- return path
- return self.joinpath("C:\\Absolute", path)
- def basename(self, path):
- return path.rpartition("\\")[2]
- def dirname(self, path):
- name = path.rstrip("\\").rpartition("\\")[0]
- if name[1:] == ":":
- return name + "\\"
- return name
- def hassuffix(self, path, suffix):
- return path.casefold().endswith(suffix.casefold())
- def isabs(self, path):
- return path[1:3] == ":\\"
- def isdir(self, path):
- if verbose:
- print("Check if", path, "is a dir")
- return path.casefold() in self._dirs
- def isfile(self, path):
- if verbose:
- print("Check if", path, "is a file")
- return path.casefold() in self._files
- def ismodule(self, path):
- if verbose:
- print("Check if", path, "is a module")
- path = path.casefold()
- return path in self._files and path.rpartition(".")[2] == "py".casefold()
- def isxfile(self, path):
- if verbose:
- print("Check if", path, "is a executable")
- path = path.casefold()
- return path in self._files and path.rpartition(".")[2] == "exe".casefold()
- def joinpath(self, *path):
- return ntpath.normpath(ntpath.join(*path))
- def readlines(self, path):
- try:
- return self._files[path.casefold()]
- except KeyError:
- raise FileNotFoundError(path) from None
- def realpath(self, path, _trail=None):
- if verbose:
- print("Read link from", path)
- try:
- link = self._links[path.casefold()]
- except KeyError:
- return path
- if _trail is None:
- _trail = set()
- elif link.casefold() in _trail:
- raise OSError("circular link")
- _trail.add(link.casefold())
- return self.realpath(link, _trail)
- def warn(self, message):
- self._warnings.append(message)
- if verbose:
- print(message)
- class MockWinreg:
- HKEY_LOCAL_MACHINE = "HKLM"
- HKEY_CURRENT_USER = "HKCU"
- def __init__(self, keys):
- self.keys = {k.casefold(): v for k, v in keys.items()}
- self.open = {}
- def __repr__(self):
- return "<MockWinreg>"
- def __eq__(self, other):
- return isinstance(other, type(self))
- def open_keys(self):
- return list(self.open)
- def OpenKeyEx(self, hkey, subkey):
- if verbose:
- print(f"OpenKeyEx({hkey}, {subkey})")
- key = f"{hkey}\\{subkey}".casefold()
- if key in self.keys:
- self.open[key] = self.open.get(key, 0) + 1
- return key
- raise FileNotFoundError()
- def CloseKey(self, hkey):
- if verbose:
- print(f"CloseKey({hkey})")
- hkey = hkey.casefold()
- if hkey not in self.open:
- raise RuntimeError("key is not open")
- self.open[hkey] -= 1
- if not self.open[hkey]:
- del self.open[hkey]
- def EnumKey(self, hkey, i):
- if verbose:
- print(f"EnumKey({hkey}, {i})")
- hkey = hkey.casefold()
- if hkey not in self.open:
- raise RuntimeError("key is not open")
- prefix = f'{hkey}\\'
- subkeys = [k[len(prefix):] for k in sorted(self.keys) if k.startswith(prefix)]
- subkeys[:] = [k for k in subkeys if '\\' not in k]
- for j, n in enumerate(subkeys):
- if j == i:
- return n.removeprefix(prefix)
- raise OSError("end of enumeration")
- def QueryValue(self, hkey, subkey):
- if verbose:
- print(f"QueryValue({hkey}, {subkey})")
- hkey = hkey.casefold()
- if hkey not in self.open:
- raise RuntimeError("key is not open")
- if subkey:
- subkey = subkey.casefold()
- hkey = f'{hkey}\\{subkey}'
- try:
- return self.keys[hkey]
- except KeyError:
- raise OSError()
- class MockPosixNamespace(dict):
- def __init__(self, *a, argv0=None, config=None, **kw):
- self.update(DEFAULT_NAMESPACE)
- self["config"] = DEFAULT_CONFIG.copy()
- self["os_name"] = "posix"
- self["PLATLIBDIR"] = "lib"
- self["WITH_NEXT_FRAMEWORK"] = 0
- super().__init__(*a, **kw)
- if argv0:
- self["config"]["orig_argv"] = [argv0]
- if config:
- self["config"].update(config)
- self._files = {}
- self._xfiles = set()
- self._links = {}
- self._dirs = set()
- self._warnings = []
- def add_known_file(self, path, lines=None):
- self._files[path] = list(lines or ())
- self.add_known_dir(path.rpartition("/")[0])
- def add_known_xfile(self, path):
- self.add_known_file(path)
- self._xfiles.add(path)
- def add_known_link(self, path, target):
- self._links[path] = target
- def add_known_dir(self, path):
- p = path.rstrip("/")
- while p:
- self._dirs.add(p)
- p = p.rpartition("/")[0]
- def __missing__(self, key):
- try:
- return getattr(self, key)
- except AttributeError:
- raise KeyError(key) from None
- def abspath(self, path):
- if self.isabs(path):
- return path
- return self.joinpath("/Absolute", path)
- def basename(self, path):
- return path.rpartition("/")[2]
- def dirname(self, path):
- return path.rstrip("/").rpartition("/")[0]
- def hassuffix(self, path, suffix):
- return path.endswith(suffix)
- def isabs(self, path):
- return path[0:1] == "/"
- def isdir(self, path):
- if verbose:
- print("Check if", path, "is a dir")
- return path in self._dirs
- def isfile(self, path):
- if verbose:
- print("Check if", path, "is a file")
- return path in self._files
- def ismodule(self, path):
- if verbose:
- print("Check if", path, "is a module")
- return path in self._files and path.rpartition(".")[2] == "py"
- def isxfile(self, path):
- if verbose:
- print("Check if", path, "is an xfile")
- return path in self._xfiles
- def joinpath(self, *path):
- return posixpath.normpath(posixpath.join(*path))
- def readlines(self, path):
- try:
- return self._files[path]
- except KeyError:
- raise FileNotFoundError(path) from None
- def realpath(self, path, _trail=None):
- if verbose:
- print("Read link from", path)
- try:
- link = self._links[path]
- except KeyError:
- return path
- if _trail is None:
- _trail = set()
- elif link in _trail:
- raise OSError("circular link")
- _trail.add(link)
- return self.realpath(link, _trail)
- def warn(self, message):
- self._warnings.append(message)
- if verbose:
- print(message)
- def diff_dict(before, after, prefix="global"):
- diff = []
- for k in sorted(before):
- if k[:2] == "__":
- continue
- if k == "config":
- diff_dict(before[k], after[k], prefix="config")
- continue
- if k in after and after[k] != before[k]:
- diff.append((k, before[k], after[k]))
- if not diff:
- return
- max_k = max(len(k) for k, _, _ in diff)
- indent = " " * (len(prefix) + 1 + max_k)
- if verbose:
- for k, b, a in diff:
- if b:
- print("{}.{} -{!r}\n{} +{!r}".format(prefix, k.ljust(max_k), b, indent, a))
- else:
- print("{}.{} +{!r}".format(prefix, k.ljust(max_k), a))
- def dump_dict(before, after, prefix="global"):
- if not verbose or not after:
- return
- max_k = max(len(k) for k in after)
- for k, v in sorted(after.items(), key=lambda i: i[0]):
- if k[:2] == "__":
- continue
- if k == "config":
- dump_dict(before[k], after[k], prefix="config")
- continue
- try:
- if v != before[k]:
- print("{}.{} {!r} (was {!r})".format(prefix, k.ljust(max_k), v, before[k]))
- continue
- except KeyError:
- pass
- print("{}.{} {!r}".format(prefix, k.ljust(max_k), v))
- def getpath(ns, keys):
- before = copy.deepcopy(ns)
- failed = True
- try:
- exec(SOURCE, ns)
- failed = False
- finally:
- if failed:
- dump_dict(before, ns)
- else:
- diff_dict(before, ns)
- return {
- k: ns['config'].get(k, ns.get(k, ...))
- for k in keys
- }
|