Doa-doa's picture
Upload folder using huggingface_hub
72268ee
# (c) Anaconda, Inc. / https://anaconda.com
# All Rights Reserved
# This file is under the BSD license
# Helper script which is called from within the nsis install process
# on Windows. The fact that we put this file into the standard library
# directory is merely a convenience. This way, functionally can easily
# be tested in an installation.
import os
import re
import sys
import traceback
from os import environ
from os.path import basename, exists, isfile, join
from subprocess import STDOUT, CalledProcessError, check_output
try:
import winreg
except ImportError:
import _winreg as winreg
ROOT_PREFIX = sys.prefix
# Install an exception hook which pops up a message box.
# Ideally, exceptions will get returned to NSIS and logged there,
# etc, but this is a stopgap solution for now.
old_excepthook = sys.excepthook
# this sucks. It is copied from _nsis.py because it can't be a relative import.
# _nsis.py must be standalone.
def ensure_comspec_set():
if basename(environ.get("COMSPEC", "")).lower() != "cmd.exe":
cmd_exe = join(environ.get('SystemRoot'), 'System32', 'cmd.exe')
if not isfile(cmd_exe):
cmd_exe = join(environ.get('windir'), 'System32', 'cmd.exe')
if not isfile(cmd_exe):
print("cmd.exe could not be found. "
"Looked in SystemRoot and windir env vars.\n")
else:
environ['COMSPEC'] = cmd_exe
def gui_excepthook(exctype, value, tb):
try:
import ctypes
import traceback
MB_ICONERROR = 0x00000010
title = u'Installation Error'
msg = u''.join(traceback.format_exception(exctype, value, tb))
ctypes.windll.user32.MessageBoxW(0, msg, title, MB_ICONERROR)
finally:
# Also call the old exception hook to let it do
# its thing too.
old_excepthook(exctype, value, tb)
sys.excepthook = gui_excepthook
# If pythonw is being run, there may be no write function
if sys.stdout and sys.stdout.write:
out = sys.stdout.write
err = sys.stderr.write
else:
import ctypes
OutputDebugString = ctypes.windll.kernel32.OutputDebugStringW
OutputDebugString.argtypes = [ctypes.c_wchar_p]
def out(x):
OutputDebugString('_nsis.py: ' + x)
def err(x):
OutputDebugString('_nsis.py: Error: ' + x)
class NSISReg:
def __init__(self, reg_path):
self.reg_path = reg_path
if exists(join(ROOT_PREFIX, '.nonadmin')):
self.main_key = winreg.HKEY_CURRENT_USER
else:
self.main_key = winreg.HKEY_LOCAL_MACHINE
def set(self, name, value):
try:
winreg.CreateKey(self.main_key, self.reg_path)
registry_key = winreg.OpenKey(self.main_key, self.reg_path, 0,
winreg.KEY_WRITE)
winreg.SetValueEx(registry_key, name, 0, winreg.REG_SZ, value)
winreg.CloseKey(registry_key)
return True
except WindowsError:
return False
def get(self, name):
try:
registry_key = winreg.OpenKey(self.main_key, self.reg_path, 0,
winreg.KEY_READ)
value, regtype = winreg.QueryValueEx(registry_key, name)
winreg.CloseKey(registry_key)
return value
except WindowsError:
return None
def mk_menus(remove=False, prefix=None, pkg_names=None, root_prefix=None):
try:
import menuinst
except (ImportError, OSError):
return
if prefix is None:
prefix = sys.prefix
if root_prefix is None:
root_prefix = sys.prefix
menu_dir = join(prefix, 'Menu')
if not os.path.isdir(menu_dir):
return
for fn in os.listdir(menu_dir):
if not fn.endswith('.json'):
continue
if pkg_names is not None and len(pkg_names) > 0 and fn[:-5] not in pkg_names:
# skip when not in the list of menus to create
# when installing, the pkg_names list is specified, otherwise not
# and we don't skip to try to remove shortcuts
continue
shortcut = join(menu_dir, fn)
try:
menuinst.install(shortcut, remove, prefix=prefix,
root_prefix=root_prefix)
except Exception as e:
out("Failed to process %s...\n" % shortcut)
err("Error: %s\n" % str(e))
err("Traceback:\n%s\n" % traceback.format_exc(20))
else:
out("Processed %s successfully.\n" % shortcut)
def mk_dirs():
envs_dir = join(ROOT_PREFIX, 'envs')
if not exists(envs_dir):
os.mkdir(envs_dir)
def get_conda_envs_from_python_api():
try:
from conda.cli.python_api import Commands, run_command
except (ImportError, OSError):
return
from json import loads
c_stdout, c_stderr, return_code = run_command(Commands.INFO, "--json")
json_conda_info = loads(c_stdout)
return json_conda_info["envs"]
get_conda_envs = get_conda_envs_from_python_api
def rm_menus(prefix=None, root_prefix=None):
try:
import menuinst # noqa
from conda.base.context import context
except (ImportError, OSError):
return
try:
envs = get_conda_envs()
envs = list(envs) # make sure `envs` is iterable
except Exception as e:
out("Failed to get conda environments list\n")
err("Error: %s\n" % str(e))
err("Traceback:\n%s\n" % traceback.format_exc(20))
if prefix is not None:
out("Will only remove shortcuts created from '%s'" % prefix)
mk_menus(remove=True, prefix=prefix, root_prefix=root_prefix)
else:
envs_dirs = list(context.envs_dirs)
if prefix is not None:
envs_dirs.append(prefix)
for env in envs:
env = str(env) # force `str` so that `os.path.join` doesn't fail
for envs_dir in envs_dirs:
# Make sure the environment is from one of the directory in
# `envs_dirs` to avoid picking up environment from other
# distributions. Not perfect but better than no checking
if envs_dir in env:
mk_menus(remove=True, prefix=env, root_prefix=root_prefix)
def run_post_install():
"""
call the post install script, if the file exists
"""
path = join(ROOT_PREFIX, 'pkgs', 'post_install.bat')
if not isfile(path):
return
env = os.environ.copy()
env.setdefault('PREFIX', str(ROOT_PREFIX))
cmd_exe = os.path.join(os.environ['SystemRoot'], 'System32', 'cmd.exe')
if not os.path.isfile(cmd_exe):
cmd_exe = os.path.join(os.environ['windir'], 'System32', 'cmd.exe')
if not os.path.isfile(cmd_exe):
err("Error: running %s failed. cmd.exe could not be found. "
"Looked in SystemRoot and windir env vars.\n" % path)
if os.environ.get("NSIS_SCRIPTS_RAISE_ERRORS"):
sys.exit(1)
args = [cmd_exe, '/d', '/c', path]
import subprocess
try:
subprocess.check_call(args, env=env)
except subprocess.CalledProcessError:
err("Error: running %s failed\n" % path)
if os.environ.get("NSIS_SCRIPTS_RAISE_ERRORS"):
sys.exit(1)
def run_pre_uninstall():
"""
call the pre uninstall script, if the file exists
"""
path = join(ROOT_PREFIX, 'pre_uninstall.bat')
if not isfile(path):
return
env = os.environ.copy()
env.setdefault('PREFIX', str(ROOT_PREFIX))
cmd_exe = os.path.join(os.environ['SystemRoot'], 'System32', 'cmd.exe')
if not os.path.isfile(cmd_exe):
cmd_exe = os.path.join(os.environ['windir'], 'System32', 'cmd.exe')
if not os.path.isfile(cmd_exe):
err("Error: running %s failed. cmd.exe could not be found. "
"Looked in SystemRoot and windir env vars.\n" % path)
if os.environ.get("NSIS_SCRIPTS_RAISE_ERRORS"):
sys.exit(1)
args = [cmd_exe, '/d', '/c', path]
import subprocess
try:
subprocess.check_call(args, env=env)
except subprocess.CalledProcessError:
err("Error: running %s failed\n" % path)
if os.environ.get("NSIS_SCRIPTS_RAISE_ERRORS"):
sys.exit(1)
allusers = (not exists(join(ROOT_PREFIX, '.nonadmin')))
# out('allusers is %s\n' % allusers)
# This must be the same as conda's binpath_from_arg() in conda/cli/activate.py
PATH_SUFFIXES = ('',
os.path.join('Library', 'mingw-w64', 'bin'),
os.path.join('Library', 'usr', 'bin'),
os.path.join('Library', 'bin'),
'Scripts')
def remove_from_path(root_prefix=None):
from _system_path import broadcast_environment_settings_change, remove_from_system_path
if root_prefix is None:
root_prefix = ROOT_PREFIX
for path in [os.path.normpath(os.path.join(root_prefix, path_suffix))
for path_suffix in PATH_SUFFIXES]:
remove_from_system_path(path, allusers)
broadcast_environment_settings_change()
def add_to_path(pyversion, arch):
from _system_path import (
add_to_system_path,
broadcast_environment_settings_change,
get_previous_install_prefixes,
)
# If a previous Anaconda install attempt to this location left remnants,
# remove those.
remove_from_path(ROOT_PREFIX)
# If a previously registered Anaconda install left remnants, remove those.
try:
old_prefixes = get_previous_install_prefixes(pyversion, arch, allusers)
except IOError:
old_prefixes = []
for prefix in old_prefixes:
out('Removing old installation at %s from PATH (if any entries get found)\n' % (prefix))
remove_from_path(prefix)
# add Anaconda to the path
add_to_system_path([os.path.normpath(os.path.join(ROOT_PREFIX, path_suffix))
for path_suffix in PATH_SUFFIXES], allusers)
broadcast_environment_settings_change()
def rm_regkeys():
cmdproc_reg_entry = NSISReg(r'Software\Microsoft\Command Processor')
cmdproc_autorun_val = cmdproc_reg_entry.get('AutoRun')
conda_hook_regex_pat = r'((\s+&\s+)?(if +exist)?(\s*?\"[^\"]*?conda[-_]hook\.bat\"))'
if join(ROOT_PREFIX, 'condabin') in (cmdproc_autorun_val or ''):
cmdproc_autorun_newval = re.sub(conda_hook_regex_pat, '',
cmdproc_autorun_val)
try:
cmdproc_reg_entry.set('AutoRun', cmdproc_autorun_newval)
except Exception:
# Hey, at least we made an attempt to cleanup
pass
def win_del(dirname):
# check_output uses comspec as the default shell when setting the parameter `shell=True`
ensure_comspec_set()
out = "unknown error (exception not caught)"
# first, remove all files
try:
out = check_output('DEL /F/Q/S *.* > NUL', shell=True, stderr=STDOUT, cwd=dirname)
except CalledProcessError as e:
# error code 5 indicates a permission error. We ignore those, but raise for anything else
if e.returncode != 5:
print("Removing folder {} the fast way failed. "
"Output was: {}".format(dirname, out))
raise
else:
print("removing dir contents the fast way failed. "
"Output was: {}".format(out))
else:
print("Unexpected error removing dirname {}. "
"Uninstall was probably not successful".format(dirname))
# next, remove folder hierarchy
try:
out = check_output('RD /S /Q "{}" > NUL'.format(dirname), shell=True, stderr=STDOUT)
except CalledProcessError as e:
# error code 5 indicates a permission error. We ignore those, but raise for anything else
if e.returncode != 5:
print("Removing folder {} the fast way failed. "
"Output was: {}".format(dirname, out))
raise
else:
print("Removing directory folders the fast way failed. "
"Output was: {}".format(out))
else:
print("Unexpected error removing dirname {}. "
"Uninstall was probably not successful".format(dirname))
def main():
cmd = sys.argv[1].strip()
if cmd == 'mkmenus':
pkg_names = [s.strip() for s in sys.argv[2:]]
mk_menus(remove=False, pkg_names=pkg_names)
elif cmd == 'post_install':
run_post_install()
elif cmd == 'rmmenus':
rm_menus()
elif cmd == 'rmreg':
rm_regkeys()
elif cmd == 'mkdirs':
mk_dirs()
elif cmd == 'addpath':
# These checks are probably overkill, but could be useful
# if I forget to update something that uses this code.
if len(sys.argv) > 2:
pyver = sys.argv[2]
else:
pyver = '%s.%s.%s' % (sys.version_info.major,
sys.version_info.minor,
sys.version_info.micro)
if len(sys.argv) > 3:
arch = sys.argv[2]
else:
arch = '32-bit' if tuple.__itemsize__ == 4 else '64-bit'
add_to_path(pyver, arch)
elif cmd == 'rmpath':
remove_from_path()
elif cmd == 'pre_uninstall':
run_pre_uninstall()
elif cmd == 'del':
assert len(sys.argv) == 3
win_del(sys.argv[2].strip())
else:
sys.exit("ERROR: did not expect %r" % cmd)
if __name__ == '__main__':
main()