Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/setuptools/_path.py: 41%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

34 statements  

1from __future__ import annotations 

2 

3import contextlib 

4import os 

5import sys 

6from typing import TYPE_CHECKING, Union 

7 

8if TYPE_CHECKING: 

9 from typing_extensions import TypeAlias 

10 

11 

12from more_itertools import unique_everseen 

13 

14if sys.version_info >= (3, 9): 

15 StrPath: TypeAlias = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath 

16else: 

17 StrPath: TypeAlias = Union[str, os.PathLike] 

18 

19 

20def ensure_directory(path): 

21 """Ensure that the parent directory of `path` exists""" 

22 dirname = os.path.dirname(path) 

23 os.makedirs(dirname, exist_ok=True) 

24 

25 

26def same_path(p1: StrPath, p2: StrPath) -> bool: 

27 """Differs from os.path.samefile because it does not require paths to exist. 

28 Purely string based (no comparison between i-nodes). 

29 >>> same_path("a/b", "./a/b") 

30 True 

31 >>> same_path("a/b", "a/./b") 

32 True 

33 >>> same_path("a/b", "././a/b") 

34 True 

35 >>> same_path("a/b", "./a/b/c/..") 

36 True 

37 >>> same_path("a/b", "../a/b/c") 

38 False 

39 >>> same_path("a", "a/b") 

40 False 

41 """ 

42 return normpath(p1) == normpath(p2) 

43 

44 

45def normpath(filename: StrPath) -> str: 

46 """Normalize a file/dir name for comparison purposes.""" 

47 # See pkg_resources.normalize_path for notes about cygwin 

48 file = os.path.abspath(filename) if sys.platform == 'cygwin' else filename 

49 return os.path.normcase(os.path.realpath(os.path.normpath(file))) 

50 

51 

52@contextlib.contextmanager 

53def paths_on_pythonpath(paths): 

54 """ 

55 Add the indicated paths to the head of the PYTHONPATH environment 

56 variable so that subprocesses will also see the packages at 

57 these paths. 

58 

59 Do this in a context that restores the value on exit. 

60 

61 >>> getfixture('monkeypatch').setenv('PYTHONPATH', 'anything') 

62 >>> with paths_on_pythonpath(['foo', 'bar']): 

63 ... assert 'foo' in os.environ['PYTHONPATH'] 

64 ... assert 'anything' in os.environ['PYTHONPATH'] 

65 >>> os.environ['PYTHONPATH'] 

66 'anything' 

67 

68 >>> getfixture('monkeypatch').delenv('PYTHONPATH') 

69 >>> with paths_on_pythonpath(['foo', 'bar']): 

70 ... assert 'foo' in os.environ['PYTHONPATH'] 

71 >>> os.environ.get('PYTHONPATH') 

72 """ 

73 nothing = object() 

74 orig_pythonpath = os.environ.get('PYTHONPATH', nothing) 

75 current_pythonpath = os.environ.get('PYTHONPATH', '') 

76 try: 

77 prefix = os.pathsep.join(unique_everseen(paths)) 

78 to_join = filter(None, [prefix, current_pythonpath]) 

79 new_path = os.pathsep.join(to_join) 

80 if new_path: 

81 os.environ['PYTHONPATH'] = new_path 

82 yield 

83 finally: 

84 if orig_pythonpath is nothing: 

85 os.environ.pop('PYTHONPATH', None) 

86 else: 

87 os.environ['PYTHONPATH'] = orig_pythonpath