Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
46 changes: 46 additions & 0 deletions .github/workflows/test_linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Test Linux

on: [push, pull_request]

jobs:
test-linux:
name: Test Linux
runs-on: ubuntu-22.04
steps:
- name: "Check out the repo"
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install system dependencies
run: |
sudo apt update && sudo apt install -y \
xvfb xauth \
libgl1 libglx-mesa0 libgl1-mesa-dri libglu1-mesa libegl1-mesa mesa-utils libopengl0 \
libx11-6 libx11-xcb1 libxext6 libxrender1 libsm6 libice6 libxxf86vm1 libxdamage1 libxfixes3 \
libxcb-glx0 libxcb-dri2-0 libxcb-dri3-0 libxcb-present0 libxcb-shape0 libxcb-shm0 libxcb-sync1 \
libxcb-xfixes0 libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 \
fontconfig fonts-dejavu-core
sudo fc-cache -f

- name: Install packages
run: |
pip install -e .
pip install .[test]
pip list

- name: Run tests
env:
LIBGL_ALWAYS_SOFTWARE: "1"
MESA_LOADER_DRIVER_OVERRIDE: "swrast"
GALLIUM_DRIVER: "llvmpipe"
LIBGL_DRIVERS_PATH: "/usr/lib/x86_64-linux-gnu/dri"
QT_OPENGL: "software"
QT_QPA_PLATFORM: "xcb"
uses: coactions/setup-xvfb@v1.0.1
with:
run: pytest
56 changes: 0 additions & 56 deletions appveyor.yml

This file was deleted.

1 change: 0 additions & 1 deletion cq_editor/cqe_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@

from cq_editor.__main__ import main


if __name__ == "__main__":
main()
1 change: 0 additions & 1 deletion cq_editor/widgets/code_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPalette, QColor


DARK_BLUE = QtGui.QColor(118, 150, 185)


Expand Down
14 changes: 13 additions & 1 deletion cq_editor/widgets/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ def __init__(self, customBanner=None, namespace=dict(), *args, **kwargs):

self.kernel_manager = kernel_manager = QtInProcessKernelManager()
kernel_manager.start_kernel(show_banner=False)
kernel_manager.kernel.gui = "qt"
kernel_manager.kernel.shell.display_banner = False
kernel_manager.kernel.shell.banner1 = ""
kernel_manager.kernel.gui = "qt"

self.kernel_client = kernel_client = self._kernel_manager.client()
kernel_client.start_channels()
Expand All @@ -66,6 +67,17 @@ def stop():

self.push_vars(namespace)

def _append_plain_text(self, text, *args, **kwargs):
"""
Overrides the super's method to filter out IPython tips.
"""
# Drop IPython startup tips (including the unicode completion tip)
# Done because turning the banner off does not work
if isinstance(text, str) and text.lstrip().startswith("Tip:"):
return

return super(ConsoleWidget, self)._append_plain_text(text, *args, **kwargs)

@pyqtSlot(dict)
def push_vars(self, variableDict):
"""
Expand Down
28 changes: 27 additions & 1 deletion cq_editor/widgets/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,32 @@ def __init__(self, log_widget, *args, **kwargs):

self._qobject = _QtLogHandlerQObject()
self._qobject.sigRecordEmit.connect(log_widget.append)
self._is_closed = False

def emit(self, record):
self._qobject.sigRecordEmit.emit(self.format(record) + "\n")
# Skip emit if handler has been closed
if self._is_closed or self._qobject is None:
# No-op when Qt side is no longer valid
return

# Protect signal emission against Qt object lifetime race at shutdown
try:
self._qobject.sigRecordEmit.emit(self.format(record) + "\n")
# Catch wrapped C/C++ deletion error during teardown
except RuntimeError:
# Mark handler closed so future emits are ignored
self._is_closed = True
# Drop QObject reference to avoid further access
self._qobject = None

# Explicit close hook to safely disable handler at teardown
def close(self):
# Mark handler as closed
self._is_closed = True
# Release QObject reference
self._qobject = None
# Preserve base class close behavior
super(QtLogHandler, self).close()


class LogViewer(QPlainTextEdit, ComponentMixin):
Expand All @@ -64,6 +87,9 @@ def __init__(self, *args, **kwargs):

self.handler = QtLogHandler(self)

# Ensure handler is closed when widget is destroyed
self.destroyed.connect(lambda *_: self.handler.close())

def append(self, msg):
"""Append text to the panel with ANSI escape sequences stipped."""
self.moveCursor(QtGui.QTextCursor.End)
Expand Down
1 change: 0 additions & 1 deletion cq_editor/widgets/occt_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from OCP.AIS import AIS_InteractiveContext, AIS_DisplayMode
from OCP.Quantity import Quantity_Color


ZOOM_STEP = 0.9


Expand Down
1 change: 0 additions & 1 deletion cq_editor/widgets/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from pyqtgraph.parametertree import Parameter
import qtawesome as qta


DEFAULT_EDGE_COLOR = Quantity_Color(BLACK)
DEFAULT_EDGE_WIDTH = 2

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ name = "CQ-editor"
version = "0.6"
dependencies = [
"cadquery",
"PyQt5",
"pyqtgraph",
"qtawesome==1.4.0",
"path",
Expand Down
1 change: 0 additions & 1 deletion run.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@

from cq_editor.__main__ import main


if __name__ == "__main__":
main()
13 changes: 9 additions & 4 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -982,20 +982,25 @@ def test_viewer(main):
assert(dummy())"""


def test_module_import(main):
def test_module_import(main, tmp_path, monkeypatch):

qtbot, win = main

editor = win.components["editor"]
debugger = win.components["debugger"]
traceback_view = win.components["traceback_viewer"]

# isolate test files in a temp directory
monkeypatch.chdir(tmp_path)

# save the dummy module
with open("module.py", "w") as f:
f.write(code_module)
module_file = tmp_path / "module.py"
module_file.write_text(code_module)

# run the code importing this module
editor.set_text(code_import)
script_file = tmp_path / "main.py"
script_file.write_text(code_import)
editor.load_from_file(str(script_file))
debugger._actions["Run"][0].triggered.emit()

# verify that no exception was generated
Expand Down