utils.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  2. # For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
  3. # Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
  4. from __future__ import annotations
  5. import contextlib
  6. import os
  7. import sys
  8. from collections.abc import Generator, Iterator
  9. from copy import copy
  10. from pathlib import Path
  11. from typing import TextIO
  12. @contextlib.contextmanager
  13. def _patch_streams(out: TextIO) -> Iterator[None]:
  14. """Patch and subsequently reset a text stream."""
  15. sys.stderr = sys.stdout = out
  16. try:
  17. yield
  18. finally:
  19. sys.stderr = sys.__stderr__
  20. sys.stdout = sys.__stdout__
  21. @contextlib.contextmanager
  22. def _test_sys_path(
  23. replacement_sys_path: list[str] | None = None,
  24. ) -> Generator[None, None, None]:
  25. original_path = sys.path
  26. try:
  27. if replacement_sys_path is not None:
  28. sys.path = copy(replacement_sys_path)
  29. yield
  30. finally:
  31. sys.path = original_path
  32. @contextlib.contextmanager
  33. def _test_cwd(
  34. current_working_directory: str | Path | None = None,
  35. ) -> Generator[None, None, None]:
  36. original_dir = os.getcwd()
  37. try:
  38. if current_working_directory is not None:
  39. os.chdir(current_working_directory)
  40. yield
  41. finally:
  42. os.chdir(original_dir)
  43. @contextlib.contextmanager
  44. def _test_environ_pythonpath(
  45. new_pythonpath: str | None = None,
  46. ) -> Generator[None, None, None]:
  47. original_pythonpath = os.environ.get("PYTHONPATH")
  48. if new_pythonpath:
  49. os.environ["PYTHONPATH"] = new_pythonpath
  50. elif new_pythonpath is None and original_pythonpath is not None:
  51. # If new_pythonpath is None, make sure to delete PYTHONPATH if present
  52. del os.environ["PYTHONPATH"]
  53. try:
  54. yield
  55. finally:
  56. if original_pythonpath is not None:
  57. os.environ["PYTHONPATH"] = original_pythonpath
  58. elif "PYTHONPATH" in os.environ:
  59. del os.environ["PYTHONPATH"]
  60. def create_files(paths: list[str], chroot: str = ".") -> None:
  61. """Creates directories and files found in <path>.
  62. :param list paths: list of relative paths to files or directories
  63. :param str chroot: the root directory in which paths will be created
  64. >>> from os.path import isdir, isfile
  65. >>> isdir('/tmp/a')
  66. False
  67. >>> create_files(['a/b/foo.py', 'a/b/c/', 'a/b/c/d/e.py'], '/tmp')
  68. >>> isdir('/tmp/a')
  69. True
  70. >>> isdir('/tmp/a/b/c')
  71. True
  72. >>> isfile('/tmp/a/b/c/d/e.py')
  73. True
  74. >>> isfile('/tmp/a/b/foo.py')
  75. True
  76. """
  77. dirs, files = set(), set()
  78. for path in paths:
  79. path = os.path.join(chroot, path)
  80. filename = os.path.basename(path)
  81. # path is a directory path
  82. if not filename:
  83. dirs.add(path)
  84. # path is a filename path
  85. else:
  86. dirs.add(os.path.dirname(path))
  87. files.add(path)
  88. for dirpath in dirs:
  89. if not os.path.isdir(dirpath):
  90. os.makedirs(dirpath)
  91. for filepath in files:
  92. with open(filepath, "w", encoding="utf-8"):
  93. pass