def handle_specific_packages(self, package): """Packages requiring additional configuration""" if package.name.lower() in ( 'pyqt4', 'pyqt5', 'pyside2', ): # Qt configuration file (where to find Qt) name = 'qt.conf' contents = """[Paths] Prefix = . Binaries = .""" self.create_file( package, name, osp.join('Lib', 'site-packages', package.name), contents, ) self.create_file( package, name, '.', contents.replace( '.', './Lib/site-packages/%s' % package.name, ), ) # pyuic script if package.name.lower() == 'pyqt5': # see http://code.activestate.com/lists/python-list/666469/ tmp_string = r'''@echo off if "%WINPYDIR%"=="" call "%~dp0..\..\scripts\env.bat" "%WINPYDIR%\python.exe" -m PyQt5.uic.pyuic %1 %2 %3 %4 %5 %6 %7 %8 %9''' else: tmp_string = r'''@echo off if "%WINPYDIR%"=="" call "%~dp0..\..\scripts\env.bat" "%WINPYDIR%\python.exe" "%WINPYDIR%\Lib\site-packages\package.name\uic\pyuic.py" %1 %2 %3 %4 %5 %6 %7 %8 %9''' # PyPy adaption: python.exe or pypy3.exe my_exec = osp.basename(utils.get_python_executable(self.target)) tmp_string = tmp_string.replace('python.exe', my_exec) self.create_file( package, 'pyuic%s.bat' % package.name[-1], 'Scripts', tmp_string.replace('package.name', package.name), ) # Adding missing __init__.py files (fixes Issue 8) uic_path = osp.join('Lib', 'site-packages', package.name, 'uic') for dirname in ('Loader', 'port_v2', 'port_v3'): self.create_file( package, '__init__.py', osp.join(uic_path, dirname), '', )
def do_pip_action( self, actions=None, install_options=None ): """Do pip action in a distribution""" my_list = install_options if my_list is None: my_list = [] my_actions = actions if my_actions is None: my_actions = [] executing = osp.join( self.target, '..', 'scripts', 'env.bat' ) if osp.isfile(executing): complement = [ r'&&', 'cd', '/D', self.target, r'&&', utils.get_python_executable(self.target), # Before PyPy: osp.join(self.target, 'python.exe') ] complement += ['-m', 'pip'] else: executing = utils.get_python_executable(self.target) # Before PyPy: osp.join(self.target, 'python.exe') complement = ['-m', 'pip'] try: fname = utils.do_script( this_script=None, python_exe=executing, architecture=self.architecture, verbose=self.verbose, install_options=complement + my_actions + my_list, ) except RuntimeError: if not self.verbose: print("Failed!") raise
def install_script(self, script, install_options=None): try: fname = utils.do_script( script, python_exe=utils.get_python_executable(self.target), # PyPy3 ! architecture=self.architecture, verbose=self.verbose, install_options=install_options, ) except RuntimeError: if not self.verbose: print("Failed!") raise
def __init__(self, target=None, verbose=False, indent=False): self.target = target self.verbose = verbose self.indent = indent # if no target path given, take the current python interpreter one if self.target is None: self.target = os.path.dirname(sys.executable) self.to_be_removed = ([]) # list of directories to be removed later self.version, self.architecture = utils.get_python_infos(target) # name of the exe (python.exe or pypy3;exe) self.short_exe = osp.basename(utils.get_python_executable(self.target))
def get_installed_packages(self, update=False): """Return installed packages""" # Include package installed via pip (not via WPPM) wppm = [] try: if (os.path.dirname(sys.executable) == self.target): # direct way: we interrogate ourself, using official API import pkg_resources, importlib importlib.reload(pkg_resources) pip_list = [(i.key, i.version) for i in pkg_resources.working_set] else: # indirect way: we interrogate something else cmdx = [ utils.get_python_executable(self.target), # PyPy ! '-c', "import pip;from pip._internal.utils.misc import get_installed_distributions as pip_get_installed_distributions ;print('+!+'.join(['%s@+@%s@+@' % (i.key,i.version) for i in pip_get_installed_distributions()]))", ] p = subprocess.Popen( cmdx, shell=True, stdout=subprocess.PIPE, cwd=self.target, ) stdout, stderr = p.communicate() start_at = (2 if sys.version_info >= (3, 0) else 0) pip_list = [ line.split("@+@")[:2] for line in ("%s" % stdout)[start_at:].split("+!+") ] # there are only Packages installed with pip now # create pip package list wppm = [ Package('%s-%s-py2.py3-none-any.whl' % (i[0].replace('-', '_').lower(), i[1]), update=update) for i in pip_list ] except: pass return sorted(wppm, key=lambda tup: tup.name.lower())
def install_bdist_direct(self, package, install_options=None): """Install a package directly !""" self._print( package, "Installing %s" % package.fname.split(".")[-1], ) try: fname = utils.direct_pip_install( package.fname, python_exe=utils.get_python_executable(self.target), # PyPy ! architecture=self.architecture, verbose=self.verbose, install_options=install_options, ) except RuntimeError: if not self.verbose: print("Failed!") raise package = Package(fname) self._print_done()
def uninstall(self, package): """Uninstall package from distribution""" self._print(package, "Uninstalling") if not package.name == 'pip': # trick to get true target (if not current) this_executable_path = self.target this_exec = utils.get_python_executable(self.target) # PyPy ! subprocess.call( [ this_exec, '-m', 'pip', 'uninstall', package.name, '-y', ], cwd=this_executable_path, ) # no more legacy, no package are installed by old non-pip means self._print_done()
def get_installed_packages(self, update=False): """Return installed packages""" # Include package installed via pip (not via WPPM) wppm = [] try: if ( os.path.dirname(sys.executable) == self.target ): # win pip 22.2, we can use pip inspect API pip = piptree.pipdata() pip_list = pip.pip_list() else: # indirect way: we use pip list (for now) cmdx = [ utils.get_python_executable(self.target), # PyPy ! '-m', "pip", "list", ] pip_list_raw = utils.exec_run_cmd(cmdx).splitlines() # pip list gives 2 lines of titles to ignore pip_list = [ l.split() for l in pip_list_raw[2:] ] # there are only Packages installed with pip now # create pip package list wppm = [ Package( '%s-%s-py2.py3-none-any.whl' % (i[0].replace('-', '_').lower(), i[1]) , update=update) for i in pip_list ] except: pass return sorted( wppm, key=lambda tup: tup.name.lower() )
def patch_standard_packages(self, package_name='', to_movable=True): """patch Winpython packages in need""" import filecmp # Adpating to PyPy if 'pypy3' in osp.basename(utils.get_python_executable(self.target)): site_package_place = "\\site-packages\\" else: site_package_place = "\\Lib\\site-packages\\" # 'pywin32' minimal post-install (pywin32_postinstall.py do too much) if (package_name.lower() == "pywin32" or package_name == ''): origin = self.target + site_package_place + "pywin32_system32" destin = self.target if osp.isdir(origin): for name in os.listdir(origin): here, there = ( osp.join(origin, name), osp.join(destin, name), ) if not os.path.exists(there) or not filecmp.cmp( here, there): shutil.copyfile(here, there) # 'pip' to do movable launchers (around line 100) !!!! # rational: https://github.com/pypa/pip/issues/2328 if (package_name.lower() == "pip" or package_name == ''): # ensure pip will create movable launchers # sheb_mov1 = classic way up to WinPython 2016-01 # sheb_mov2 = tried way, but doesn't work for pip (at least) sheb_fix = " executable = get_executable()" sheb_mov1 = " executable = os.path.join(os.path.basename(get_executable()))" sheb_mov2 = " executable = os.path.join('..',os.path.basename(get_executable()))" # Adpating to PyPy the_place = site_package_place + r"pip\_vendor\distlib\scripts.py" print(the_place) if to_movable: utils.patch_sourcefile( self.target + the_place, sheb_fix, sheb_mov1, ) utils.patch_sourcefile( self.target + the_place, sheb_mov2, sheb_mov1, ) else: utils.patch_sourcefile( self.target + the_place, sheb_mov1, sheb_fix, ) utils.patch_sourcefile( self.target + the_place, sheb_mov2, sheb_fix, ) # ensure pip wheel will register relative PATH in 'RECORD' files # will be in standard pip 8.0.3 utils.patch_sourcefile( self.target + (site_package_place + r"pip\wheel.py"), " writer.writerow((f, h, l))", " writer.writerow((normpath(f, lib_dir), h, l))", ) # create movable launchers for previous package installations self.patch_all_shebang(to_movable=to_movable) if (package_name.lower() == "spyder" or package_name == ''): # spyder don't goes on internet without I ask utils.patch_sourcefile( self.target + (site_package_place + r"spyderlib\config\main.py"), "'check_updates_on_startup': True,", "'check_updates_on_startup': False,", ) utils.patch_sourcefile( self.target + (site_package_place + r"spyder\config\main.py"), "'check_updates_on_startup': True,", "'check_updates_on_startup': False,", ) # workaround bad installers if package_name.lower() == "numba": self.create_pybat(['numba', 'pycc']) else: self.create_pybat(package_name.lower())
def register(target, current=True): """Register a Python distribution in Windows registry""" root = (winreg.HKEY_CURRENT_USER if current else winreg.HKEY_LOCAL_MACHINE) # Extensions winreg.SetValueEx( winreg.CreateKey(root, KEY_C % ".py"), "", 0, winreg.REG_SZ, "Python.File", ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C % ".pyw"), "", 0, winreg.REG_SZ, "Python.NoConFile", ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C % ".pyc"), "", 0, winreg.REG_SZ, "Python.CompiledFile", ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C % ".pyo"), "", 0, winreg.REG_SZ, "Python.CompiledFile", ) # MIME types winreg.SetValueEx( winreg.CreateKey(root, KEY_C % ".py"), "Content Type", 0, winreg.REG_SZ, "text/plain", ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C % ".pyw"), "Content Type", 0, winreg.REG_SZ, "text/plain", ) # Verbs python = utils.get_python_executable(target) # PyPy ! pythonw = python[:-4] + 'w.exe' spyder = osp.abspath(osp.join(target, os.pardir, 'Spyder.exe')) if not osp.isfile(spyder): spyder = '%s" "%s\Scripts\spyder' % ( pythonw, target, ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C2 % ("", "open")), "", 0, winreg.REG_SZ, '"%s" "%%1" %%*' % python, ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C2 % ("NoCon", "open")), "", 0, winreg.REG_SZ, '"%s" "%%1" %%*' % pythonw, ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C2 % ("Compiled", "open")), "", 0, winreg.REG_SZ, '"%s" "%%1" %%*' % python, ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C2 % ("", EWI)), "", 0, winreg.REG_SZ, '"%s" "%s\Lib\idlelib\idle.pyw" -n -e "%%1"' % (pythonw, target), ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C2 % ("NoCon", EWI)), "", 0, winreg.REG_SZ, '"%s" "%s\Lib\idlelib\idle.pyw" -n -e "%%1"' % (pythonw, target), ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C2 % ("", EWS)), "", 0, winreg.REG_SZ, '"%s" "%%1"' % spyder, ) winreg.SetValueEx( winreg.CreateKey(root, KEY_C2 % ("NoCon", EWS)), "", 0, winreg.REG_SZ, '"%s" "%%1"' % spyder, ) # Drop support handler = "{60254CA5-953B-11CF-8C96-00AA00B8708C}" for ftype in ("", "NoCon", "Compiled"): winreg.SetValueEx( winreg.CreateKey(root, KEY_DROP1 % ftype), "", 0, winreg.REG_SZ, handler, ) # Icons dlls = osp.join(target, 'DLLs') winreg.SetValueEx( winreg.CreateKey(root, KEY_I % ""), "", 0, winreg.REG_SZ, r'%s\py.ico' % dlls, ) winreg.SetValueEx( winreg.CreateKey(root, KEY_I % "NoCon"), "", 0, winreg.REG_SZ, r'%s\py.ico' % dlls, ) winreg.SetValueEx( winreg.CreateKey(root, KEY_I % "Compiled"), "", 0, winreg.REG_SZ, r'%s\pyc.ico' % dlls, ) # Descriptions winreg.SetValueEx( winreg.CreateKey(root, KEY_D % ""), "", 0, winreg.REG_SZ, "Python File", ) winreg.SetValueEx( winreg.CreateKey(root, KEY_D % "NoCon"), "", 0, winreg.REG_SZ, "Python File (no console)", ) winreg.SetValueEx( winreg.CreateKey(root, KEY_D % "Compiled"), "", 0, winreg.REG_SZ, "Compiled Python File", ) # PythonCore entries short_version = utils.get_python_infos(target)[0] long_version = utils.get_python_long_version(target) key_core = (KEY_S1 % short_version) + r'\%s' winreg.SetValueEx( winreg.CreateKey(root, key_core % 'InstallPath'), "", 0, winreg.REG_SZ, target, ) winreg.SetValueEx( winreg.CreateKey(root, key_core % r'InstallPath\InstallGroup'), "", 0, winreg.REG_SZ, "Python %s" % short_version, ) winreg.SetValueEx( winreg.CreateKey(root, key_core % 'Modules'), "", 0, winreg.REG_SZ, "", ) winreg.SetValueEx( winreg.CreateKey(root, key_core % 'PythonPath'), "", 0, winreg.REG_SZ, r"%s\Lib;%s\DLLs" % (target, target), ) winreg.SetValueEx( winreg.CreateKey( root, key_core % r'Help\Main Python Documentation', ), "", 0, winreg.REG_SZ, r"%s\Doc\python%s.chm" % (target, long_version), ) # Create start menu entries for all WinPython launchers for path, desc, fname in _get_shortcut_data(target, current=current): utils.create_shortcut(path, desc, fname) # Register the Python ActiveX Scripting client (requires pywin32) axscript = osp.join( target, 'Lib', 'site-packages', 'win32comext', 'axscript', 'client', 'pyscript.py', ) if osp.isfile(axscript): subprocess.call('"%s" "%s"' % (python, axscript), cwd=target) else: print( 'Unable to register ActiveX: please install pywin32', file=sys.stderr, )