From 0faf03ecb36effad9434d2e8e586cd06d69c0368 Mon Sep 17 00:00:00 2001 From: maziggy Date: Thu, 5 Mar 2026 10:44:24 +0100 Subject: [PATCH] Fix Python 3.10 compatibility (StrEnum requires 3.11) enum.StrEnum was added in Python 3.11, but the documented minimum is 3.10. Add a compatibility shim in backend/app/core/compat.py that falls back to (str, Enum) on older versions. Updated all 5 import sites and lowered pyproject.toml target-version to py310. --- CHANGELOG.md | 1 + backend/app/core/compat.py | 11 +++++++++++ backend/app/core/permissions.py | 2 +- backend/app/schemas/github_backup.py | 3 ++- backend/app/schemas/notification.py | 3 ++- backend/app/schemas/notification_template.py | 3 ++- backend/app/services/firmware_update.py | 2 +- install/install.sh | 2 +- pyproject.toml | 6 ++++-- 9 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 backend/app/core/compat.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 855fb16ba..2c538721b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to Bambuddy will be documented in this file. - **Print Queue Scheduler Diagnostics** ([#616](https://github.com/maziggy/bambuddy/issues/616)) — Added diagnostic logging to the print queue scheduler to help diagnose why queued prints aren't starting. After each queue check, the scheduler now logs a skip summary (how many items were skipped due to manual_start, scheduled_time, etc.) and for each busy printer, logs the exact state preventing it from being considered idle (connected status, printer state, plate_cleared flag). Previously the scheduler only logged "found N pending items" with no visibility into why items were skipped. ### Fixed +- **Python 3.10 Compatibility** — Bambuddy failed to start on Python 3.10 with `ImportError: cannot import name 'StrEnum' from 'enum'` because `enum.StrEnum` was added in Python 3.11. Added a compatibility shim that falls back to `(str, Enum)` on Python < 3.11, matching the documented requirement of Python 3.10+. - **Bug Report Bubble Overlapping Toasts** — Moved toast notifications and upload progress up so they stack above the bug report bubble instead of overlapping on top of each other. - **Virtual Printer: Bind-TLS Proxy Handshake Failure on OpenSSL 3.x** — The TLS proxy connecting to the printer's bind port (3002) failed with `SSLV3_ALERT_HANDSHAKE_FAILURE` on systems with OpenSSL 3.x (e.g. Python 3.12+) because the default cipher set excludes plain RSA key exchange, which is the only mode Bambu printers support. Added `AES256-GCM-SHA384` and `AES128-GCM-SHA256` to the client SSL context's cipher list. - **Windows: Server Shuts Down After 60 Seconds** ([#605](https://github.com/maziggy/bambuddy/issues/605)) — On Windows, terminating orphaned ffmpeg camera processes broadcast `CTRL_C_EVENT` to the entire process group, causing uvicorn to interpret it as a user-initiated shutdown. ffmpeg is now spawned in its own process group (`CREATE_NEW_PROCESS_GROUP`) so cleanup no longer affects the server. Reported by @Reactantvr. diff --git a/backend/app/core/compat.py b/backend/app/core/compat.py new file mode 100644 index 000000000..1cabc6f3e --- /dev/null +++ b/backend/app/core/compat.py @@ -0,0 +1,11 @@ +"""Compatibility shims for older Python versions.""" + +import sys + +if sys.version_info >= (3, 11): + from enum import StrEnum +else: + from enum import Enum + + class StrEnum(str, Enum): + """Drop-in replacement for enum.StrEnum on Python < 3.11.""" diff --git a/backend/app/core/permissions.py b/backend/app/core/permissions.py index a90eaff2b..29f1aab0a 100644 --- a/backend/app/core/permissions.py +++ b/backend/app/core/permissions.py @@ -4,7 +4,7 @@ This module defines all permissions using a string enum with `resource:action` n Permissions are additive across groups - a user has all permissions from all their groups. """ -from enum import StrEnum +from backend.app.core.compat import StrEnum class Permission(StrEnum): diff --git a/backend/app/schemas/github_backup.py b/backend/app/schemas/github_backup.py index ca3cfe587..f0b5c1d7c 100644 --- a/backend/app/schemas/github_backup.py +++ b/backend/app/schemas/github_backup.py @@ -2,10 +2,11 @@ import re from datetime import datetime -from enum import StrEnum from pydantic import BaseModel, Field, field_validator +from backend.app.core.compat import StrEnum + class ScheduleType(StrEnum): """Backup schedule types.""" diff --git a/backend/app/schemas/notification.py b/backend/app/schemas/notification.py index 4405251fe..ad125d0aa 100644 --- a/backend/app/schemas/notification.py +++ b/backend/app/schemas/notification.py @@ -1,11 +1,12 @@ """Pydantic schemas for notification providers.""" from datetime import datetime -from enum import StrEnum from typing import Any from pydantic import BaseModel, Field, field_validator +from backend.app.core.compat import StrEnum + class ProviderType(StrEnum): """Supported notification provider types.""" diff --git a/backend/app/schemas/notification_template.py b/backend/app/schemas/notification_template.py index 15193261d..93910b9c7 100644 --- a/backend/app/schemas/notification_template.py +++ b/backend/app/schemas/notification_template.py @@ -1,10 +1,11 @@ """Pydantic schemas for notification templates.""" from datetime import datetime -from enum import StrEnum from pydantic import BaseModel, Field +from backend.app.core.compat import StrEnum + class EventType(StrEnum): """Supported notification event types.""" diff --git a/backend/app/services/firmware_update.py b/backend/app/services/firmware_update.py index 27fa94fb4..8aa459ec2 100644 --- a/backend/app/services/firmware_update.py +++ b/backend/app/services/firmware_update.py @@ -11,11 +11,11 @@ Orchestrates firmware updates for Bambu Lab printers: import asyncio import logging from dataclasses import dataclass -from enum import StrEnum from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession +from backend.app.core.compat import StrEnum from backend.app.core.websocket import ws_manager from backend.app.models.printer import Printer from backend.app.services.bambu_ftp import ( diff --git a/install/install.sh b/install/install.sh index 4560bcb90..3203fa273 100755 --- a/install/install.sh +++ b/install/install.sh @@ -242,7 +242,7 @@ detect_python() { minor=$(echo "$version" | cut -d'.' -f2) if [[ "$major" -lt 3 ]] || { [[ "$major" -eq 3 ]] && [[ "$minor" -lt 10 ]]; }; then - log_warn "Python $version found, but 3.10+ is required" + log_warn "Python $version found, but 3.10 or newer is required" return 1 fi diff --git a/pyproject.toml b/pyproject.toml index 38133daa3..768cda9c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,10 +2,10 @@ name = "bambuddy" version = "0.1.5" description = "Archive and manage Bambu Lab 3MF files" -requires-python = ">=3.11" +requires-python = ">=3.10" [tool.ruff] -target-version = "py311" +target-version = "py310" line-length = 120 exclude = [ ".git", @@ -54,6 +54,8 @@ unfixable = [] "backend/app/main.py" = ["E402"] # MQTT client has some unused variables for debugging "backend/app/services/bambu_mqtt.py" = ["F841"] +# compat module intentionally uses version checks for Python 3.10 support +"backend/app/core/compat.py" = ["UP036"] [tool.ruff.lint.isort] known-first-party = ["backend"]