Skip to content
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
25 changes: 25 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM python:3.11-bookworm

# Install system dependencies
RUN apt-get update && apt-get install -y \
build-essential \
git \
libgl1-mesa-dev \
libglu1-mesa-dev \
freeglut3-dev \
mesa-common-dev \
xvfb \
&& rm -rf /var/lib/apt/lists/*

# Install Poetry
RUN pip install poetry

# Set up a non-root user
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME

# Switch to the non-root user
USER $USERNAME
30 changes: 30 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "pysdfscad",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"njpwerner.autodocstring",
"ms-python.black-formatter"
],
"settings": {
"python.defaultInterpreterPath": "/home/vscode/.local/bin/poetry",
"python.poetryPath": "/home/vscode/.local/bin/poetry",
"python.testing.pytestEnabled": true,
"editor.formatOnSave": true,
"python.formatting.provider": "black"
}
}
},
"remoteUser": "vscode",
"postCreateCommand": "poetry install --with dev,qtgui --no-root",
"mounts": [
"source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"
],
"workspaceFolder": "/workspace"
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.aider*
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ it mostly doesn't.

![](docs/Screenshot_0.png)

## Development

I use dev containers and nixos.

`nix-shell -p xorg.xhost --run "xhost +local:docker"`
61 changes: 61 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
description = "Python Qt development environment with UV";

inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
# Python and UV
python311
uv

# Qt libraries
#qt6.full
qt6.qtbase
#qt6.qttools

# Python Qt bindings (available system-wide for reference)
python311Packages.pyqt6
python311Packages.pyside6

# Development tools
python311Packages.pip
];

shellHook = ''
echo "Qt Python development environment with UV"
echo "Python: $(python --version)"
echo "UV: $(uv --version)"
echo ""
echo "Use 'uv init' to create a new project"
echo "Use 'uv add pyqt6' or 'uv add pyside6' to add Qt bindings"
echo "Use 'uv run python your_app.py' to run your application"
'';

# Required for Qt applications
QT_QPA_PLATFORM_PLUGIN_PATH = "${pkgs.qt6.qtbase}/lib/qt-6/plugins";
LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath [ pkgs.qt6.qtbase ]}";
};
}
);
}
73 changes: 30 additions & 43 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,53 +1,40 @@
[tool.poetry]
[project]
name = "pysdfscad"
version = "0.1.0"
description = ""
authors = ["Alex Davies <[email protected]>"]
authors = [{ name = "Alex Davies", email = "[email protected]" }]
requires-python = ">=3.10,<3.12"
readme = "README.md"

packages = [
{ include = "pysdfscad" },
{ include = "pysdfscad_qtgui" },
dependencies = [
"sdf",
"lark>=1.1.5,<2",
"loguru>=0.6.0,<0.7",
"click>=8.1.3,<9",
"appdirs>=1.4.4,<2",
"astor>=0.8.1,<0.9",
]

include = ["pysdfscad/openscad.lark"]

[tool.poetry.dependencies]
#python = "^3.10"
python = ">=3.10,<3.12" #Required for pyinstaller
sdf = {git = "https://github.com/fogleman/sdf.git"}
lark = "^1.1.5"
loguru = "^0.6.0"
click = "^8.1.3"
pyqt5 = {version = "^5.15.7", optional = true}
qscintilla = {version = "^2.13.3", optional = true}
pyqtgraph = {version = "^0.13.1", optional = true}
pyopengl = {version = "^3.1.6", optional=true}
appdirs = "^1.4.4"
astor = "^0.8.1"
mkdocs-macros-plugin = "^0.7.0"
[project.scripts]
pysdfscad = "pysdfscad.main:main"
pysdfscad_qtgui = "pysdfscad_qtgui.main:main"

[tool.poetry.extras]
qtgui = ["PyQt5","qscintilla","pysdfscad_qtgui","pyqtgraph","pyopengl"]
#docs = ["Sphinx", "sphinx-rtd-theme",]
[project.optional-dependencies]
gui = [
"pyside6>=6.9.3",
"qscintilla>=2.13.3,<3",
"pyqtgraph>=0.13.1,<0.14",
"pyopengl>=3.1.6,<4",
]
dev = [
"pytest>=7.2.0,<8",
"black>=22.12.0,<23",
]

[tool.poetry.scripts]
pysdfscad = "pysdfscad.main:main"
pysdfscad_qtgui = { callable = "pysdfscad_qtgui.main:main", extras = ["qtgui"] }
[tool.uv]
package = true

[tool.poetry.group.dev.dependencies]
pytest = "^7.2.0"
black = "^22.12.0"
coverage = "^7.0.5"
nuitka = "^1.4.5"
ordered-set = "^4.1.0"
zstandard = "^0.19.0"
pyinstaller = "^5.8.0"
pyinstaller-hooks-contrib = "^2022.15"
mkdocs = "^1.4.2"
mkdocstrings = {extras = ["python"], version = "^0.20.0"}
mkdocs-material = "^9.0.12"
[tool.uv.sources]
sdf = { git = "https://github.com/fogleman/sdf.git" }

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.setuptools]
packages = ["pysdfscad", "pysdfscad_qtgui"]
8 changes: 4 additions & 4 deletions pysdfscad_qtgui/logWidget.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtGui import QTextCursor
from PySide6.QtCore import QObject, Slot as pyqtSlot, Signal as pyqtSignal
from PySide6.QtWidgets import QTextEdit
from PySide6.QtGui import QTextCursor
import shlex
import re
import html
Expand Down Expand Up @@ -35,7 +35,7 @@ def emit(self, record):
self._text.append(msg)
self._update_signal.emit()

@pyqtSlot(object)
@pyqtSlot()
def update(self):
#ToDO, ideally we wouldn't re-render the entire thing every time
# poor performance for the scroll bars
Expand Down
Loading
Loading