Skip to content
Draft
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
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
build:
docker:
# specify the version you desire here
- image: circleci/python:3.6
- image: cimg/python:3.14.6

working_directory: ~/repo

Expand Down Expand Up @@ -47,7 +47,7 @@ jobs:
name: run tests
command: |
. .venv/bin/activate
tox -e py36
tox -e py314

- save_cache:
paths:
Expand All @@ -71,7 +71,7 @@ jobs:

deploy:
docker:
- image: circleci/python:3.6
- image: cimg/python:3.14.6
steps:
- checkout
# Download and cache dependencies
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.*
!.gitignore
!.python-version
*.egg-info
**/__pycache__/**
!.gitignore
*.egg-info
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14.6
6 changes: 5 additions & 1 deletion pyqttoolkit/scripting/script_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,12 @@ def run(self, script, context):
try:
self._context = context
with redirect_output(self._context, self._skip_empty_output_lines):
# Use one namespace so functions defined by the script can
# resolve each other recursively through their globals.
namespace = self._globals(context)
namespace.update(context.locals)
#pylint: disable=exec-used
exec(code, self._globals(context), context.locals)
exec(code, namespace, namespace)
#pylint: enable=exec-used
except ScriptStopped:
pass
Expand Down
5 changes: 5 additions & 0 deletions pyqttoolkit/services/task_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ def __init__(self, parent):
self._is_cancelled = False
self._executor = ThreadPoolExecutor(max_workers=1, thread_name_prefix='TaskRunner_Thread')

def shutdown(self, wait=True):
# Tests and short-lived apps need an explicit way to join worker
# threads before QApplication teardown.
self._executor.shutdown(wait=wait)

def run_task(self, task_function, task_args=None, on_completed=None, on_cancelled=None, on_error=None, description=None, error_description=None, show_progress=True, cancellable=False, force_indeterminate_start=False, **kwargs):
"""function::runTask(self, task_function, task_args, on_completed, on_error)
:param task_function: The function to execute
Expand Down
37 changes: 37 additions & 0 deletions scripts/check_license_headers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
PACKAGE_DIR = ROOT / "pyqttoolkit"
LICENSE_PATH = ROOT / "LICENSE_SHORT"
EXCLUDED_FILENAMES = {"_version.py"}


def commented_license_text() -> str:
lines = LICENSE_PATH.read_text().splitlines()
return "\n".join(f"# {line}" if line else "#" for line in lines)


def main() -> int:
expected_header = commented_license_text()
missing_headers = []

for path in sorted(PACKAGE_DIR.rglob("*.py")):
if path.name in EXCLUDED_FILENAMES:
continue

content = path.read_text().replace("\r\n", "\n")
if not content.startswith(expected_header):
missing_headers.append(path.relative_to(ROOT))

if missing_headers:
print("Missing license header:")
for path in missing_headers:
print(path)
return 1

return 0


if __name__ == "__main__":
raise SystemExit(main())
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
'pytest-cov',
'pytest-xvfb',
'pytest-asyncio',
'pytest-qt',
'licensify'
'pytest-qt'
]

extras_require = {
'test': tests_require,
'publish': ['twine'],
'publish': ['setuptools', 'twine'],
'ui': ['pyqt5']
}

Expand All @@ -49,5 +48,5 @@
description='A toolkit for PyQt 5',
long_description=README_CONTENTS,
long_description_content_type='text/markdown',
python_requires='>=3.6'
python_requires='>=3.14'
)
9 changes: 5 additions & 4 deletions tests/services/test_task_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from pyqttoolkit.services.task_runner import *
from pytestqt.exceptions import capture_exceptions
from pytestqt.qt_compat import qt_api

class Result:
def __init__(self):
Expand All @@ -22,8 +21,10 @@ def value(self):

@pytest.fixture
def task_runner(qtbot):
app = QApplication([])
yield TaskRunner(app)
app = QApplication.instance() or QApplication([])
runner = TaskRunner(app)
yield runner
runner.shutdown()

def _handler(event, result=None):
def _(value):
Expand Down Expand Up @@ -115,7 +116,7 @@ def _task():
with capture_exceptions() as exceptions:
task_runner.run_task(_task)
time.sleep(1)
qt_api.QApplication.instance().processEvents()
QApplication.instance().processEvents()
assert len(exceptions) == 1
assert exceptions[0][1] == exception

Expand Down
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[tox]
envlist=py36
envlist=py314

[testenv]
extras=
test
commands=
; pytest tests --cov pyqttoolkit --ignore tests/services/test_task_runner.py
licensify LICENSE_SHORT --directory pyqttoolkit --files *.py --exclude _version.py --check
python scripts/check_license_headers.py
4 changes: 2 additions & 2 deletions versioneer.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,9 @@ def get_config_from_root(root):
# configparser.NoOptionError (if it lacks "VCS="). See the docstring at
# the top of versioneer.py for instructions on writing your setup.cfg .
setup_cfg = os.path.join(root, "setup.cfg")
parser = configparser.SafeConfigParser()
parser = configparser.ConfigParser()
with open(setup_cfg, "r") as f:
parser.readfp(f)
parser.read_file(f)
VCS = parser.get("versioneer", "VCS") # mandatory

def get(parser, name):
Expand Down