diff --git a/.github/workflows/make_bundle_conda.yml b/.github/workflows/make_bundle_conda.yml index 67f927c4..c7c797dd 100644 --- a/.github/workflows/make_bundle_conda.yml +++ b/.github/workflows/make_bundle_conda.yml @@ -169,7 +169,7 @@ jobs: # See this SO answer for details on conditional matrices # https://stackoverflow.com/a/65434401/3407590 runs-on: ubuntu-latest - outputs: + outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - uses: actions/setup-python@v4 @@ -186,17 +186,17 @@ jobs: "python-version": "3.9", "target-platform": "linux-64", }, - { + { "os": "macos-latest", "python-version": "3.9", "target-platform": "osx-64", }, - { + { "os": "macos-latest", "python-version": "3.9", "target-platform": "osx-arm64", }, - { + { "os": "windows-latest", "python-version": "3.8", "target-platform": "win-64", @@ -204,12 +204,12 @@ jobs: ] platforms_str = "${{ inputs.installer_platforms || 'linux-64,win-64,osx-64,osx-arm64' }}" platforms = {p.strip() for p in platforms_str.split(",")} - + matrix = {"include": []} for element in elements: if element["target-platform"] in platforms: matrix["include"].append(element) - + with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write(f"matrix={json.dumps(matrix)}\n") diff --git a/.github/workflows/pre_commit.yml b/.github/workflows/pre_commit.yml new file mode 100644 index 00000000..01f55f51 --- /dev/null +++ b/.github/workflows/pre_commit.yml @@ -0,0 +1,37 @@ +name: pre-commit + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + test: + name: ${{ matrix.platform }} py${{ matrix.python-version }} + runs-on: ${{ matrix.platform }} + strategy: + matrix: + platform: [ubuntu-latest] + python-version: ['3.10'] + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install pre-commit + pip list + + - name: Pre-commit + run: | + pre-commit run -a diff --git a/.gitignore b/.gitignore index 14ac9dc5..78ae70d8 100644 --- a/.gitignore +++ b/.gitignore @@ -161,4 +161,5 @@ cython_debug/ _work/ -.DS_Store +# OS stuff +.DS_store diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..4475c5bb --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,31 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-docstring-first + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/asottile/pyupgrade + rev: v3.2.2 + hooks: + - id: pyupgrade + args: [--py38-plus, --keep-runtime-typing] + - repo: https://github.com/myint/autoflake + rev: v2.0.0 + hooks: + - id: autoflake + args: ["--in-place", "--remove-all-unused-imports"] + - repo: https://github.com/psf/black + rev: 22.10.0 + hooks: + - id: black + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + additional_dependencies: [flake8-typing-imports>=1.9.0] + args: ["-j8", "--ignore=TYP001,E501,W503"] + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.143 + hooks: + - id: ruff diff --git a/build_installers.py b/build_installers.py index 5eb9a9a4..5d534523 100644 --- a/build_installers.py +++ b/build_installers.py @@ -47,17 +47,16 @@ import zipfile from argparse import ArgumentParser from distutils.spawn import find_executable +from functools import lru_cache, partial from pathlib import Path +from subprocess import check_call, check_output from tempfile import NamedTemporaryFile from textwrap import dedent, indent -from functools import lru_cache, partial -from subprocess import check_call, check_output +import napari import requests from ruamel.yaml import YAML -import napari - yaml = YAML() yaml.indent(mapping=2) indent4 = partial(indent, prefix=" ") @@ -111,7 +110,7 @@ def _version(): return version else: # get latest published on conda-forge - r = requests.get(f"https://api.anaconda.org/package/conda-forge/napari") + r = requests.get("https://api.anaconda.org/package/conda-forge/napari") r.raise_for_status() return r.json()["latest_version"] @@ -357,7 +356,8 @@ def _constructor(version=_version(), extra_specs=None, napari_repo=HERE): raise RuntimeError("Constructor must be installed and in PATH.") # TODO: temporarily patching password - remove block when the secret has been fixed - # (I think it contains an ending newline or something like that, copypaste artifact?) + # (I think it contains an ending newline or something like that, + # copypaste artifact?) pfx_password = os.environ.get("CONSTRUCTOR_PFX_CERTIFICATE_PASSWORD") if pfx_password: os.environ["CONSTRUCTOR_PFX_CERTIFICATE_PASSWORD"] = pfx_password.strip() diff --git a/constructor-manager-ui/src/constructor_manager_ui/main.py b/constructor-manager-ui/src/constructor_manager_ui/main.py index 12acbba9..1aa1ca54 100644 --- a/constructor-manager-ui/src/constructor_manager_ui/main.py +++ b/constructor-manager-ui/src/constructor_manager_ui/main.py @@ -23,16 +23,12 @@ QWidget, ) -# To setup image resources for .qss file -from constructor_manager_ui.style import images -from constructor_manager_ui.style.utils import update_styles - -# To get mock data from constructor_manager_ui.data import ( INSTALL_INFORMATION, - UPDATE_AVAILABLE_VERSION, PACKAGES, + UPDATE_AVAILABLE_VERSION, ) +from constructor_manager_ui.style.utils import update_styles # Packages table constants RELATED_PACKAGES = 0 @@ -136,14 +132,10 @@ def _initialize_update_available_widget(self): # Connect buttons signals to parent class signals skip_version_button.clicked.connect( - lambda checked: self.skip_version.emit( - self.update_available_version - ) + lambda checked: self.skip_version.emit(self.update_available_version) ) install_version_button.clicked.connect( - lambda checked: self.install_version.emit( - self.update_available_version - ) + lambda checked: self.install_version.emit(self.update_available_version) ) def show_checking_updates_message(self): @@ -159,9 +151,7 @@ def show_update_available_message(self, update_available_version): class PackagesTable(QTableWidget): - def __init__( - self, packages, visible_packages=RELATED_PACKAGES, parent=None - ): + def __init__(self, packages, visible_packages=RELATED_PACKAGES, parent=None): super().__init__(parent=parent) self.packages = packages self.visible_packages = visible_packages @@ -186,9 +176,7 @@ def setup(self): self.verticalHeader().setVisible(False) # Set horizontal headers alignment and config - self.horizontalHeader().setDefaultAlignment( - Qt.AlignLeft | Qt.AlignVCenter - ) + self.horizontalHeader().setDefaultAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.horizontalHeader().setStretchLastSection(True) self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) @@ -205,22 +193,11 @@ def set_data(self, packages): for name, version, source, build, related_package in self.packages: self.insertRow(self.rowCount()) package_row = self.rowCount() - 1 - self.setItem( - package_row, 0, self._create_item(name, related_package) - ) - self.setItem( - package_row, 1, self._create_item(version, related_package) - ) - self.setItem( - package_row, 2, self._create_item(source, related_package) - ) - self.setItem( - package_row, 3, self._create_item(build, related_package) - ) - if ( - self.visible_packages == RELATED_PACKAGES - and not related_package - ): + self.setItem(package_row, 0, self._create_item(name, related_package)) + self.setItem(package_row, 1, self._create_item(version, related_package)) + self.setItem(package_row, 2, self._create_item(source, related_package)) + self.setItem(package_row, 3, self._create_item(build, related_package)) + if self.visible_packages == RELATED_PACKAGES and not related_package: self.hideRow(package_row) def change_visible_packages(self, toggled_option): @@ -315,9 +292,7 @@ def _create_packages_group(self): packages_filter_layout = QHBoxLayout() packages_filter_label = QLabel("Show:") - self.packages_spinner_label = SpinnerWidget( - "Loading packages...", parent=self - ) + self.packages_spinner_label = SpinnerWidget("Loading packages...", parent=self) show_detailed_view_checkbox = QCheckBox("Detailed view") show_detailed_view_checkbox.setChecked(False) @@ -412,9 +387,7 @@ def show_up_to_date_message(self): self.updates_widget.show_up_to_date_message() def show_update_available_message(self, update_available_version): - self.updates_widget.show_update_available_message( - update_available_version - ) + self.updates_widget.show_update_available_message(update_available_version) def install_version(self, update_version): # TODO: To be handled with the backend. @@ -471,9 +444,7 @@ def main(package_name): # Change commented lines to check different UI update widget states def data_initialization(): installation_manager_dlg.set_packages(PACKAGES) - installation_manager_dlg.show_update_available_message( - UPDATE_AVAILABLE_VERSION - ) + installation_manager_dlg.show_update_available_message(UPDATE_AVAILABLE_VERSION) # installation_manager_dlg.show_up_to_date_message() QTimer.singleShot(5000, data_initialization) diff --git a/constructor-manager-ui/src/constructor_manager_ui/style/images.py b/constructor-manager-ui/src/constructor_manager_ui/style/images.py index f6a96540..b9cef510 100644 --- a/constructor-manager-ui/src/constructor_manager_ui/style/images.py +++ b/constructor-manager-ui/src/constructor_manager_ui/style/images.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # Resource object code # # Created by: The Resource Compiler for PyQt5 (Qt v5.15.2) @@ -23281,7 +23279,7 @@ \x00\x00\x01\x84\x53\x5b\x17\xfc\ " -qt_version = [int(v) for v in QtCore.qVersion().split('.')] +qt_version = [int(v) for v in QtCore.qVersion().split(".")] if qt_version < [5, 8, 0]: rcc_version = 1 qt_resource_struct = qt_resource_struct_v1 @@ -23289,10 +23287,17 @@ rcc_version = 2 qt_resource_struct = qt_resource_struct_v2 + def qInitResources(): - QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + QtCore.qRegisterResourceData( + rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data + ) + def qCleanupResources(): - QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + QtCore.qUnregisterResourceData( + rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data + ) + qInitResources() diff --git a/constructor-manager-ui/src/constructor_manager_ui/style/images.qrc b/constructor-manager-ui/src/constructor_manager_ui/style/images.qrc index 89d602b6..628331b5 100644 --- a/constructor-manager-ui/src/constructor_manager_ui/style/images.qrc +++ b/constructor-manager-ui/src/constructor_manager_ui/style/images.qrc @@ -10,4 +10,4 @@ images/up_arrow.svg images/loading.gif - \ No newline at end of file + diff --git a/constructor-manager-ui/src/constructor_manager_ui/style/style_variables.txt b/constructor-manager-ui/src/constructor_manager_ui/style/style_variables.txt index cf811a7f..6b41df4c 100644 --- a/constructor-manager-ui/src/constructor_manager_ui/style/style_variables.txt +++ b/constructor-manager-ui/src/constructor_manager_ui/style/style_variables.txt @@ -15,4 +15,4 @@ @background-color15=rgb(163, 41, 53) @background-color16=rgb(137, 16, 27) @background-selection-color01=rgba(0, 122, 204, 100) -@color01=rgb(240, 241, 242) \ No newline at end of file +@color01=rgb(240, 241, 242) diff --git a/constructor-manager-ui/src/constructor_manager_ui/style/utils.py b/constructor-manager-ui/src/constructor_manager_ui/style/utils.py index 38fe2b16..07dc21ed 100644 --- a/constructor-manager-ui/src/constructor_manager_ui/style/utils.py +++ b/constructor-manager-ui/src/constructor_manager_ui/style/utils.py @@ -16,14 +16,11 @@ def _load_styles(stylesheet_file, style_variables={}): def update_styles(app): style_variables = {} - with open(STYLE_VARIABLES, "r") as style_variables_file: + with open(STYLE_VARIABLES) as style_variables_file: for line in style_variables_file: key, value = line.split("=") style_variables[key] = value - with open(QSS_STYLESHEET, "r") as stylesheet_file: + with open(QSS_STYLESHEET) as stylesheet_file: app.setStyleSheet( - _load_styles( - stylesheet_file, - style_variables=style_variables - ) + _load_styles(stylesheet_file, style_variables=style_variables) ) diff --git a/constructor-manager-ui/src/constructor_manager_ui/tests/test_constructor_manager_ui.py b/constructor-manager-ui/src/constructor_manager_ui/tests/test_constructor_manager_ui.py index b3bca64a..9b1ec967 100644 --- a/constructor-manager-ui/src/constructor_manager_ui/tests/test_constructor_manager_ui.py +++ b/constructor-manager-ui/src/constructor_manager_ui/tests/test_constructor_manager_ui.py @@ -2,12 +2,11 @@ import pytest - from constructor_manager_ui.data import ( - PACKAGE_NAME, INSTALL_INFORMATION, + PACKAGE_NAME, + PACKAGES, UPDATE_AVAILABLE_VERSION, - PACKAGES ) from constructor_manager_ui.main import InstallationManagerDialog @@ -26,6 +25,4 @@ def installation_manager_dlg(qtbot): def test_installation_manager_dialog(installation_manager_dlg): installation_manager_dlg.show() installation_manager_dlg.set_packages(PACKAGES) - installation_manager_dlg.show_update_available_message( - UPDATE_AVAILABLE_VERSION - ) + installation_manager_dlg.show_update_available_message(UPDATE_AVAILABLE_VERSION) diff --git a/constructor-manager-ui/tox.ini b/constructor-manager-ui/tox.ini index 1a110817..5d20d538 100644 --- a/constructor-manager-ui/tox.ini +++ b/constructor-manager-ui/tox.ini @@ -31,8 +31,8 @@ passenv = extras = testing pyqt5 -commands = +commands = python -m pip install -e . {linux}: xvfb-run --auto-servernum pytest -v -s --color=yes --cov=constructor_manager_ui --cov-report=xml {macos}: pytest -v -s --color=yes --cov=constructor_manager_ui --cov-report=xml - {windows}: pytest -v -s --color=yes --cov=constructor_manager_ui --cov-report=xml \ No newline at end of file + {windows}: pytest -v -s --color=yes --cov=constructor_manager_ui --cov-report=xml