mirror of
https://github.com/muziing/Py2exe-GUI.git
synced 2025-01-13 16:42:54 +08:00
Refactor PyEnv
启用新版 `PyEnv`: 不再仅仅是一个数据类型,还包括获取版本、已安装包等功能; 从 `Constants` 移至 `Utilities` 中;
This commit is contained in:
parent
b257c35b08
commit
562a73c72d
@ -2,8 +2,6 @@
|
||||
# For details: https://github.com/muziing/Py2exe-GUI/blob/main/README.md#license
|
||||
|
||||
import enum
|
||||
import subprocess
|
||||
from typing import NamedTuple
|
||||
|
||||
|
||||
@enum.unique
|
||||
@ -17,29 +15,3 @@ class PyEnvType(enum.IntFlag):
|
||||
poetry = enum.auto() # Poetry 环境 https://python-poetry.org/
|
||||
conda = enum.auto() # conda 环境 https://docs.conda.io/en/latest/
|
||||
unknown = enum.auto() # 未知
|
||||
|
||||
|
||||
class PyEnv(NamedTuple):
|
||||
"""
|
||||
Python 解释器(环境)数据类
|
||||
"""
|
||||
|
||||
type: PyEnvType
|
||||
executable_path: str
|
||||
|
||||
|
||||
def get_pyenv_version(pyenv: PyEnv) -> str:
|
||||
"""
|
||||
获取Python解释器的版本,以形如 "3.11.7" 的字符串形式返回 \n
|
||||
:param pyenv: Python环境
|
||||
:return: Version of the Python interpreter, such as "3.11.7".
|
||||
"""
|
||||
|
||||
cmd = [
|
||||
pyenv.executable_path,
|
||||
"-c",
|
||||
"import platform;print(platform.python_version(), end='')",
|
||||
]
|
||||
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
version = str(result.stdout, encoding="utf-8")
|
||||
return version
|
||||
|
@ -3,3 +3,4 @@
|
||||
|
||||
from .open_qfile import QtFileOpen
|
||||
from .platform_specifc_funcs import get_sys_python, open_dir_in_explorer
|
||||
from .python_env import PyEnv
|
||||
|
@ -20,17 +20,19 @@ class PyEnv:
|
||||
executable_path: Union[str, Path],
|
||||
type_: Optional[PyEnvType] = PyEnvType.unknown,
|
||||
):
|
||||
self.executable_path = Path(executable_path)
|
||||
self._executable_path = Path(executable_path)
|
||||
self.exe_path = str(executable_path)
|
||||
self.type = type_
|
||||
|
||||
if type_ is None:
|
||||
# type_ 为 None 表示特殊含义——待推断
|
||||
self.type_ = self.infer_type(self.executable_path)
|
||||
self.type_ = self.infer_type(self._executable_path)
|
||||
|
||||
self.pyversion = self.get_py_version(self.executable_path)
|
||||
self.installed_packages = self.get_installed_packages(self.executable_path)
|
||||
self.pyversion = self.get_py_version(self._executable_path)
|
||||
self.installed_packages = self.get_installed_packages(self._executable_path)
|
||||
|
||||
@classmethod
|
||||
def get_py_version(cls, executable_path: Union[str, Path]) -> str:
|
||||
@staticmethod
|
||||
def get_py_version(executable_path: Union[str, Path]) -> str:
|
||||
"""
|
||||
获取Python解释器的版本,以形如 "3.11.7" 的字符串形式返回 \n
|
||||
:return: Version of the Python interpreter, such as "3.11.7".
|
||||
@ -40,8 +42,8 @@ class PyEnv:
|
||||
version = subprocess.getoutput(cmd, encoding="utf-8")
|
||||
return version
|
||||
|
||||
@classmethod
|
||||
def get_installed_packages(cls, executable_path: Union[str, Path]) -> list[dict]:
|
||||
@staticmethod
|
||||
def get_installed_packages(executable_path: Union[str, Path]) -> list[dict]:
|
||||
"""
|
||||
获取该 Python 环境中已安装的包信息 \n
|
||||
:param executable_path: Python 解释器可执行文件路径
|
||||
@ -56,14 +58,14 @@ class PyEnv:
|
||||
@classmethod
|
||||
def infer_type(cls, executable_path: Union[str, Path]) -> PyEnvType:
|
||||
"""
|
||||
推断 Python 环境类型,如 venv Poetry Conda 等
|
||||
推断 Python 环境类型,如 venv Poetry Conda 等 \n
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def pkg_installed(self, package_name: str) -> bool:
|
||||
"""
|
||||
检索某个包是否已安装
|
||||
检索某个包是否已安装 \n
|
||||
:param package_name: 待检索的包名
|
||||
:return: 是否已安装
|
||||
"""
|
@ -1,7 +1,6 @@
|
||||
# Licensed under the GPLv3 License: https://www.gnu.org/licenses/gpl-3.0.html
|
||||
# For details: https://github.com/muziing/Py2exe-GUI/blob/main/README.md#license
|
||||
|
||||
import platform
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
@ -9,8 +8,8 @@ from PySide6.QtCore import QSize
|
||||
from PySide6.QtGui import QIcon
|
||||
from PySide6.QtWidgets import QComboBox, QWidget
|
||||
|
||||
from ..Constants import RUNTIME_INFO, PyEnv, PyEnvType, get_pyenv_version
|
||||
from ..Utilities import get_sys_python
|
||||
from ..Constants import RUNTIME_INFO, PyEnvType
|
||||
from ..Utilities import PyEnv, get_sys_python
|
||||
|
||||
|
||||
class PyEnvComboBox(QComboBox):
|
||||
@ -25,20 +24,15 @@ class PyEnvComboBox(QComboBox):
|
||||
|
||||
if not RUNTIME_INFO.is_bundled:
|
||||
# 在非 PyInstaller 捆绑环境中,第一项为当前用于运行 Py2exe-GUI 的 Python 环境
|
||||
current_pyenv = PyEnv(PyEnvType.poetry, executable_path=sys.executable)
|
||||
current_pyenv = PyEnv(sys.executable, PyEnvType.poetry)
|
||||
self.addItem(*self.gen_item(current_pyenv))
|
||||
sys_pyenv = PyEnv(get_sys_python(), PyEnvType.system)
|
||||
self.addItem(*self.gen_item(sys_pyenv))
|
||||
else:
|
||||
# 若已由 PyInstaller 捆绑成冻结应用程序,则第一项为系统 Python 环境
|
||||
sys_pyenv = PyEnv(PyEnvType.system, executable_path=get_sys_python())
|
||||
sys_pyenv = PyEnv(get_sys_python(), PyEnvType.system)
|
||||
self.addItem(*self.gen_item(sys_pyenv))
|
||||
|
||||
# 测试项
|
||||
self.addItem(
|
||||
QIcon(":/Icons/Python_128px"),
|
||||
f"Python {platform.python_version()}",
|
||||
sys.executable,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def gen_item(cls, pyenv: PyEnv) -> tuple:
|
||||
"""
|
||||
@ -47,8 +41,8 @@ class PyEnvComboBox(QComboBox):
|
||||
:return: (icon, text, data)
|
||||
"""
|
||||
|
||||
data = pyenv.executable_path
|
||||
version = get_pyenv_version(pyenv)
|
||||
data = pyenv
|
||||
version = pyenv.pyversion
|
||||
|
||||
if pyenv.type == PyEnvType.system:
|
||||
icon = QIcon(":/Icons/Python_128px")
|
||||
|
@ -7,11 +7,11 @@ from PySide6.QtCore import Slot
|
||||
from PySide6.QtGui import QCloseEvent
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
from .Constants import PyInstOpt # noqa
|
||||
from .Core import Packaging, PackagingTask # noqa
|
||||
from .Constants import PyInstOpt
|
||||
from .Core import Packaging, PackagingTask
|
||||
from .Resources import COMPILED_RESOURCES # noqa
|
||||
from .Utilities import open_dir_in_explorer # noqa
|
||||
from .Widgets import MainWindow, SubProcessDlg # noqa
|
||||
from .Utilities import PyEnv, open_dir_in_explorer
|
||||
from .Widgets import MainWindow, SubProcessDlg
|
||||
|
||||
|
||||
class MainApp(MainWindow):
|
||||
@ -22,6 +22,7 @@ class MainApp(MainWindow):
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.current_pyenv: PyEnv
|
||||
self.packaging_task = PackagingTask(self)
|
||||
self.packager = Packaging(self)
|
||||
self.subprocess_dlg = SubProcessDlg(self)
|
||||
@ -63,16 +64,24 @@ class MainApp(MainWindow):
|
||||
处理用户通过选择不同的 Python 解释器时的响应
|
||||
"""
|
||||
|
||||
self.packager.set_python_path(self.center_widget.pyenv_combobox.currentData())
|
||||
self.center_widget.pyenv_combobox.currentIndexChanged.connect(
|
||||
lambda: self.packager.set_python_path(
|
||||
self.center_widget.pyenv_combobox.currentData()
|
||||
@Slot()
|
||||
def on_pyenv_change() -> None:
|
||||
"""
|
||||
处理用户通过选择不同的 Python 解释器时的响应
|
||||
"""
|
||||
|
||||
self.current_pyenv = self.center_widget.pyenv_combobox.currentData()
|
||||
self.packager.set_python_path(self.current_pyenv.exe_path)
|
||||
self.center_widget.hidden_import_dlg.pkg_browser_dlg.load_pkg_list(
|
||||
self.current_pyenv.installed_packages
|
||||
)
|
||||
)
|
||||
|
||||
on_pyenv_change() # 显式调用一次,确保用户无任何操作时也能正确处理默认pyenv
|
||||
self.center_widget.pyenv_combobox.currentIndexChanged.connect(on_pyenv_change)
|
||||
|
||||
def _connect_run_pkg_btn_slot(self):
|
||||
@Slot()
|
||||
def run_packaging() -> None:
|
||||
def on_run_packaging_btn_clicked() -> None:
|
||||
"""
|
||||
“运行打包”按钮的槽函数 \n
|
||||
"""
|
||||
@ -81,11 +90,13 @@ class MainApp(MainWindow):
|
||||
self.subprocess_dlg.show()
|
||||
self.packager.run_packaging_process()
|
||||
|
||||
self.center_widget.run_packaging_btn.clicked.connect(run_packaging)
|
||||
self.center_widget.run_packaging_btn.clicked.connect(
|
||||
on_run_packaging_btn_clicked
|
||||
)
|
||||
|
||||
def _connect_mul_btn_slot(self, subprocess_dlg):
|
||||
@Slot()
|
||||
def handle_multifunction() -> None:
|
||||
def on_multifunction_btn_clicked() -> None:
|
||||
"""
|
||||
处理子进程窗口多功能按钮点击信号的槽 \n
|
||||
"""
|
||||
@ -102,7 +113,7 @@ class MainApp(MainWindow):
|
||||
self.subprocess_dlg.close()
|
||||
|
||||
# 连接信号与槽
|
||||
subprocess_dlg.multifunction_btn.clicked.connect(handle_multifunction)
|
||||
subprocess_dlg.multifunction_btn.clicked.connect(on_multifunction_btn_clicked)
|
||||
|
||||
def closeEvent(self, event: QCloseEvent) -> None:
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user