diff --git a/winpython/utils.py b/winpython/utils.py index 324403cc..7302e943 100644 --- a/winpython/utils.py +++ b/winpython/utils.py @@ -29,16 +29,16 @@ def get_python_executable(path=None): """Return the path to the Python executable.""" - python_path = sys.executable if path is None else path - base_dir = Path(python_path).parent if not Path(python_path).is_dir() else Path(python_path) + python_path = Path(path) if path else Path(sys.executable) + base_dir = python_path if python_path.is_dir() else python_path.parent python_exe = base_dir / 'python.exe' pypy_exe = base_dir / 'pypy3.exe' # For PyPy return str(python_exe if python_exe.is_file() else pypy_exe) def get_site_packages_path(path=None): """Return the path to the Python site-packages directory.""" - python_path = sys.executable if path is None else path - base_dir = Path(python_path).parent if not Path(python_path).is_dir() else Path(python_path) + python_path = Path(path) if path else Path(sys.executable) + base_dir = python_path if python_path.is_dir() else python_path.parent site_packages = base_dir / 'Lib' / 'site-packages' pypy_site_packages = base_dir / 'site-packages' # For PyPy return str(pypy_site_packages if pypy_site_packages.is_dir() else site_packages) @@ -322,40 +322,33 @@ def buildflit_wininst(root, python_exe=None, copy_to=None, verbose=False): if verbose: subprocess.call(cmd, cwd=root) else: - process = subprocess.Popen(cmd, cwd=root, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - process.communicate() - process.stdout.close() - process.stderr.close() - distdir = str(Path(root) / 'dist') - if not Path(distdir).is_dir(): + subprocess.Popen(cmd, cwd=root, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + distdir = Path(root) / 'dist' + if not distdir.is_dir(): raise RuntimeError( "Build failed: see package README file for further details regarding installation requirements.\n\n" "For more concrete debugging infos, please try to build the package from the command line:\n" "1. Open a WinPython command prompt\n" "2. Change working directory to the appropriate folder\n" - "3. Type `python -m filt build`" + "3. Type `python -m flit build`" ) - for distname in os.listdir(distdir): if re.match(SOURCE_PATTERN, distname) or re.match(WHEELBIN_PATTERN, distname): break else: raise RuntimeError(f"Build failed: not a pure Python package? {distdir}") - src_fname = str(Path(distdir) / distname) + src_fname = distdir / distname if copy_to: - dst_fname = str(Path(copy_to) / distname) + dst_fname = Path(copy_to) / distname shutil.move(src_fname, dst_fname) if verbose: print(f"Move: {src_fname} --> {dst_fname}") - return dst_fname - return src_fname def direct_pip_install(fname, python_exe=None, verbose=False, install_options=None): """Direct install via python -m pip !""" python_exe = python_exe or sys.executable - myroot = str(Path(python_exe).parent) - + myroot = Path(python_exe).parent cmd = [python_exe, "-m", "pip", "install"] + (install_options or []) + [fname] if not verbose: process = subprocess.Popen(cmd, cwd=myroot, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -374,15 +367,12 @@ def direct_pip_install(fname, python_exe=None, verbose=False, install_options=No def do_script(this_script, python_exe=None, copy_to=None, verbose=False, install_options=None): """Execute a script (get-pip typically).""" python_exe = python_exe or sys.executable - myroot = os.path.dirname(python_exe) + myroot = Path(python_exe).parent # cmd = [python_exe, myroot + r'\Scripts\pip-script.py', 'install'] cmd = [python_exe] + (install_options or []) + ([this_script] if this_script else []) print("Executing ", cmd) if not verbose: - process = subprocess.Popen(cmd, cwd=myroot, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - process.communicate() - process.stdout.close() - process.stderr.close() + subprocess.Popen(cmd, cwd=myroot, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() else: subprocess.call(cmd, cwd=myroot) print("Executed ", cmd) @@ -406,9 +396,9 @@ def normalize(this): def get_package_metadata(database, name): """Extract infos (description, url) from the local database.""" - DATA_PATH = str(Path(sys.modules['winpython'].__file__).parent / 'data') + DATA_PATH = Path(sys.modules['winpython'].__file__).parent / 'data' db = cp.ConfigParser() - filepath = Path(database) if Path(database).is_absolute() else Path(DATA_PATH) / database + filepath = Path(database) if Path(database).is_absolute() else DATA_PATH / database db.read_file(open(str(filepath), encoding=guess_encoding(filepath)[0])) my_metadata = { diff --git a/winpython/wppm.py b/winpython/wppm.py index f97e4a13..640748d9 100644 --- a/winpython/wppm.py +++ b/winpython/wppm.py @@ -7,15 +7,13 @@ # (see winpython/__init__.py for details) import os -from pathlib import Path -import shutil import re import sys +import shutil import subprocess import json +from pathlib import Path from argparse import ArgumentParser, RawTextHelpFormatter - -# Local imports from winpython import utils, piptree # Workaround for installing PyVISA on Windows from source: @@ -66,34 +64,26 @@ def remove_directory(self, path: str): def create_file(self, package, name, dstdir, contents): """Generate data file -- path is relative to distribution root dir""" - dst = str(Path(dstdir) / name) + dst = Path(dstdir) / name if self.verbose: print(f"create: {dst}") - full_dst = str(Path(self.target) / dst) + full_dst = Path(self.target) / dst with open(full_dst, "w") as fd: fd.write(contents) - package.files.append(dst) + package.files.append(str(dst)) def get_installed_packages(self, update: bool = False) -> list[Package]: """Return installed packages.""" # Include package installed via pip (not via WPPM) - wppm = [] if str(Path(sys.executable).parent) == self.target: self.pip = piptree.PipData() else: self.pip = piptree.PipData(utils.get_python_executable(self.target)) pip_list = self.pip.pip_list() - # create pip package list - wppm = [ - Package( - f"{i[0].replace('-', '_').lower()}-{i[1]}-py3-none-any.whl", #faking wheel - suggested_summary=self.pip.summary(i[0]) if self.pip else None - ) - for i in pip_list - ] - return sorted(wppm, key=lambda tup: tup.name.lower()) + # return a list of package objects + return [Package(f"{i[0].replace('-', '_').lower()}-{i[1]}-py3-none-any.whl") for i in pip_list] def find_package(self, name: str) -> Package | None: """Find installed package by name.""" @@ -103,16 +93,13 @@ def find_package(self, name: str) -> Package | None: def patch_all_shebang(self, to_movable: bool = True, max_exe_size: int = 999999, targetdir: str = ""): """Make all python launchers relative.""" - import glob - - for ffname in glob.glob(r"%s\Scripts\*.exe" % self.target): - size = os.path.getsize(ffname) - if size <= max_exe_size: + for ffname in Path(self.target).glob("Scripts/*.exe"): + if ffname.stat().st_size <= max_exe_size: utils.patch_shebang_line(ffname, to_movable=to_movable, targetdir=targetdir) - for ffname in glob.glob(r"%s\Scripts\*.py" % self.target): + for ffname in Path(self.target).glob("Scripts/*.py"): utils.patch_shebang_line_py(ffname, to_movable=to_movable, targetdir=targetdir) - def install(self, package: Package, install_options: list[str] = None): # Type hint install_options + def install(self, package: Package, install_options: list[str] = None): """Install package in distribution.""" if package.fname.endswith((".whl", ".tar.gz", ".zip")): # Check extension with tuple self.install_bdist_direct(package, install_options=install_options) @@ -158,12 +145,10 @@ def patch_standard_packages(self, package_name="", to_movable=True): # 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) + the_place = Path(self.target) / "lib" / "site-packages" / "pip" / "_vendor" / "distlib" / "scripts.py" 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()))" - - the_place = Path(self.target) / "lib" / "site-packages" / "pip" / "_vendor" / "distlib" / "scripts.py" - print(the_place) if to_movable: utils.patch_sourcefile(the_place, sheb_fix, sheb_mov1) utils.patch_sourcefile(the_place, sheb_mov2, sheb_mov1) @@ -176,7 +161,7 @@ def patch_standard_packages(self, package_name="", to_movable=True): if package_name.lower() in ("", "spyder"): # spyder don't goes on internet without I ask utils.patch_sourcefile( - Path(self.target) / "lib" / "site-packages" / "spyder" / "config" /"main.py", + Path(self.target) / "lib" / "site-packages" / "spyder" / "config" / "main.py", "'check_updates_on_startup': True,", "'check_updates_on_startup': False,", ) @@ -250,7 +235,7 @@ def install_bdist_direct(self, package, install_options=None): def main(test=False): if test: - sbdir = Path(__file__).parents[0].parent.parent.parent / "sandbox" + sbdir = Path(__file__).parents[3] / "sandbox" tmpdir = sbdir / "tobedeleted" fname = sbdir / "VTK-5.10.0-Qt-4.7.4.win32-py2.7.exe" print(Package(str(fname)))