mirror of https://github.com/pypa/hatch.git
194 lines
4.1 KiB
Python
194 lines
4.1 KiB
Python
import glob
|
|
import os
|
|
import platform
|
|
import re
|
|
import shutil
|
|
from base64 import urlsafe_b64encode
|
|
from datetime import datetime
|
|
from contextlib import contextmanager
|
|
from pathlib import Path
|
|
from tempfile import TemporaryDirectory
|
|
|
|
ON_WINDOWS = False
|
|
if os.name == 'nt' or platform.system() == 'Windows': # no cov
|
|
ON_WINDOWS = True
|
|
|
|
NEED_SUBPROCESS_SHELL = ON_WINDOWS
|
|
|
|
VENV_FLAGS = {
|
|
'_HATCHING_',
|
|
'VIRTUAL_ENV',
|
|
'CONDA_PREFIX'
|
|
}
|
|
|
|
|
|
def venv_active():
|
|
return bool(VENV_FLAGS & set(os.environ))
|
|
|
|
|
|
def get_random_venv_name():
|
|
# Will be length 4, so 16777216 possibilities.
|
|
return urlsafe_b64encode(os.urandom(3)).decode()
|
|
|
|
|
|
def get_proper_python(): # no cov
|
|
if not venv_active():
|
|
default_python = os.environ.get('_DEFAULT_PYTHON_', None)
|
|
if default_python:
|
|
return default_python
|
|
elif not ON_WINDOWS:
|
|
return 'python3'
|
|
return 'python'
|
|
|
|
|
|
def get_proper_pip(): # no cov
|
|
if not venv_active():
|
|
default_pip = os.environ.get('_DEFAULT_PIP_', None)
|
|
if default_pip:
|
|
return default_pip
|
|
elif not ON_WINDOWS:
|
|
return 'pip3'
|
|
return 'pip'
|
|
|
|
|
|
def get_admin_command(): # no cov
|
|
if ON_WINDOWS:
|
|
return [
|
|
'runas', r'/user:{}\{}'.format(
|
|
platform.node() or os.environ.get('USERDOMAIN', ''),
|
|
os.environ.get('_DEFAULT_ADMIN_', 'Administrator')
|
|
)
|
|
]
|
|
# Should we indeed use -H here?
|
|
else:
|
|
admin = os.environ.get('_DEFAULT_ADMIN_', '')
|
|
return ['sudo', '-H'] + (['--user={}'.format(admin)] if admin else [])
|
|
|
|
|
|
def get_requirements_file(d, dev=False):
|
|
d = d or os.getcwd()
|
|
|
|
reqs = os.path.join(d, 'requirements.txt')
|
|
if dev or not os.path.exists(reqs):
|
|
paths = set(glob.iglob(os.path.join(d, '*requirements*.txt')))
|
|
paths.discard(reqs)
|
|
if not paths:
|
|
return
|
|
reqs = sorted(paths)[0]
|
|
|
|
return reqs
|
|
|
|
|
|
def ensure_dir_exists(d):
|
|
if not os.path.exists(d):
|
|
os.makedirs(d)
|
|
|
|
|
|
def create_file(fname):
|
|
ensure_dir_exists(os.path.dirname(os.path.abspath(fname)))
|
|
with open(fname, 'a'):
|
|
os.utime(fname, times=None)
|
|
|
|
|
|
def copy_path(path, d):
|
|
if os.path.isdir(path):
|
|
shutil.copytree(
|
|
path,
|
|
os.path.join(d, basepath(path)),
|
|
copy_function=shutil.copy
|
|
)
|
|
else:
|
|
shutil.copy(path, d)
|
|
|
|
|
|
def remove_path(path):
|
|
try:
|
|
shutil.rmtree(path)
|
|
except (FileNotFoundError, OSError):
|
|
try:
|
|
os.remove(path)
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
|
|
def resolve_path(path):
|
|
try:
|
|
path = str(Path(path).resolve())
|
|
# FUTURE: Remove this when we drop 3.5.
|
|
except FileNotFoundError: # no cov
|
|
return ''
|
|
return path if os.path.exists(path) else ''
|
|
|
|
|
|
def basepath(path):
|
|
return os.path.basename(os.path.normpath(path))
|
|
|
|
|
|
def get_current_year():
|
|
return str(datetime.now().year)
|
|
|
|
|
|
def normalize_package_name(package_name):
|
|
return re.sub(r"[-_.]+", "_", package_name).lower()
|
|
|
|
|
|
@contextmanager
|
|
def chdir(d, cwd=None):
|
|
origin = cwd or os.getcwd()
|
|
os.chdir(d)
|
|
|
|
try:
|
|
yield
|
|
finally:
|
|
os.chdir(origin)
|
|
|
|
|
|
@contextmanager
|
|
def temp_chdir(cwd=None):
|
|
with TemporaryDirectory() as d:
|
|
origin = cwd or os.getcwd()
|
|
os.chdir(d)
|
|
|
|
try:
|
|
yield resolve_path(d)
|
|
finally:
|
|
os.chdir(origin)
|
|
|
|
|
|
@contextmanager
|
|
def env_vars(evars):
|
|
old_evars = {}
|
|
|
|
for ev in evars:
|
|
if ev in os.environ:
|
|
old_evars[ev] = os.environ[ev]
|
|
os.environ[ev] = evars[ev]
|
|
|
|
try:
|
|
yield
|
|
finally:
|
|
for ev in evars:
|
|
if ev in old_evars:
|
|
os.environ[ev] = old_evars[ev]
|
|
else:
|
|
os.environ.pop(ev)
|
|
|
|
|
|
@contextmanager
|
|
def temp_move_path(path, d):
|
|
if os.path.exists(path):
|
|
dst = shutil.move(path, d)
|
|
|
|
try:
|
|
yield dst
|
|
finally:
|
|
try:
|
|
os.replace(dst, path)
|
|
except OSError: # no cov
|
|
shutil.move(dst, path)
|
|
else:
|
|
try:
|
|
yield
|
|
finally:
|
|
remove_path(path)
|