Skip to content

Commit

Permalink
talipot-python: Create a virtualenv for the embedded interpreter (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
anlambert committed Jan 14, 2025
1 parent 4f3954b commit 0364824
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/windows-mingw64-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_NEED_RESPONSE=ON
-DCMAKE_INSTALL_PREFIX=$PWD/install
-DPython3_EXECUTABLE=/${{ matrix.config.msystem }}/bin/python3
-DPython3_EXECUTABLE=/${{ matrix.config.msystem }}/bin/python.exe
-DTALIPOT_BUILD_TESTS=ON
-DTALIPOT_USE_CCACHE=ON ..
- name: Talipot build
Expand Down
3 changes: 2 additions & 1 deletion library/talipot-python/include/talipot/PythonInterpreter.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2019-2021 The Talipot developers
* Copyright (C) 2019-2024 The Talipot developers
*
* Talipot is a fork of Tulip, created by David Auber
* and the Tulip development Team from LaBRI, University of Bordeaux
Expand Down Expand Up @@ -51,6 +51,7 @@ class TLP_PYTHON_SCOPE PythonInterpreter : public QObject, public Singleton<Pyth

void setDefaultConsoleWidget(QAbstractScrollArea *consoleWidget);
void setConsoleWidget(QAbstractScrollArea *consoleWidget);
void setupVirtualEnv();

bool _wasInit;
bool _runningScript;
Expand Down
60 changes: 57 additions & 3 deletions library/talipot-python/src/PythonInterpreter.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2019-2024 The Talipot developers
* Copyright (C) 2019-2025 The Talipot developers
*
* Talipot is a fork of Tulip, created by David Auber
* and the Tulip development Team from LaBRI, University of Bordeaux
Expand All @@ -27,6 +27,7 @@
#if defined(__MINGW32__)
#include <QSslSocket>
#endif
#include <QFileInfo>

#include <talipot/Release.h>
#include <talipot/PythonVersionChecker.h>
Expand Down Expand Up @@ -133,8 +134,10 @@ int tracefunc(PyObject *, PyFrameObject *, int what, PyObject *) {
const QString PythonInterpreter::pythonPluginsPath(tlpStringToQString(tlp::TalipotLibDir) +
"talipot/python/");

const QString PythonInterpreter::pythonPluginsPathHome(QDir::homePath() + "/.Talipot-" +
TALIPOT_MM_VERSION + "/plugins/python");
const QString talipotUserDirectory = QDir::homePath() + "/.Talipot-" + TALIPOT_MM_VERSION;
const QString talipotVenvDirectory =
talipotUserDirectory + "/venv" + PythonVersionChecker::compiledVersion();
const QString PythonInterpreter::pythonPluginsPathHome(talipotUserDirectory + "/plugins/python");

const char PythonInterpreter::pythonReservedCharacters[] = {
'#', '%', '/', '+', '-', '&', '*', '<', '>', '|', '~', '^', '=',
Expand Down Expand Up @@ -211,6 +214,8 @@ PythonInterpreter::PythonInterpreter()
#endif
}

setupVirtualEnv();

holdGIL();

importModule("sys");
Expand Down Expand Up @@ -305,6 +310,55 @@ PythonInterpreter::PythonInterpreter()
}

releaseGIL();

setupVirtualEnv();
}

void PythonInterpreter::setupVirtualEnv() {
#ifdef Q_OS_WIN
if (!QFileInfo(talipotVenvDirectory + "/Scripts/pip.exe").exists()) {
#else
if (!QFileInfo(talipotVenvDirectory + "/bin/pip").exists()) {
#endif
runString(QString(R"(
import os
import platform
import sys
import venv
python_command = 'python3'
if platform.system() == 'Windows':
python_command = 'python.exe'
sys._base_executable = os.path.join('%1', python_command)
venv.create('%2', with_pip=True)
)")
.arg(QApplication::applicationDirPath(), talipotVenvDirectory));
}

runString(QString(R"(
import os
import platform
import sys
base = '%1'
if platform.system() == 'Windows':
site_packages = os.path.join(base, 'Lib', 'site-packages')
else:
site_packages = os.path.join(
base, 'lib',
'python%s.%s' % (sys.version_info.major, sys.version_info.minor),
'site-packages')
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = base
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path)")
.arg(talipotVenvDirectory));
}

PythonInterpreter::~PythonInterpreter() {
Expand Down
11 changes: 11 additions & 0 deletions software/talipot/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,14 @@ IF(LINUX)
OUTPUT_QUIET ERROR_QUIET)")
ENDIF(TALIPOT_LINUX_DESKTOP_REGISTRATION)
ENDIF(LINUX)

STRING(REPLACE "\\" "/" PYTHON_EXE_PATH "${PYTHON_EXECUTABLE}")

INSTALL(CODE "FILE(COPY \"${PYTHON_EXE_PATH}\"
DESTINATION \"\${CMAKE_INSTALL_PREFIX}/bin/\" FOLLOW_SYMLINK_CHAIN)")

IF(APPLE AND NOT EXISTS ${CMAKE_INSTALL_PREFIX}/bin/python3)
GET_FILENAME_COMPONENT(PYTHON_EXE_NAME ${PYTHON_EXECUTABLE} NAME)
FILE(CREATE_LINK ${CMAKE_INSTALL_PREFIX}/bin/${PYTHON_EXE_NAME}
${CMAKE_INSTALL_PREFIX}/bin/python3 SYMBOLIC)
ENDIF(APPLE AND NOT EXISTS ${CMAKE_INSTALL_PREFIX}/bin/python3)

0 comments on commit 0364824

Please sign in to comment.