util.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. # Copyright (c) 2014-present PlatformIO <contact@platformio.org>
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import io
  15. import logging
  16. import os
  17. import platform
  18. import re
  19. import shutil
  20. import stat
  21. import sys
  22. import tarfile
  23. import requests
  24. IS_WINDOWS = sys.platform.lower().startswith("win")
  25. IS_MACOS = sys.platform.lower() == "darwin"
  26. log = logging.getLogger(__name__)
  27. def get_source_dir():
  28. curpath = os.path.realpath(__file__)
  29. if not os.path.isfile(curpath):
  30. for p in sys.path:
  31. if os.path.isfile(os.path.join(p, __file__)):
  32. curpath = os.path.join(p, __file__)
  33. break
  34. return os.path.dirname(curpath)
  35. def get_pythonexe_path():
  36. return os.environ.get("PYTHONEXEPATH", os.path.normpath(sys.executable))
  37. def expanduser(path):
  38. """
  39. Be compatible with Python 3.8, on Windows skip HOME and check for USERPROFILE
  40. """
  41. if not IS_WINDOWS or not path.startswith("~") or "USERPROFILE" not in os.environ:
  42. return os.path.expanduser(path)
  43. return os.environ["USERPROFILE"] + path[1:]
  44. def has_non_ascii_char(text):
  45. for c in text:
  46. if ord(c) >= 128:
  47. return True
  48. return False
  49. def rmtree(path):
  50. def _onerror(func, path, __):
  51. st_mode = os.stat(path).st_mode
  52. if st_mode & stat.S_IREAD:
  53. os.chmod(path, st_mode | stat.S_IWRITE)
  54. func(path)
  55. return shutil.rmtree(path, onerror=_onerror)
  56. def find_file(name, path):
  57. for root, _, files in os.walk(path):
  58. if name in files:
  59. return os.path.join(root, name)
  60. return None
  61. def safe_create_dir(path, raise_exception=False):
  62. try:
  63. os.makedirs(path)
  64. return path
  65. except Exception as e: # pylint: disable=broad-except
  66. if raise_exception:
  67. raise e
  68. def download_file(url, dst, cache=True):
  69. if cache:
  70. content_length = requests.head(url).headers.get("Content-Length")
  71. if os.path.isfile(dst) and content_length == os.path.getsize(dst):
  72. log.debug("Getting from cache: %s", dst)
  73. return dst
  74. resp = requests.get(url, stream=True)
  75. itercontent = resp.iter_content(chunk_size=io.DEFAULT_BUFFER_SIZE)
  76. safe_create_dir(os.path.dirname(dst))
  77. with open(dst, "wb") as fp:
  78. for chunk in itercontent:
  79. fp.write(chunk)
  80. return dst
  81. def unpack_archive(src, dst):
  82. assert src.endswith("tar.gz")
  83. with tarfile.open(src, mode="r:gz") as fp:
  84. fp.extractall(dst)
  85. return dst
  86. def get_installer_script():
  87. return os.path.abspath(sys.argv[0])
  88. def get_systype():
  89. type_ = platform.system().lower()
  90. arch = platform.machine().lower()
  91. if type_ == "windows":
  92. arch = "amd64" if platform.architecture()[0] == "64bit" else "x86"
  93. return "%s_%s" % (type_, arch) if arch else type_
  94. def safe_remove_dir(path, raise_exception=False):
  95. try:
  96. return rmtree(path)
  97. except Exception as e: # pylint: disable=broad-except
  98. if raise_exception:
  99. raise e
  100. def pepver_to_semver(pepver):
  101. return re.sub(r"(\.\d+)\.?(dev|a|b|rc|post)", r"\1-\2.", pepver, 1)