Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

code linting & docs tidy #79

Merged
merged 10 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# automated code formatting (pre-commit)
5c797ae2f3dcc2c47fec4c09d28ce656114bcbbd
2 changes: 2 additions & 0 deletions .mailmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Laura Murgatroyd <[email protected]> <[email protected]>
Laura Murgatroyd <[email protected]> lauramurgatroyd
55 changes: 55 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
default_language_version:
python: python3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-toml
- id: check-merge-conflict
- id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: mixed-line-ending
- id: sort-simple-yaml
- id: trailing-whitespace
- repo: local
hooks:
- id: todo
name: Check TODO
language: pygrep
args: [-i]
entry: TODO
types: [text]
exclude: ^(.pre-commit-config.yaml|.github/workflows/test.yml)$
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
hooks:
- id: flake8
args: [-j8]
additional_dependencies:
- flake8-broken-line
- flake8-bugbear
- flake8-comprehensions
- flake8-debugger
- flake8-isort
- flake8-pyproject
- flake8-string-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.4.1
hooks:
- id: mypy
additional_dependencies: [types-setuptools]
- repo: https://github.com/google/yapf
rev: v0.40.0
hooks:
- id: yapf
args: [-i]
additional_dependencies: [toml]
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
33 changes: 25 additions & 8 deletions .github/workflows/README.md → CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,43 @@
# GitHub Actions
# Developer Contribution Guide

## Local

```sh
# Clone (download) source code
git clone [email protected]:TomographicImaging/eqt
cd eqt
# Install git hooks for automatic sanity checking when trying to commit
pip install pre-commit
pre-commit install
# Install test dependencies
pip install .[dev]
# Run tests
pytest
```

## CI

Runs automatically on every commit via [test.yml](./test.yml).
GitHub Actions runs automatically on every commit via [test.yml](.github/workflows/test.yml).

## Testing
### Testing

Runs `pytest`.

## Building
### Building

Runs automatically after tests (above) succeed.

Builds binary (`*.whl`) & source (`*.tar.gz`) distributions.

## Releasing
### Releasing

Runs automatically -- when an annotated tag is pushed -- after builds (above) succeed.

