1# mypy: allow-untyped-defs 2import _warnings 3import os.path 4 5 6# note: implementations 7# copied from cpython's import code 8 9 10# _zip_searchorder defines how we search for a module in the Zip 11# archive: we first search for a package __init__, then for 12# non-package .pyc, and .py entries. The .pyc entries 13# are swapped by initzipimport() if we run in optimized mode. Also, 14# '/' is replaced by path_sep there. 15 16_zip_searchorder = ( 17 ("/__init__.py", True), 18 (".py", False), 19) 20 21 22# Replace any occurrences of '\r\n?' in the input string with '\n'. 23# This converts DOS and Mac line endings to Unix line endings. 24def _normalize_line_endings(source): 25 source = source.replace(b"\r\n", b"\n") 26 source = source.replace(b"\r", b"\n") 27 return source 28 29 30def _resolve_name(name, package, level): 31 """Resolve a relative module name to an absolute one.""" 32 bits = package.rsplit(".", level - 1) 33 if len(bits) < level: 34 raise ValueError("attempted relative import beyond top-level package") 35 base = bits[0] 36 return f"{base}.{name}" if name else base 37 38 39def _sanity_check(name, package, level): 40 """Verify arguments are "sane".""" 41 if not isinstance(name, str): 42 raise TypeError(f"module name must be str, not {type(name)}") 43 if level < 0: 44 raise ValueError("level must be >= 0") 45 if level > 0: 46 if not isinstance(package, str): 47 raise TypeError("__package__ not set to a string") 48 elif not package: 49 raise ImportError("attempted relative import with no known parent package") 50 if not name and level == 0: 51 raise ValueError("Empty module name") 52 53 54def _calc___package__(globals): 55 """Calculate what __package__ should be. 56 57 __package__ is not guaranteed to be defined or could be set to None 58 to represent that its proper value is unknown. 59 60 """ 61 package = globals.get("__package__") 62 spec = globals.get("__spec__") 63 if package is not None: 64 if spec is not None and package != spec.parent: 65 _warnings.warn( # noqa: G010 66 f"__package__ != __spec__.parent ({package!r} != {spec.parent!r})", # noqa: G004 67 ImportWarning, 68 stacklevel=3, 69 ) 70 return package 71 elif spec is not None: 72 return spec.parent 73 else: 74 _warnings.warn( # noqa: G010 75 "can't resolve package from __spec__ or __package__, " 76 "falling back on __name__ and __path__", 77 ImportWarning, 78 stacklevel=3, 79 ) 80 package = globals["__name__"] 81 if "__path__" not in globals: 82 package = package.rpartition(".")[0] 83 return package 84 85 86def _normalize_path(path): 87 """Normalize a path by ensuring it is a string. 88 89 If the resulting string contains path separators, an exception is raised. 90 """ 91 parent, file_name = os.path.split(path) 92 if parent: 93 raise ValueError(f"{path!r} must be only a file name") 94 else: 95 return file_name 96