diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f591fb33..9ccf9233 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,24 +24,17 @@ jobs: name: [ # latest conan 1.X on U22 and Windows - "u22-py38-conan1-latest", "u22-py39-conan1-latest", "u22-py310-conan1-latest", "win-py311-conan1-latest", # conan minimum version with python minimum version - "u22-py38-conan1.48", + "u22-py39-conan1.48", # conan 2 stuff with bleeding edge - use Python 3.12 (U22 needed) "u22-py310-conan2.3", # 2.3 API changes - "u22-py312-conan2-latest", # post 2.3 API changes - "win-py312-conan2-latest", # latest everything + "u22-py314-conan2-latest", # post 2.3 API changes + "win-py314-conan2-latest", # latest everything ] include: - - name: "u22-py38-conan1-latest" - python: "3.8" - os: ubuntu-22.04 - conan: "<2" - conan_server: "<2" - pytest_args: "" - name: "u22-py39-conan1-latest" python: "3.9" conan: "<2" @@ -60,8 +53,8 @@ jobs: conan: "<2" conan_server: "<2" pytest_args: "" - - name: "u22-py38-conan1.48" - python: "3.8" + - name: "u22-py39-conan1.48" + python: "3.9" os: ubuntu-22.04 conan: "==1.48.0" conan_server: "==1.48.0" @@ -72,17 +65,17 @@ jobs: conan: <2.4 conan_server: "-server <2.4" pytest_args: "-m conanv2" - - name: "u22-py312-conan2-latest" - python: "3.12" + - name: "u22-py314-conan2-latest" + python: "3.13" os: ubuntu-22.04 - conan: <2.8 - conan_server: "-server <2.8" + conan: <2.21 + conan_server: "-server <2.21" pytest_args: "-m conanv2" - - name: win-py312-conan2-latest - python: "3.12" + - name: win-py314-conan2-latest + python: "3.14" os: windows-latest - conan: <2.8 # latest conan 2 - conan_server: "-server <2.8" + conan: <2.21 # latest conan 2 + conan_server: "-server <2.21" pytest_args: "-m conanv2" env: DISPLAY: ":99.0" @@ -117,7 +110,8 @@ jobs: sudo apt install qt6-wayland ######### Platform specifics end ######### - name: Install specific Conan version - run: | # markupsafe is a workaround fix for broken conan dependencies + run: | # pip version needed for --no-use-pep517 and markupsafe is a workaround fix for broken conan dependencies + python -m pip install pip==24.3.1 pip install markupsafe==2.0.1 --use-pep517 pip install "conan${{ matrix.conan }}" --use-pep517 pip install "conan${{ matrix.conan_server }}" --use-pep517 @@ -177,6 +171,6 @@ jobs: -Dsonar.exclusions=**/*_ui.py -Dsonar.tests=./test -Dsonar.sourceEncoding=UTF-8 - -Dsonar.python.version=3.8,3.9,3.10,3.11,3.12 + -Dsonar.python.version=3.8,3.9,3.10,3.11,3.12,3.13,3.14 -Dsonar.python.coverage.reportPaths=**/cov/cov-*.xml -Dsonar.python.xunit.reportPath=**/results/result-unit-*.xml diff --git a/README.md b/README.md index 35bae48f..5d47044a 100644 --- a/README.md +++ b/README.md @@ -143,8 +143,9 @@ You can also assign its icon to it from the site packages folder in **conan_expl > From version 2.4.0 the conan-unified-api package provides the compatiblity layer for Conan Explorer. By upgrading it in your Python enviroment, the compatibility will also be ensured. The version number corresponds to the latest conan version supported. Please see https://pypi.org/project/conan-unified-api/ to find the latest version. > ⚠ **Warning** - **Deprecation of Python 3.X** -> From version 2.0.0 Python 3.6 support will be dropped, having reached end-of-life. -> From version 2.2.0 Python 3.7 support will be dropped, having reached end-of-life. +> From version 2.0.0 Python 3.6 support will be dropped, having reached end-of-life. +> From version 2.2.0 Python 3.7 support will be dropped, having reached end-of-life. +> From version 2.5.0 Python 3.8 support will be dropped, having reached end-of-life. ## 🛠 Toolchain diff --git a/pyproject.toml b/pyproject.toml index ed5f0d4e..7bd1cbe2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [project] name = "conan-explorer" authors = [{name = "Péter Gosztolya and Contributors"}] -version = "2.4.2" -requires-python = ">=3.8" +version = "2.5.0" +requires-python = ">=3.9, <3.15" description = "Package Explorer and App Launcher for Conan" keywords = ["conan", "gui"] license = {'file'="LICENSE"} @@ -10,11 +10,12 @@ classifiers = [ "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Environment :: X11 Applications :: Qt", "Environment :: Win32 (MS Windows)" @@ -22,7 +23,7 @@ classifiers = [ dependencies = [ "conan-unified-api >=2.15.0, <3.0.0", # MIT License # 6.4.3 is needed for off-the-shelf U20 support - "PySide6-Essentials>=6.4.3", # LGPLv3 License + "PySide6-Essentials<=6.11.0, >6.4.3", # LGPLv3 License "jsonschema>=3.2.0, <5", # MIT License "dictdiffer==0.9.0", # MIT License # compatibility @@ -62,12 +63,12 @@ dev = [ "debugpy", # Qt thread debugging ] test = [ - "pytest==8.3.3", - "pytest-cov==5.0.0", - "pytest-mock==3.14.0", - "pytest-qt==4.4.0", - "psutil==6.1.1", - "pytest-check==2.4.1", + "pytest==8.4.2", + "pytest-cov==7.0.0", + "pytest-mock==3.15.1", + "pytest-qt==4.5.0", + "psutil==7.1.2", + "pytest-check==2.6.0", "pywin32; sys_platform=='win32'" ] diff --git a/test/02_integration/test_gui_app_grid.py b/test/02_integration/test_gui_app_grid.py index 437c7c76..d7334264 100644 --- a/test/02_integration/test_gui_app_grid.py +++ b/test/02_integration/test_gui_app_grid.py @@ -1,13 +1,11 @@ - import os import tempfile from pathlib import Path -from test.conftest import TEST_REF, conan_install_ref +from conan_unified_api.types import ConanRef from PySide6 import QtCore, QtWidgets import conan_explorer.app as app -from conan_unified_api.types import ConanRef from conan_explorer.settings import * from conan_explorer.settings.ini_file import IniSettings from conan_explorer.ui import main_window @@ -16,11 +14,13 @@ from conan_explorer.ui.views.app_grid.config.json_file import JsonUiConfig from conan_explorer.ui.views.app_grid.model import UiAppLinkModel from conan_explorer.ui.views.app_grid.tab import AppEditDialog, ListAppLink +from test.conftest import TEST_REF, conan_install_ref Qt = QtCore.Qt + def test_rename_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): - """ Test, that rename dialog change the name """ + """Test, that rename dialog change the name""" from pytestqt.plugin import _qapp_instance main_gui = main_window.MainWindow(_qapp_instance) @@ -32,11 +32,11 @@ def test_rename_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): new_text = "My Text" - mocker.patch.object(QtWidgets.QInputDialog, 'getText', return_value=[new_text, True]) + mocker.patch.object(QtWidgets.QInputDialog, "getText", return_value=[new_text, True]) main_gui.app_grid.on_tab_rename(0) assert main_gui.app_grid.tab_widget.tabBar().tabText(0) == new_text - mocker.patch.object(QtWidgets.QInputDialog, 'getText', return_value=["OtherText", False]) + mocker.patch.object(QtWidgets.QInputDialog, "getText", return_value=["OtherText", False]) main_gui.app_grid.on_tab_rename(0) # text must be the same assert main_gui.app_grid.tab_widget.tabBar().tabText(0) == new_text @@ -44,7 +44,7 @@ def test_rename_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): def test_add_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): - """ Test, that Add Tab function adds a new tab """ + """Test, that Add Tab function adds a new tab""" from pytestqt.plugin import _qapp_instance main_gui = main_window.MainWindow(_qapp_instance) @@ -56,7 +56,7 @@ def test_add_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): new_text = "My New Tab" prev_count = main_gui.app_grid.tab_widget.tabBar().count() - mocker.patch.object(QtWidgets.QInputDialog, 'getText', return_value=[new_text, True]) + mocker.patch.object(QtWidgets.QInputDialog, "getText", return_value=[new_text, True]) main_gui.app_grid.on_new_tab() assert main_gui.app_grid.tab_widget.tabBar().count() == prev_count + 1 assert main_gui.app_grid.tab_widget.tabBar().tabText(prev_count) == new_text @@ -65,8 +65,7 @@ def test_add_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): assert len(config_tabs) == prev_count + 1 # press cancel - count must still be original + 1 - mocker.patch.object(QtWidgets.QInputDialog, 'getText', - return_value=["OtherText", False]) + mocker.patch.object(QtWidgets.QInputDialog, "getText", return_value=["OtherText", False]) main_gui.app_grid.on_new_tab() config_tabs = JsonUiConfig(ui_no_refs_config_fixture).load().app_grid.tabs assert main_gui.app_grid.tab_widget.tabBar().count() == prev_count + 1 @@ -76,7 +75,7 @@ def test_add_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): def test_remove_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): - """ Test, that Remove Tab actually removes a tab. Last tab must not be deletable. """ + """Test, that Remove Tab actually removes a tab. Last tab must not be deletable.""" from pytestqt.plugin import _qapp_instance main_gui = main_window.MainWindow(_qapp_instance) @@ -94,17 +93,18 @@ def test_remove_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): # press no print("Test pressing no") - mocker.patch.object(QtWidgets.QMessageBox, 'exec', - return_value=QtWidgets.QMessageBox.StandardButton.No) + mocker.patch.object( + QtWidgets.QMessageBox, "exec", return_value=QtWidgets.QMessageBox.StandardButton.No + ) main_gui.app_grid.on_tab_remove(0) config_tabs = JsonUiConfig(ui_no_refs_config_fixture).load().app_grid.tabs assert main_gui.app_grid.tab_widget.tabBar().count() == prev_count assert len(config_tabs) == prev_count - print("Test pressing yes") - mocker.patch.object(QtWidgets.QMessageBox, 'exec', - return_value=QtWidgets.QMessageBox.StandardButton.Yes) + mocker.patch.object( + QtWidgets.QMessageBox, "exec", return_value=QtWidgets.QMessageBox.StandardButton.Yes + ) print("Execute remove") main_gui.app_grid.on_tab_remove(0) @@ -117,7 +117,7 @@ def test_remove_tab_dialog(app_qt_fixture, ui_no_refs_config_fixture, mocker): def test_tab_move_is_saved(app_qt_fixture, ui_no_refs_config_fixture): - """ Test, that the config file is saved, when the tab is moved. """ + """Test, that the config file is saved, when the tab is moved.""" from pytestqt.plugin import _qapp_instance main_gui = main_window.MainWindow(_qapp_instance) @@ -140,7 +140,7 @@ def test_tab_move_is_saved(app_qt_fixture, ui_no_refs_config_fixture): def test_edit_AppLink(app_qt_fixture, base_fixture, ui_config_fixture, mocker): - """ Test, that Edit AppLink Dialog saves all the configured data s""" + """Test, that Edit AppLink Dialog saves all the configured data s""" from pytestqt.plugin import _qapp_instance main_gui = main_window.MainWindow(_qapp_instance) @@ -157,18 +157,22 @@ def test_edit_AppLink(app_qt_fixture, base_fixture, ui_config_fixture, mocker): app_link: ListAppLink = tabs[1].app_links[0] # check that no changes happens on cancel - mocker.patch.object(AppEditDialog, 'exec', - return_value=QtWidgets.QDialog.DialogCode.Rejected) + mocker.patch.object( + QtWidgets.QDialog, "exec", return_value=QtWidgets.QDialog.DialogCode.Rejected + ) app_link.open_edit_dialog() config_tabs = JsonUiConfig(ui_config_fixture).load().app_grid.tabs - assert config_tabs[0].name == tab_model.name == "Basics" # just safety that it is the same tab + assert ( + config_tabs[0].name == tab_model.name == "Basics" + ) # just safety that it is the same tab assert len(config_tabs[0].apps) == prev_count # check, that changing something has the change in the saved config and we the same number of elements - app_config = UiAppLinkConfig(name="NewApp", conan_ref=TEST_REF, - executable="bin/exe") + app_config = UiAppLinkConfig(name="NewApp", conan_ref=TEST_REF, executable="bin/exe") app_model = UiAppLinkModel().load(app_config, app_link.model.parent) - mocker.patch.object(AppEditDialog, 'exec', return_value=QtWidgets.QDialog.DialogCode.Accepted) + mocker.patch.object( + QtWidgets.QDialog, "exec", return_value=QtWidgets.QDialog.DialogCode.Accepted + ) app_link.open_edit_dialog(app_model) # check that the gui has updated @@ -186,7 +190,7 @@ def test_edit_AppLink(app_qt_fixture, base_fixture, ui_config_fixture, mocker): def test_remove_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, mocker): - """ Test, that Remove Applink removes and AppLink and the last one is not deletable """ + """Test, that Remove Applink removes and AppLink and the last one is not deletable""" from pytestqt.plugin import _qapp_instance main_gui = main_window.MainWindow(_qapp_instance) @@ -201,8 +205,9 @@ def test_remove_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, apps_model = tab_model.apps prev_count = len(apps_model) - mocker.patch.object(QtWidgets.QMessageBox, 'exec', - return_value=QtWidgets.QMessageBox.StandardButton.Yes) + mocker.patch.object( + QtWidgets.QMessageBox, "exec", return_value=QtWidgets.QMessageBox.StandardButton.Yes + ) app_link = tabs[1].app_links[0] app_link.remove() @@ -217,7 +222,7 @@ def test_remove_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, def test_add_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, mocker): - """ Tests, that the Edit App Dialog wotks for adding a new Link """ + """Tests, that the Edit App Dialog wotks for adding a new Link""" from pytestqt.plugin import _qapp_instance # preinstall ref, to see if link updates paths @@ -236,12 +241,14 @@ def test_add_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, mo apps_model = tab_model.apps prev_count = len(apps_model) app_link: ListAppLink = tab.app_links[0] - app_config = UiAppLinkConfig(name="NewApp", conan_ref=TEST_REF, - executable="conanmanifest.txt") + app_config = UiAppLinkConfig( + name="NewApp", conan_ref=TEST_REF, executable="conanmanifest.txt" + ) app_model = UiAppLinkModel().load(app_config, app_link.model.parent) - mocker.patch.object(AppEditDialog, 'exec', - return_value=QtWidgets.QDialog.DialogCode.Accepted) + mocker.patch.object( + QtWidgets.QDialog, "exec", return_value=QtWidgets.QDialog.DialogCode.Accepted + ) new_app_link = tab.open_app_link_add_dialog(app_model) assert new_app_link assert tab._edit_app_dialog._ui.name_line_edit.text() @@ -266,9 +273,9 @@ def test_add_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, mo def test_move_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, mocker): - """ Test, that the move dialog works and correctly updates the AppGrid. There are 2 apps on the loaded tab. """ + """Test, that the move dialog works and correctly updates the AppGrid. There are 2 apps on the loaded tab.""" from pytestqt.plugin import _qapp_instance - + main_gui = main_window.MainWindow(_qapp_instance) main_gui.show() main_gui.load(ui_no_refs_config_fixture) @@ -284,7 +291,9 @@ def test_move_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, m move_dialog = ReorderDialog(parent=main_gui, model=tab_model) move_dialog.show() sel_idx = tab_model.index(0, 0, QtCore.QModelIndex()) - move_dialog._ui.list_view.selectionModel().select(sel_idx, QtCore.QItemSelectionModel.SelectionFlag.Select) + move_dialog._ui.list_view.selectionModel().select( + sel_idx, QtCore.QItemSelectionModel.SelectionFlag.Select + ) move_dialog._ui.move_down_button.clicked.emit() # check model assert apps_model[1].name == app_link.model.name @@ -293,7 +302,9 @@ def test_move_AppLink(app_qt_fixture, base_fixture, ui_no_refs_config_fixture, m assert apps_model[1].name == app_link.model.name # now the element is deselcted - select the same element again (now row 1) sel_idx = tab_model.index(1, 0, QtCore.QModelIndex()) - move_dialog._ui.list_view.selectionModel().select(sel_idx, QtCore.QItemSelectionModel.SelectionFlag.Select) + move_dialog._ui.list_view.selectionModel().select( + sel_idx, QtCore.QItemSelectionModel.SelectionFlag.Select + ) # now move back move_dialog._ui.move_up_button.clicked.emit() assert apps_model[0].name == app_link.model.name @@ -310,13 +321,16 @@ def test_multiple_apps_ungreying(app_qt_fixture, base_fixture): Set greyed attribute of the underlying app button expected. """ from pytestqt.plugin import _qapp_instance + conan_install_ref(TEST_REF, "-u") temp_dir = tempfile.gettempdir() temp_ini_path = os.path.join(temp_dir, "config.ini") app.active_settings = IniSettings(Path(temp_ini_path)) - config_file_path = base_fixture.testdata_path / "config_file/multiple_apps_same_package.json" + config_file_path = ( + base_fixture.testdata_path / "config_file/multiple_apps_same_package.json" + ) app.active_settings.set(AUTO_INSTALL_QUICKLAUNCH_REFS, False) app.active_settings.set(LAST_CONFIG_FILE, str(config_file_path)) # load path into local cache diff --git a/test/02_integration/test_gui_local_pkg_exp.py b/test/02_integration/test_gui_local_pkg_exp.py index b0e148ae..5bec1087 100644 --- a/test/02_integration/test_gui_local_pkg_exp.py +++ b/test/02_integration/test_gui_local_pkg_exp.py @@ -1,14 +1,12 @@ - import os import platform from pathlib import Path -from test.conftest import (TEST_REF, PathSetup, conan_add_editables, - conan_install_ref, get_current_profile) from time import sleep from typing import Generator, Tuple import pytest import pytest_check as check +from conan_unified_api.types import ConanPkgRef, ConanRef from PySide6 import QtCore, QtWidgets from PySide6.QtWidgets import QApplication from pytest_mock import MockerFixture @@ -17,14 +15,19 @@ import conan_explorer.app as app # using global module pattern from conan_explorer import conan_version from conan_explorer.app.system import delete_path -from conan_unified_api.types import ConanPkgRef, ConanRef from conan_explorer.settings import FILE_EDITOR_EXECUTABLE from conan_explorer.ui import main_window from conan_explorer.ui.views import LocalConanPackageExplorer from conan_explorer.ui.views.app_grid.tab import AppEditDialog -from conan_explorer.ui.views.package_explorer.file_controller import \ - NEW_FOLDER_NAME +from conan_explorer.ui.views.package_explorer.file_controller import NEW_FOLDER_NAME from conan_explorer.ui.views.package_explorer.sel_model import PkgSelectionType +from test.conftest import ( + TEST_REF, + PathSetup, + conan_add_editables, + conan_install_ref, + get_current_profile, +) Qt = QtCore.Qt SelFlags = QtCore.QItemSelectionModel.SelectionFlag @@ -35,9 +38,11 @@ LPESetupType = Tuple[QApplication, LocalConanPackageExplorer, main_window.MainWindow] + @pytest.fixture -def setup_local_package_explorer(qtbot, - base_fixture, ui_no_refs_config_fixture) -> Generator[LPESetupType, None, None]: +def setup_local_package_explorer( + qtbot, base_fixture, ui_no_refs_config_fixture +) -> Generator[LPESetupType, None, None]: from pytestqt.plugin import _qapp_instance # 1. Switch to another package view @@ -50,8 +55,8 @@ def setup_local_package_explorer(qtbot, app.conan_worker.finish_working() lpe = main_gui.page_widgets.get_page_by_type(LocalConanPackageExplorer) - # change to local explorer page - main_gui.page_widgets.get_button_by_type(type(lpe)).click() + # change to local explorer page + main_gui.page_widgets.get_button_by_type(type(lpe)).click() lpe._pkg_sel_ctrl._loader.wait_for_finished() yield (_qapp_instance, lpe, main_gui) @@ -59,9 +64,13 @@ def setup_local_package_explorer(qtbot, @pytest.mark.conanv2 -def test_local_package_explorer_pkg_selection(qtbot, mocker, - setup_local_package_explorer: LPESetupType, - base_fixture, ui_no_refs_config_fixture: Path): +def test_local_package_explorer_pkg_selection( + qtbot, + mocker, + setup_local_package_explorer: LPESetupType, + base_fixture, + ui_no_refs_config_fixture: Path, +): """ Test Local Pacakge Explorer functions. 1. Change to Page, check if the installed package is in the list. @@ -71,6 +80,7 @@ def test_local_package_explorer_pkg_selection(qtbot, mocker, 5. Select export folder """ from conan_explorer.app.logger import Logger + _qapp_instance, lpe, main_gui = setup_local_package_explorer # 1. Switch to another package view # need new id @@ -87,8 +97,8 @@ def test_local_package_explorer_pkg_selection(qtbot, mocker, pkg_id2 = installed_pkgs[1].get("id") assert pkg_id1 assert pkg_id2 - pkg_path1 = app.conan_api.get_package_folder(cfr, pkg_id1) - pkg_path2 = app.conan_api.get_package_folder(cfr, pkg_id2) + pkg_path1 = app.conan_api.get_package_folder(cfr, pkg_id1) + pkg_path2 = app.conan_api.get_package_folder(cfr, pkg_id2) export_path = app.conan_api.get_export_folder(cfr) # restart reload (check for thread safety) @@ -110,8 +120,10 @@ def test_local_package_explorer_pkg_selection(qtbot, mocker, if child.type.value == PkgSelectionType.export.value: continue assert pkg_sel_model.get_quick_profile_name(child) in [ - "Windows_x64_vs16_release", "Linux_x64_gcc9_release", - "Windows_x64_msvc192_release"] # ConanV2 + "Windows_x64_vs16_release", + "Linux_x64_gcc9_release", + "Windows_x64_msvc192_release", + ] # ConanV2 assert found_tst_pkg # 2. select package (ref, not profile) @@ -128,12 +140,12 @@ def test_local_package_explorer_pkg_selection(qtbot, mocker, # 4. switch to another package Logger().debug("Select pkg2") - assert lpe.select_local_package_from_ref(TEST_REF+ ":" + pkg_id2) + assert lpe.select_local_package_from_ref(TEST_REF + ":" + pkg_id2) assert lpe._pkg_tabs_ctrl[0]._model # view selected -> fs_model is set assert Path(lpe._pkg_tabs_ctrl[0]._model.rootPath()) == pkg_path2 - #5.Select export folder + # 5.Select export folder Logger().debug("Select export folder") assert lpe._pkg_sel_ctrl.select_local_package_from_ref(TEST_REF, export=True) @@ -154,9 +166,13 @@ def test_local_package_explorer_pkg_selection(qtbot, mocker, @pytest.mark.conanv2 -def test_local_package_explorer_pkg_selection_editables(qtbot, mocker, - setup_local_package_explorer: LPESetupType, - base_fixture :PathSetup, ui_no_refs_config_fixture: Path): +def test_local_package_explorer_pkg_selection_editables( + qtbot, + mocker, + setup_local_package_explorer: LPESetupType, + base_fixture: PathSetup, + ui_no_refs_config_fixture: Path, +): """ Check editable packages open set root path. """ @@ -179,8 +195,13 @@ def test_local_package_explorer_pkg_selection_editables(qtbot, mocker, @pytest.mark.conanv2 -def test_local_package_explorer_pkg_sel_functions(qtbot, mocker: MockerFixture, base_fixture, - ui_no_refs_config_fixture, setup_local_package_explorer: LPESetupType): +def test_local_package_explorer_pkg_sel_functions( + qtbot, + mocker: MockerFixture, + base_fixture, + ui_no_refs_config_fixture, + setup_local_package_explorer: LPESetupType, +): """ Test Local Package Explorer functions. 1. Change to Page @@ -199,6 +220,7 @@ def test_local_package_explorer_pkg_sel_functions(qtbot, mocker: MockerFixture, _qapp_instance, lpe, main_gui = setup_local_package_explorer from conan_explorer.app.logger import Logger + cfr = ConanRef.loads(TEST_REF) conanfile_path = app.conan_api.get_conanfile_path(cfr) id, pkg_path = app.conan_api.install_best_matching_package(cfr) @@ -224,25 +246,31 @@ def test_local_package_explorer_pkg_sel_functions(qtbot, mocker: MockerFixture, mock_open_file.assert_called_once_with(conanfile_path) sleep(1) - # test install ref + # test install ref Logger().debug("open install ref") mock_install_dialog = mocker.patch("package_explorer.sel_controller.ConanInstallDialog") lpe.install_ref_action.trigger() - mock_install_dialog.assert_called_with(lpe._pkg_sel_ctrl._view, TEST_REF + ":" + id, - lpe._pkg_sel_ctrl._base_signals.conan_pkg_installed, lock_reference=True) + mock_install_dialog.assert_called_with( + lpe._pkg_sel_ctrl._view, + TEST_REF + ":" + id, + lpe._pkg_sel_ctrl._base_signals.conan_pkg_installed, + lock_reference=True, + ) # check show buildinfo - if conan_version.major == 1: # only in 1 + if conan_version.major == 1: # only in 1 Logger().debug("show buildinfo") - mock_b = mocker.patch.object(app.conan_api, 'get_conan_buildinfo', return_value="Dummy") - mocker.patch.object(QtWidgets.QDialog, 'exec', - return_value=QtWidgets.QDialog.DialogCode.Accepted) + mock_b = mocker.patch.object(app.conan_api, "get_conan_buildinfo", return_value="Dummy") + mocker.patch.object( + QtWidgets.QDialog, "exec", return_value=QtWidgets.QDialog.DialogCode.Accepted + ) lpe.show_build_info_action.trigger() profile_name = get_current_profile() settings = app.conan_api.get_profile_settings( - str(base_fixture.testdata_path / f"conan/profile/{profile_name}")) - options = {'fPIC2': 'True', 'shared': 'True', 'variant': 'var1'} + str(base_fixture.testdata_path / f"conan/profile/{profile_name}") + ) + options = {"fPIC2": "True", "shared": "True", "variant": "var1"} mock_b.assert_called_with(ConanRef.loads(TEST_REF), settings, options) # check diff pkgs @@ -263,9 +291,11 @@ def test_local_package_explorer_pkg_sel_functions(qtbot, mocker: MockerFixture, another_id = pkg.get("id") break assert another_id - sel_index = lpe._pkg_sel_ctrl.select_local_package_from_ref(TEST_REF + ":" + str(another_id), - select_mode=QtCore.QItemSelectionModel.SelectionFlag.Select) - + sel_index = lpe._pkg_sel_ctrl.select_local_package_from_ref( + TEST_REF + ":" + str(another_id), + select_mode=QtCore.QItemSelectionModel.SelectionFlag.Select, + ) + mock_diff_dialog = mocker.patch("package_explorer.sel_controller.PkgDiffDialog") lpe.diff_pkg_action.trigger() mock_diff_dialog.assert_called_once() @@ -274,7 +304,7 @@ def test_local_package_explorer_pkg_sel_functions(qtbot, mocker: MockerFixture, assert mock_diff_dialog.mock_calls[3][0] == "().show" elem_pos = lpe._pkg_sel_ctrl._view.visualRect(sel_index) - mocker.patch.object(lpe.select_cntx_menu, 'exec') + mocker.patch.object(lpe.select_cntx_menu, "exec") # check that on multiple selection diff pkg action is enabled lpe.on_selection_context_menu_requested(elem_pos.center()) @@ -301,8 +331,13 @@ def test_local_package_explorer_pkg_sel_functions(qtbot, mocker: MockerFixture, # TODO: I don't know how to check this lpe._pkg_sel_ctrl._view.isIndexHidden(idx) returns wrong value -def test_sizes_calculation(qtbot, mocker: MockerFixture, base_fixture, - ui_no_refs_config_fixture, setup_local_package_explorer: LPESetupType): +def test_sizes_calculation( + qtbot, + mocker: MockerFixture, + base_fixture, + ui_no_refs_config_fixture, + setup_local_package_explorer: LPESetupType, +): if platform.system() == "Linux": pytest.skip("Skipping plugin test on Linux due to race conditions") _qapp_instance, lpe, main_gui = setup_local_package_explorer @@ -315,9 +350,14 @@ def test_sizes_calculation(qtbot, mocker: MockerFixture, base_fixture, @pytest.mark.conanv2 -def test_local_package_explorer_tabs(qtbot, mocker, base_fixture, ui_no_refs_config_fixture, - setup_local_package_explorer: LPESetupType): - """ Test tabs feature +def test_local_package_explorer_tabs( + qtbot, + mocker, + base_fixture, + ui_no_refs_config_fixture, + setup_local_package_explorer: LPESetupType, +): + """Test tabs feature 1. Check that last tab can not be closed 1. Change to Page, check if the installed package is in the list. 3. Select view for tab 1 @@ -347,8 +387,8 @@ def test_local_package_explorer_tabs(qtbot, mocker, base_fixture, ui_no_refs_con pkg_id2 = installed_pkgs[1].get("id") assert pkg_id1 assert pkg_id2 - pkg_path1 = app.conan_api.get_package_folder(cfr, pkg_id1) - pkg_path2 = app.conan_api.get_package_folder(cfr, pkg_id2) + pkg_path1 = app.conan_api.get_package_folder(cfr, pkg_id1) + pkg_path2 = app.conan_api.get_package_folder(cfr, pkg_id2) # 3. ensure, that we select the pkg with the correct options Logger().debug("Select pkg1") @@ -356,13 +396,13 @@ def test_local_package_explorer_tabs(qtbot, mocker, base_fixture, ui_no_refs_con assert lpe._pkg_tabs_ctrl[0]._model # view selected -> fs_model is set assert Path(lpe._pkg_tabs_ctrl[0]._model.rootPath()) == pkg_path1 - #4 + # 4 # switches to + tab and back to create new view lpe._ui.package_tab_widget.tabBar().setCurrentIndex(1) assert lpe._ui.package_tab_widget.tabBar().currentIndex() == 1 assert lpe._ui.package_tab_widget.tabBar().count() == 3 assert lpe._ui.package_tab_widget.tabBar().tabText(1) == "New tab" - assert "+" in lpe._ui.package_tab_widget.tabBar().tabText(2) + assert "+" in lpe._ui.package_tab_widget.tabBar().tabText(2) assert lpe._pkg_tabs_ctrl[1]._model is None # 5 @@ -381,8 +421,13 @@ def test_local_package_explorer_tabs(qtbot, mocker, base_fixture, ui_no_refs_con @pytest.mark.conanv2 -def test_local_package_explorer_file_generic_functions(qtbot, mocker, base_fixture, - ui_no_refs_config_fixture, setup_local_package_explorer: LPESetupType): +def test_local_package_explorer_file_generic_functions( + qtbot, + mocker, + base_fixture, + ui_no_refs_config_fixture, + setup_local_package_explorer: LPESetupType, +): """ Test simple context menu functions of File View 1. Change to Page, check if the installed package is in the list. @@ -437,10 +482,13 @@ def test_local_package_explorer_file_generic_functions(qtbot, mocker, base_fixtu oifm_mock.assert_called_with(Path(cp_text)) # 2.4 check "Add AppLink to AppGrid" - mocker.patch.object(QtWidgets.QInputDialog, 'exec', - return_value=QtWidgets.QInputDialog.DialogCode.Accepted) - mocker.patch.object(QtWidgets.QInputDialog, 'textValue', return_value="Basics") - mocker.patch.object(AppEditDialog, 'exec', return_value=QtWidgets.QDialog.DialogCode.Accepted) + mocker.patch.object( + QtWidgets.QInputDialog, "exec", return_value=QtWidgets.QInputDialog.DialogCode.Accepted + ) + mocker.patch.object(QtWidgets.QInputDialog, "textValue", return_value="Basics") + mocker.patch.object( + QtWidgets.QDialog, "exec", return_value=QtWidgets.QDialog.DialogCode.Accepted + ) lpe.on_add_app_link_from_file(None) # assert that the link has been created @@ -449,17 +497,25 @@ def test_local_package_explorer_file_generic_functions(qtbot, mocker, base_fixtu assert str(last_app_link.conan_file_reference) == str(cfr) # 2.5 check edit file - # Cheat here: use the selected file as the name of the editor and the file to be opened too + # Cheat here: use the selected file as the name of the editor and the file to be opened too # - only check the mocked CLI call mock_execute_cmd = mocker.patch("package_explorer.file_controller.execute_cmd") app.active_settings.set(FILE_EDITOR_EXECUTABLE, str(selected_pkg_file)) lpe.on_edit_file(None) - mock_execute_cmd.assert_called_with([str(selected_pkg_file), selected_pkg_file.as_posix()], False) - -def test_local_package_explorer_file_specific_functions(qtbot, mocker, base_fixture, - ui_no_refs_config_fixture, setup_local_package_explorer: LPESetupType): - """ Test file related context menu functions of File View + mock_execute_cmd.assert_called_with( + [str(selected_pkg_file), selected_pkg_file.as_posix()], False + ) + + +def test_local_package_explorer_file_specific_functions( + qtbot, + mocker, + base_fixture, + ui_no_refs_config_fixture, + setup_local_package_explorer: LPESetupType, +): + """Test file related context menu functions of File View 1. Change to Page, check if the installed package is in the list. 2. Expand ref and select the pkg, fileview should open. 1. Copy - copy file to clipboard (MIME) @@ -497,7 +553,7 @@ def test_local_package_explorer_file_specific_functions(qtbot, mocker, base_fixt # 2.0 execuite context menu elem_pos = lpe._pkg_tabs_ctrl[0]._view.visualRect(sel_idx) - mocker.patch.object(lpe._file_cntx_menu, 'exec') + mocker.patch.object(lpe._file_cntx_menu, "exec") # check that on multiple selection diff pkg action is enabled lpe.on_file_context_menu_requested(elem_pos.center()) @@ -511,13 +567,15 @@ def test_local_package_explorer_file_specific_functions(qtbot, mocker, base_fixt # 2.2 check paste Logger().debug("check paste") - config_path: Path = ui_no_refs_config_fixture # use the config file as test data to be pasted + config_path: Path = ( + ui_no_refs_config_fixture # use the config file as test data to be pasted + ) data = QtCore.QMimeData() url = QtCore.QUrl.fromLocalFile(str(config_path)) data.setUrls([url]) _qapp_instance.clipboard().setMimeData(data) - - delete_path((pkg_root_path / config_path.name)) # delete file is there + + delete_path((pkg_root_path / config_path.name)) # delete file is there lpe.on_file_paste(None) # check new file check.is_true((pkg_root_path / config_path.name).exists()) @@ -529,7 +587,9 @@ def test_local_package_explorer_file_specific_functions(qtbot, mocker, base_fixt sel_idx = lpe._pkg_tabs_ctrl[0].select_file_item(str(pkg_root_path / config_path.name)) mime_files = lpe.on_file_cut(None) - file_index = lpe._pkg_tabs_ctrl[0]._model.index((pkg_root_path / config_path.name).as_posix(), 0) + file_index = lpe._pkg_tabs_ctrl[0]._model.index( + (pkg_root_path / config_path.name).as_posix(), 0 + ) check.is_true(file_index in lpe._pkg_tabs_ctrl[0]._model._disabled_indexes) # 2.4 check cut-paste @@ -547,7 +607,7 @@ def test_local_package_explorer_file_specific_functions(qtbot, mocker, base_fixt # 2.5 check rename Logger().debug("check rename") - mock_rename_cmd = mocker.patch.object(QtWidgets.QTreeView, 'edit') + mock_rename_cmd = mocker.patch.object(QtWidgets.QTreeView, "edit") lpe.on_item_rename(None) mock_rename_cmd.assert_called_once() @@ -558,53 +618,63 @@ def test_local_package_explorer_file_specific_functions(qtbot, mocker, base_fixt lpe._pkg_tabs_ctrl[0].select_file_item(str(pkg_root_path / config_path.name)) mime_files = lpe.on_file_copy(None) - + # select no in dialog mock_copy_cmd = mocker.patch("package_explorer.file_controller.copy_path_with_overwrite") - mocker.patch.object(QtWidgets.QDialog, 'exec', - return_value=QtWidgets.QDialog.DialogCode.Rejected) - + mocker.patch.object( + QtWidgets.QDialog, "exec", return_value=QtWidgets.QDialog.DialogCode.Rejected + ) + lpe.on_file_paste(None) mock_copy_cmd.assert_not_called() - # 2.7 check auto renaming + # 2.7 check auto renaming Logger().debug("check overwrite auto renaming") mock_copy_cmd = mocker.patch("package_explorer.file_controller.copy_path_with_overwrite") renamed_file = pkg_root_path / "app_config_empty_refs (2).json" assert (pkg_root_path / config_path.name).exists() try: - os.remove(renamed_file) # ensure file does not exist - except: # nothing to do here + os.remove(renamed_file) # ensure file does not exist + except: # nothing to do here pass - mocker.patch.object(QtWidgets.QDialog, 'exec', - return_value=QtWidgets.QDialog.DialogCode.Accepted) - lpe._pkg_tabs_ctrl[0].paste_path(pkg_root_path / config_path.name, pkg_root_path / config_path.name) + mocker.patch.object( + QtWidgets.QDialog, "exec", return_value=QtWidgets.QDialog.DialogCode.Accepted + ) + lpe._pkg_tabs_ctrl[0].paste_path( + pkg_root_path / config_path.name, pkg_root_path / config_path.name + ) mock_copy_cmd.assert_called_with(pkg_root_path / config_path.name, renamed_file) # 2.8 check delete Logger().debug("delete") - sel_idx = lpe._pkg_tabs_ctrl[0].select_file_item( - str(pkg_root_path / config_path.name)) + sel_idx = lpe._pkg_tabs_ctrl[0].select_file_item(str(pkg_root_path / config_path.name)) sleep(1) - mocker.patch.object(QtWidgets.QMessageBox, 'exec', - return_value=QtWidgets.QMessageBox.StandardButton.Yes) + mocker.patch.object( + QtWidgets.QMessageBox, "exec", return_value=QtWidgets.QMessageBox.StandardButton.Yes + ) lpe.on_file_delete(None) # check new file? check.is_false((pkg_root_path / config_path.name).exists()) # @pytest.mark.conanv2 # def test_delete_package_dialog(qtbot, mocker, ui_config_fixture, base_fixture): -# """ Test, that the delete package dialog deletes a reference with id, +# """ Test, that the delete package dialog deletes a reference with id, # without id and cancel does nothing""" # # TODO: Test with multiselect in LocalPackageExplorer # pass -def test_new_folder(qtbot, mocker, base_fixture, - ui_no_refs_config_fixture, setup_local_package_explorer: LPESetupType): - """ Test, that a creating a new folder works in the gui and selects the file - and applies the rename function on it. """ + +def test_new_folder( + qtbot, + mocker, + base_fixture, + ui_no_refs_config_fixture, + setup_local_package_explorer: LPESetupType, +): + """Test, that a creating a new folder works in the gui and selects the file + and applies the rename function on it.""" _qapp_instance, lpe, main_gui = setup_local_package_explorer cfr = ConanRef.loads(TEST_REF) id, pkg_path = app.conan_api.install_best_matching_package(cfr) @@ -623,17 +693,15 @@ def test_new_folder(qtbot, mocker, base_fixture, if target_dir_path.exists(): target_dir_path.rmdir() - # create new folder in model root folder (special case) - mock_rename_cmd = mocker.patch.object(QtWidgets.QTreeView, 'edit') + mock_rename_cmd = mocker.patch.object(QtWidgets.QTreeView, "edit") lpe.on_new_folder(QtCore.QModelIndex()) mock_rename_cmd.assert_called_once() assert target_dir_path.is_dir() target_dir_path.rmdir() - # Setup: select a file and call new folder - mock_rename_cmd = mocker.patch.object(QtWidgets.QTreeView, 'edit') + mock_rename_cmd = mocker.patch.object(QtWidgets.QTreeView, "edit") selected_pkg_file = pkg_root_path / "conaninfo.txt" sel_idx = lpe._pkg_tabs_ctrl[0].select_file_item(str(selected_pkg_file)) lpe.on_new_folder(sel_idx) diff --git a/test/conftest.py b/test/conftest.py index cedd7b6a..c50565c9 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,5 +1,3 @@ -from contextlib import contextmanager -from datetime import datetime, timedelta import configparser import ctypes import os @@ -8,6 +6,8 @@ import sys import tempfile import time +from contextlib import contextmanager +from datetime import datetime, timedelta from pathlib import Path from subprocess import CalledProcessError, check_output from threading import Thread @@ -16,17 +16,16 @@ import psutil import pytest +from conan_unified_api.types import ConanRef + import conan_explorer.app as app # resolve circular dependencies -from conan_explorer import SETTINGS_FILE_NAME, base_path, user_save_path +from conan_explorer import SETTINGS_FILE_NAME, base_path, conan_version, user_save_path from conan_explorer.app.system import str2bool -from conan_explorer.conan_wrapper import ConanInfoCache, ConanWorker from conan_explorer.conan_wrapper import ConanApiFactory as ConanApi - +from conan_explorer.conan_wrapper import ConanInfoCache, ConanWorker +from conan_explorer.settings import * from conan_explorer.ui.common import remove_qt_logger from conan_explorer.ui.main_window import MainWindow -from conan_explorer.settings import * -from conan_unified_api.types import ConanRef -from conan_explorer import conan_version exe_ext = ".exe" if platform.system() == "Windows" else "" conan_server_thread = None @@ -39,22 +38,23 @@ def is_ci_job(): - """ Test runs in CI environment """ + """Test runs in CI environment""" if os.getenv("GITHUB_WORKSPACE"): return True return False def get_window_pid(title): - import win32process import win32gui + import win32process + hwnd = win32gui.FindWindow(None, title) _, pid = win32process.GetWindowThreadProcessId(hwnd) return pid -class PathSetup(): - """ Get the important paths form the source repo. """ +class PathSetup: + """Get the important paths form the source repo.""" def __init__(self): self.test_path = Path(os.path.dirname(__file__)) @@ -62,12 +62,14 @@ def __init__(self): self.testdata_path = self.test_path / "testdata" -def check_if_process_running(process_name, cmd_contains=[], kill=False, cmd_narg=1, timeout_s=10) -> bool: +def check_if_process_running( + process_name, cmd_contains=[], kill=False, cmd_narg=1, timeout_s=10 +) -> bool: start_time = datetime.now() while datetime.now() - start_time < timedelta(seconds=timeout_s) or timeout_s == 0: for process in psutil.process_iter(): try: - print(f"Checking process {process.pid} : {process.name()}") + # print(f"Checking process {process.pid} : {process.name()}") if process_name.lower() in process.name().lower(): matches = 0 cmdline = "" @@ -86,9 +88,16 @@ def check_if_process_running(process_name, cmd_contains=[], kill=False, cmd_narg process.kill() return True else: - print(f"Not matching arguments: {cmd_contains} in cmdline {cmdline} arg nr. {cmd_narg}") - - except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess, IndexError): + print( + f"Not matching arguments: {cmd_contains} in cmdline {cmdline} arg nr. {cmd_narg}" + ) + + except ( + psutil.NoSuchProcess, + psutil.AccessDenied, + psutil.ZombieProcess, + IndexError, + ): pass print(f"Not found process {process_name}, keep looking...") if timeout_s == 0: @@ -110,25 +119,30 @@ def conan_install_ref(ref, args="", profile=None): args += " -pr " + str(profiles_path / profile) assert os.system(f"conan install {extra_cmd} {ref} {args}") == 0 + def conan_remove_ref(ref): if conan_version.major == 2: os.system(f"conan remove {ref} -c") else: os.system(f"conan remove {ref} -f") -def conan_add_editables(conanfile_path: str, reference: ConanRef): # , path: str + +def conan_add_editables(conanfile_path: str, reference: ConanRef): # , path: str if conan_version.major == 2: - os.system(f"conan editable add --version {reference.version} " - f"--channel {reference.channel} --user {reference.user} {conanfile_path}") + os.system( + f"conan editable add --version {reference.version} " + f"--channel {reference.channel} --user {reference.user} {conanfile_path}" + ) else: os.system(f"conan editable add {conanfile_path} {str(reference)}") + def conan_create_and_upload(conanfile: str, ref: str, create_params=""): if conan_version.major == 1: os.system(f"conan create {conanfile} {ref} {create_params}") os.system(f"conan upload {ref} -r {TEST_REMOTE_NAME} --force --all") elif conan_version.major == 2: - ref = ref.replace("@_/_", "") # does not work anymore... + ref = ref.replace("@_/_", "") # does not work anymore... cfr = ConanRef.loads(ref) extra_args = "" if cfr.user: @@ -136,13 +150,14 @@ def conan_create_and_upload(conanfile: str, ref: str, create_params=""): if cfr.channel: extra_args += f"--channel={cfr.channel} " os.system( - f"conan create {conanfile} --name={cfr.name} --version={cfr.version} {extra_args} {create_params}") + f"conan create {conanfile} --name={cfr.name} --version={cfr.version} {extra_args} {create_params}" + ) os.system(f"conan upload {ref} -r {TEST_REMOTE_NAME} --force") def create_test_ref(ref, paths, create_params=[""], update=False): if conan_version.major == 2: - ref = ref.replace("@_/_", "") # does not work anymore... + ref = ref.replace("@_/_", "") # does not work anymore... native_ref = str(ConanRef.loads(ref)) conan = ConanApi() conan.init_api() @@ -160,15 +175,18 @@ def create_test_ref(ref, paths, create_params=[""], update=False): for param in create_params: conan_create_and_upload(conanfile, ref, param) + def add_remote(remote_name, url): if conan_version.major == 1: os.system(f"conan remote add {remote_name} {url} false") elif conan_version.major == 2: os.system(f"conan remote add {remote_name} {url} --insecure") + def remove_remote(remote_name): os.system(f"conan remote remove {remote_name}") + def login_test_remote(remote_name): if conan_version.major == 1: os.system(f"conan user demo -r {remote_name} -p demo") @@ -176,11 +194,13 @@ def login_test_remote(remote_name): elif conan_version.major == 2: os.system(f"conan remote login {remote_name} demo -p demo") + def logout_all_remotes(): if conan_version.major == 1: os.system("conan user --clean") elif conan_version.major == 2: - os.system('conan remote logout "*"') # need " for linux + os.system('conan remote logout "*"') # need " for linux + def clean_remotes_on_ci(): if not is_ci_job(): @@ -191,12 +211,14 @@ def clean_remotes_on_ci(): elif conan_version.major == 2: os.system("conan remote remove conancenter") + def get_profiles(): profiles = ["windows", "linux"] if conan_version.major == 2: profiles = ["windowsV2", "linuxV2"] return profiles + def get_current_profile(): profiles = get_profiles() for profile in profiles: @@ -220,7 +242,7 @@ def start_conan_server(): if "write_permissions" not in cp: cp.add_section("write_permissions") cp["write_permissions"]["*/*@*/*"] = "*" - with config_path.open('w', encoding="utf8") as fd: + with config_path.open("w", encoding="utf8") as fd: cp.write(fd) # Setup default profile @@ -230,7 +252,10 @@ def start_conan_server(): conan = ConanApi() conan.init_api() os.makedirs(conan._client_cache.profiles_path, exist_ok=True) - shutil.copy(str(profiles_path / platform.system().lower()), conan._client_cache.default_profile_path) + shutil.copy( + str(profiles_path / platform.system().lower()), + conan._client_cache.default_profile_path, + ) elif conan_version.major == 2: os.system("conan profile detect") @@ -263,15 +288,19 @@ def start_conan_server(): for profile in get_profiles(): profile_path = profiles_path / profile - create_test_ref(TEST_REF, paths, [f"-pr {str(profile_path)}", - f"-o shared=False -pr {str(profile_path)}"], update=True) + create_test_ref( + TEST_REF, + paths, + [f"-pr {str(profile_path)}", f"-o shared=False -pr {str(profile_path)}"], + update=True, + ) create_test_ref(TEST_REF_OFFICIAL, paths, [f"-pr {str(profile_path)}"], update=True) if not conan_version.major == 2: paths = PathSetup() conanfile = str(paths.testdata_path / "conan" / "conanfile_no_settings.py") - conan_create_and_upload(conanfile, "nocompsettings/1.0.0@local/no_sets") + conan_create_and_upload(conanfile, "nocompsettings/1.0.0@local/no_sets") # create many packages - #if not conan_version.major == 2: + # if not conan_version.major == 2: # for i in range(9,100): # print(f"Copying index {i}") # os.system(f"conan alias example/9.9.{i}@local/alias {TEST_REF}") @@ -301,6 +330,7 @@ def test_output(): def app_qt_fixture(qtbot): yield qtbot import conan_explorer.app as app + # remove logger, so the logger doesn't log into nonexistant qt gui remove_qt_logger(app.Logger(), MainWindow.qt_logger_name) # finish worker - otherwise errors and crashes will occur! @@ -309,7 +339,7 @@ def app_qt_fixture(qtbot): @pytest.fixture -def base_fixture()-> Generator[PathSetup, None, None]: +def base_fixture() -> Generator[PathSetup, None, None]: """ Set up the global variables to be able to start the application. Needs to be used, if the tested component uses the global Logger. @@ -353,6 +383,7 @@ def base_fixture()-> Generator[PathSetup, None, None]: @pytest.fixture def light_theme_fixture(base_fixture): import conan_explorer.app as app + app.active_settings.set(GUI_MODE, GUI_MODE_LIGHT) app.active_settings.set(GUI_STYLE, GUI_STYLE_MATERIAL) @@ -369,14 +400,14 @@ def temp_ui_config(config_file_path: Path): @pytest.fixture def ui_config_fixture(base_fixture): - """ Use temporary default settings and config file based on testdata/app_config.json """ + """Use temporary default settings and config file based on testdata/app_config.json""" config_file_path = base_fixture.testdata_path / "app_config.json" yield temp_ui_config(config_file_path) @pytest.fixture def ui_no_refs_config_fixture(base_fixture): - """ Use temporary default settings and config file based on testdata/app_config_empty_refs.json """ + """Use temporary default settings and config file based on testdata/app_config_empty_refs.json""" config_file_path = base_fixture.testdata_path / "app_config_empty_refs.json" yield temp_ui_config(config_file_path) @@ -384,12 +415,14 @@ def ui_no_refs_config_fixture(base_fixture): @pytest.fixture def mock_clipboard(mocker): from PySide6.QtWidgets import QApplication - mocker.patch.object(QApplication, 'clipboard') + + mocker.patch.object(QApplication, "clipboard") clipboard = mock.MagicMock() clipboard.supportsSelection.return_value = True QApplication.clipboard.return_value = clipboard return clipboard + @contextmanager def escape_venv(): # don't do this while testing! if it errors or the gui is closed, while this is running, @@ -401,8 +434,9 @@ def escape_venv(): path_var = os.environ.get("PATH", "") bin_path = Path(sys.executable).parent import re + path_regex = re.compile(re.escape(str(bin_path)), re.IGNORECASE) - new_path_var = path_regex.sub('', path_var) + new_path_var = path_regex.sub("", path_var) apply_vars = {"PATH": new_path_var} old_env = dict(os.environ) os.environ.update(apply_vars) @@ -410,4 +444,4 @@ def escape_venv(): yield finally: os.environ.clear() - os.environ.update(old_env) \ No newline at end of file + os.environ.update(old_env)