Publishes to [PyPI](https://pypi.org/project/eqt).

:warning: The annotated tag's `title` must be `Version <number without v-prefix>` (separated by a blank line) and the `body` must contain release notes, e.g.:

```bash
```sh
git tag v1.33.7 -a
```

Expand All @@ -32,11 +49,11 @@ Version 1.33.7

The `<body>` will be used in the changelog (below).

### Changelog
#### Changelog

See <https://github.com/TomographicImaging/eqt/releases>, or offline:

```bash
```sh
git config --global alias.changelog 'for-each-ref --sort=-*authordate --format="# %(contents:subject)%0a%(contents:body)" refs/tags'
git changelog
```
38 changes: 22 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## Qt Elements eqt
# eqt: Qt Elements

[![Tests](https://img.shields.io/github/actions/workflow/status/TomographicImaging/eqt/test.yml?branch=main&label=Tests&logo=GitHub)](https://github.com/casperdcl/cdcl/actions)

A number of templates and tools to develop Qt GUI's with Python effectively.

Expand All @@ -7,14 +9,13 @@ running some task asynchronously so that the interface is still responsive.

This little package tries to address both recurring requirements.


1. `UIFormWidget`, a class to help creating Qt forms
programmatically, useable in `QDockWidgets` and `QWidget`
1. `FormDialog`, a `QDialog` with a form inside with OK and Cancel button
1. `Worker`, a class that defines a `QRunnable` to
programmatically, useable in `QDockWidgets` and `QWidget`
2. `FormDialog`, a `QDialog` with a form inside with OK and Cancel button
3. `Worker`, a class that defines a `QRunnable` to
handle worker thread setup, signals and wrap up

### Installation
## Installation

You may install via `pip` or `conda`

Expand All @@ -24,10 +25,12 @@ python -m pip install eqt
conda install eqt -c paskino
```

### Example
In the `example` directory there is an example on how to launch a `QDialog` with a form inside using `eqt`'s [`QWidget`](https://github.com/TomographicImaging/eqt/blob/main/examples/dialog_example.py) or [`FormDialog`](https://github.com/TomographicImaging/eqt/blob/main/examples/dialog_example_2.py).
## Examples

In the `example` directory there is an example on how to launch a `QDialog` with a form inside using `eqt`'s [`QWidget`](examples/dialog_example.py) or [`FormDialog`](examples/dialog_example_2.py).

### Running asynchronous tasks

To run a function in a separate thread we use a `Worker` which is a subclass of a `QRunnable`.

For the `Worker` to work one needs to define:
Expand Down Expand Up @@ -72,7 +75,8 @@ def fn(num_iter, **kwargs):
progress_callback.emit( i )
```

#### But how are the signal passed to the Worker anyway?
### Passing a signal to a Worker

This is done just after one has defined the `Worker`:

```python
Expand All @@ -86,16 +90,18 @@ worker.signals.progress.connect(handle_progress)

So, each time `fn` comes to `progress_callback.emit( i )` the function `handle_progress` will be called with the parameter `i` of its `for` loop.

#### What are the available signals?
### Signals available

The signals that are available in the `Worker` class are defined in [`WorkerSignal`](https://github.com/TomographicImaging/eqt/blob/535e487d09d928713d7d6aa1123657597627c4b0/eqt/threading/QtThreading.py#L66) and are the following. Below you can also see the type of data that each signal can emit.

```python
finished = QtCore.Signal()
error = QtCore.Signal(tuple)
result = QtCore.Signal(object)
finished = QtCore.Signal()
error = QtCore.Signal(tuple)
result = QtCore.Signal(object)

progress = QtCore.Signal(int)
message = QtCore.Signal(str)
status = QtCore.Signal(tuple)
progress = QtCore.Signal(int)
message = QtCore.Signal(str)
status = QtCore.Signal(tuple)
```

Read more on [Qt signals and slots](https://doc.qt.io/qt-5/signalsandslots.html) and on how to use them in [pyside2](https://wiki.qt.io/Qt_for_Python_Signals_and_Slots).
2 changes: 1 addition & 1 deletion eqt/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import zipfile


def zip_directory(directory: str, compress: bool=True):
def zip_directory(directory: str, compress: bool = True):
"""
Zips a directory, optionally compressing it.

Expand Down
36 changes: 18 additions & 18 deletions eqt/threading/QtThreading.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
# -*- coding: utf-8 -*-
"""
Basic classes for Threading a Qt application
Created on Wed Feb 6 11:10:36 2019

@author: ofn77899
"""
import sys

#https://www.geeksforgeeks.org/migrate-pyqt5-app-to-pyside2/
# https://www.geeksforgeeks.org/migrate-pyqt5-app-to-pyside2
import traceback
import sys

from PySide2 import QtCore
from PySide2.QtCore import Slot


class Worker(QtCore.QRunnable):
"""Worker: defines a QRunnable to execute a function asynchronously. It handles worker thread setup, signals and wrapup."""

"""Executes a function asynchronously. Handles worker thread setup, signals, and wrapup."""
def __init__(self, fn, *args, **kwargs):
'''Worker creator
:param fn: The function to be run by this Worker in a different thread.

:param fn: The function to be run by this Worker in a different thread.
:param args: positional arguments to pass to the function
:param kwargs: keyword arguments to pass to the function

The creator will add progress_callback, message_callback and status_callback to the kwargs.
'''
super(Worker, self).__init__()
Expand All @@ -40,15 +38,16 @@ def __init__(self, fn, *args, **kwargs):
def run(self):
"""
Run the worker. Emits signals based on run state.
Signals:
- Error: Emitted when an exception is thrown in the workers function.
- Result: Emitted if function completes successfully. Contains the return value of the function.
- Finished: Emitted on completion of the worker thread.

Signals
-------
- Error: An exception is thrown in the workers function.
- Result: Contains the return value of a function that has just completed successfully.
- Finished: Worker thread has completed.
"""
try:
result = self.fn(*self.args, **self.kwargs)
except:
except BaseException:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
Expand All @@ -57,6 +56,7 @@ def run(self):
finally:
self.signals.finished.emit()


class WorkerSignals(QtCore.QObject):
"""
Defines signals available when running a worker thread
Expand All @@ -72,17 +72,17 @@ class WorkerSignals(QtCore.QObject):

progress
`int` indicating % progress

message
`string` with some text
status
`tuple`
`tuple`
"""

finished = QtCore.Signal()
error = QtCore.Signal(tuple)
result = QtCore.Signal(object)

progress = QtCore.Signal(int)
message = QtCore.Signal(str)
status = QtCore.Signal(tuple)
5 changes: 3 additions & 2 deletions eqt/threading/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .QtThreading import Worker
from .QtThreading import WorkerSignals
from .QtThreading import Worker, WorkerSignals

__all__ = ['Worker', 'WorkerSignals']
Loading