diff --git a/installPsychoPy.py b/installPsychoPy.py index 004cdcf8cc..d272688e8f 100644 --- a/installPsychoPy.py +++ b/installPsychoPy.py @@ -1,186 +1,109 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Part of the PsychoPy library -# Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd. -# Distributed under the terms of the GNU General Public License (GPL). +## python script to install psychopy including dependencies +import os, sys +import pathlib import subprocess -import os -import sys -import requests - -"""This script will install PsychoPy to the current Python environment. - -For Linux installations, the script will fetch the supported linux distros for wxPython -and interactively select the distro and version to download the appropriate .whl file. - -After that the script will install PsychoPy using pip. - -NB: At present, for windows and MacOS you may as well just use `pip install psychopy` but -in the future we may add some additional functionality here, like adding application -shortcuts, checking/recommending virtual envs etc. -""" - -# Author: Florian Osmani -# Author: Jonathan Peirce - -wxLinuxUrl = "https://extras.wxpython.org/wxPython4/extras/linux/gtk3/" - -def installWhlFile(whlUrl): - """Installs a single specified wheel file using pip""" - wheel_path = os.path.basename(whlUrl) - subprocess.run([sys.exectuable, '-m', 'pip', 'install', '-U', '-f', wheel_path, 'wxPython'], check=True) - -def installPsychoPy(): - """Runs pip install psychopy""" - subprocess.run([sys.exectuable, '-m', 'pip', 'install', 'psychopy'], check=True) - -def getWxUrl(distroNames=None): - """Fetch the supported linux distros for wx and interactively select the - distro and version to download the appropriate .whl file. - - Args: - distroNames (_type_, optional): _description_. Defaults to None. - - Returns: - list: URL of the wheel for the selected distro/version - """ - def extractDistroNames(url): - """Extract the names of the linux distributions from the html content""" - - response = requests.get(url) - response.raise_for_status() - - distro_names = [] - lines = response.text.split('\n') - for line in lines: - if ' 10: - print("Sorry, please use Python 3.8, 3.9, or 3.10 to install Psychopy") - return None - - python_cp = f"cp{version_info.major}{version_info.minor}" - - def selectDistro(distroNames): - print("Please select your Linux distribution:") - for i, distro in enumerate(distroNames): - print(f"{i + 1}. {distro}") - - while True: - choice = input("Enter your choice (number): ") - if choice.isdigit() and 1 <= int(choice) <= len(distroNames): - return distroNames[int(choice) - 1] +import platform + +_linux_installer = None # will be apt-get or yum depending on system + +print( + "This `install_psychopy.py` script is EXPERIMENTAL and may not work!" + " PsychoPy users have many different systems and it's hard to maintain them all. " + " Let us know how you get on!\n" +) +if sys.version_info[:2] != (3,10): + print( + "PsychoPy is designed for Python 3.10.x " + f"You are running Python {sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}. " + "PsychoPy may not work and may not even install!\n" + ) + +print( + "This `install_psychopy.py` script is EXPERIMENTAL and may not work!" + " PsychoPy users have many different systems and it's hard to maintain them all. " + " Let us know how you get on!\n" +) + +def pip_install(*packages): + """Install packages using pip.""" + print('Installing packages:', packages) + subprocess.run([sys.executable, '-m', 'pip', 'install', '--upgrade'] + list(packages)) + +def check_venv(): + """Check if this is a virtual environment. If not, recommend quitting and creating one. + """ + # If this is not a venv then recommend quitting to create one + if not hasattr(sys, 'real_prefix'): + print( + 'You should install PsychoPy in a virtual environment,' + ' to avoid conflicts with other packages, or damaging your system.' + ' To create a virtual environment in the current directory, run:') + print(' python3 -m venv .') + print('Then activate the virtual environment with:') + print(' source bin/activate') + print('Then run this script again.') + response = input('Shall we QUIT now? [y]/n: ') + if response.lower() != 'n': + sys.exit(1) + +def apt_install(*packages): + """Install packages using apt, yum, or similar""" + global _linux_installer + # check if using this system has apt-get or yum + if _linux_installer is None: + for installer in ['apt', 'yum', 'dnf', 'zypper', 'apt-cyg']: + out = subprocess.run(['which', installer], stdout=subprocess.PIPE) + if out.returncode == 0: + _linux_installer = installer + break + if _linux_installer is None: + print('On Linux systems, this script requires either apt-get or yum.') + sys.exit(1) + + def find_package(package): + # check pacakage name according to apt/yum + packages_lookup = { + 'python3-dev': {'apt':'libgtk-3-dev', 'yum':'gtk3-devel'}, + 'libgtk-3-dev': {'apt':'libgtk-3-dev', 'yum':'gtk3-devel'}, + 'libwebkit2gtk-4.0-dev': {'apt':'libwebkit2gtk-4.0-dev', 'yum':'webkit2gtk3-devel'}, + 'libxcb-xinerama0': {'apt':'libxcb-xinerama0', 'yum':'libxcb-xinerama'}, + 'libegl1-mesa-dev': {'apt':'libegl1-mesa-dev', 'yum':'mesa-libEGL-devel'}, + } + if package in packages_lookup: + if _linux_installer in packages_lookup[package]: + return packages_lookup[package][_linux_installer] else: - print("Invalid choice, please try again.") - - def organizeDistributions(distroNames): - distroDict = {} - for distro in distroNames: - nameParts = distro.split('-') - distroName = '-'.join(nameParts[:-1]) - version = nameParts[-1] if len(nameParts) > 1 else 'default' - - if distroName in distroDict: - distroDict[distroName].append(version) - else: - distroDict[distroName] = [version] - - return distroDict - - def selectVersion(selectedDistro, versions): - while True: - print("Please select the version:") - for i, version in enumerate(versions): - print(f"{i + 1}. {selectedDistro}-{version}") - print("0. Go back") - - choice = input("Enter your choice (number): ") - if choice.isdigit(): - choice = int(choice) - if 1 <= choice <= len(versions): - return versions[choice - 1] - elif choice == 0: - return None - print("Invalid choice, please try again.") - - def fetchWhlFiles(htmlContent, pythonVersions): - all = [] - recommended = [] - lines = htmlContent.split('\n') - for line in lines: - if '