southernpitbull/rules icon
public
Published on 7/11/2025
rules

Rules

I. Python Language Fundamentals

  1. Follow PEP 8 Strictly: Adhere to the official Python style guide for consistent and readable code.
  2. Use Type Hints: Annotate function signatures and variable types using the typing module to improve code clarity and enable static analysis.
  3. Prefer f-strings: Use f-strings for string formatting unless complex formatting or Python 2 compatibility (not required here) is needed.
  4. Use Context Managers: Utilize with statements for resource management (files, locks, network connections) to ensure proper cleanup.
  5. Write Idiomatic Python: Favor Python's built-in features and standard library over overly complex or non-Pythonic constructs.
  6. Use Virtual Environments: Always work within a dedicated virtual environment for dependency management.
  7. Organize with Modules and Packages: Structure the codebase logically into modules and packages based on functionality.
  8. Avoid __del__: Do not rely on object finalization (__del__) for resource cleanup; prefer explicit methods or context managers.
  9. Standard Library First: Before adding a third-party library, check if the required functionality is available in Python's standard library.
  10. Ensure Python 3.8+ Compatibility: Develop and test against the specified minimum Python version (or latest stable release).
  11. Use Properties: Define controlled access to class attributes using the @property decorator.
  12. Prefer Composition over Inheritance: Design classes by favoring composition to build complex behavior from simpler objects.
  13. Keep Functions Small: Aim for functions and methods that are concise and focused on a single task.
  14. Avoid Global State: Minimize the use of global variables; prefer passing data explicitly or using dependency injection.
  15. Handle Exceptions Explicitly: Use specific exception types in except blocks rather than catching generic Exception.

II. Qt6 & PyQt6 Core Usage

  1. Inherit from QObject: Any class requiring signals, slots, or the object-tree memory management system must inherit from QtCore.QObject.
  2. Define Signals with pyqtSignal: Declare signals using QtCore.pyqtSignal or PyQt6.QtCore.Signal with appropriate argument types.
  3. Use @pyqtSlot Decorator: While optional, decorate slot methods with @QtCore.pyqtSlot specifying argument types for clarity and runtime checking.
  4. Connect Signals and Slots Correctly: Use the new-style connection syntax (signal.connect(slot)) unless connecting signals to methods with overloaded signatures (which may require the old QtCore.QObject.connect syntax or specifying the signature).
  5. GUI Operations on Main Thread Only: All creation, manipulation, and deletion of GUI widgets must occur on the main application thread.
  6. Thread-Safe GUI Updates: Never directly update GUI elements from a background thread. Use signals/slots or QtCore.QMetaObject.invokeMethod queued connections for thread-safe communication back to the main thread.
  7. Understand the Event Loop: Have a solid grasp of the Qt event loop and how events are processed. Blocking the event loop will freeze the GUI.
  8. Prefer Standard Widgets: Utilize widgets from QtWidgets or other standard Qt modules unless complex or highly customized rendering is required.
  9. Use Layouts: Employ QtWidgets.QVBoxLayout, QHBoxLayout, QGridLayout, QFormLayout, etc., for positioning widgets, avoiding fixed sizes unless absolutely necessary.
  10. Set Object Names: Assign meaningful and unique names to widgets using setObjectName() for easy styling via QSS and debugging.
  11. Utilize QSettings: Manage persistent application settings and user preferences using QtCore.QSettings.
  12. Understand Object Tree: Leverage the parent-child relationship of QObject for automatic memory management; a child object is automatically deleted when its parent is deleted.
  13. Disconnect Signals: Disconnect signals and slots when they are no longer needed, especially before deleting objects, to prevent dangling references and crashes.
  14. Use QTimer: For periodic tasks or delayed function calls that need to run on the main thread, use QtCore.QTimer.
  15. Handle Events by Overriding: Implement custom behavior for specific events by overriding the relevant event methods (e.g., paintEvent, closeEvent, mousePressEvent).
  16. Use QDialog for Modality: Employ QtWidgets.QDialog subclasses for creating modal windows that block interaction with the main window.
  17. Adopt Model/View: Use Qt's Model/View architecture (QtWidgets.QListView, QTableView, QTreeView with QAbstractItemModel subclasses) for displaying complex data sets.
  18. Implement Custom Models Correctly: Ensure custom models inherit from appropriate QAbstractItemModel base classes and correctly implement required methods (data(), rowCount(), columnCount(), headerData(), index(), parent()).
  19. Use QDataStream for Binary: For efficient binary serialization and deserialization, use QtCore.QDataStream.
  20. Use QJsonDocument for JSON: Handle JSON data parsing and generation using QtCore.QJsonDocument.
  21. Use QPainter for Custom Drawing: When standard widgets aren't sufficient, use QtGui.QPainter within a widget's paintEvent to draw custom graphics.
  22. Avoid Excessive Widget Creation/Deletion: Reusing widgets and updating their content is generally more performant than constantly creating and destroying them.

III. GUI Design & Widgets

  1. Design Responsive Layouts: Ensure layouts adapt gracefully to window resizing and orientation changes.
  2. Configure QSizePolicy: Correctly set the sizePolicy property for widgets to control how they grow and shrink within layouts.
  3. Provide Visual Feedback: Implement visual cues (e.g., changing button state, showing spinners, progress bars) to indicate that an action is in progress.
  4. Validate User Input: Provide immediate feedback (e.g., changing border color, showing error icons/text) when user input is invalid.
  5. Implement Keyboard Shortcuts: Define keyboard shortcuts for frequently used actions, aligning with OS conventions.
  6. Ensure Logical Focus Order: Configure the tab order (setTabOrder) so users can navigate interactive elements logically using the keyboard.
  7. Provide Clear Tooltips: Write concise and informative tooltips for all interactive UI elements, especially icons.
  8. Use Standard System Dialogs: Employ QtWidgets.QFileDialog, QMessageBox, QFontDialog, etc., for common tasks like opening/saving files or showing messages.
  9. Support High DPI: Ensure the application scales correctly on high-resolution displays.
  10. Minimize Interaction Steps: Streamline user workflows to reduce the number of clicks or steps required to perform common tasks.
  11. Implement Undo/Redo: Provide an undo/redo mechanism for significant user actions where applicable.
  12. Prefer Composition: Build complex custom UI elements by composing multiple standard Qt widgets within a custom widget class.
  13. Design for Theming: Structure the UI and QSS to make it easy to apply different visual themes.

IV. Architecture (Python & Qt)

  1. Separate Core Logic from GUI: Strictly separate the application's business logic, data models, and agent code from the PyQt6 UI code. Business logic classes should not depend on PyQt6.
  2. Use Signals for Communication: Use signals and slots as the primary mechanism for communication between decoupled core logic components and the GUI.
  3. Centralize State: The application's core state and data models should reside in non-GUI classes, managed independently of the visual representation.
  4. Implement a Presentation Layer: Introduce a layer (e.g., Presenters, ViewModels) that translates data from core models into a format suitable for the UI and handles UI-initiated actions by interacting with core logic.
  5. Dependency Injection: Use dependency injection to manage dependencies between components, making them easier to mock and test.
  6. Design for Testability: Structure components so they can be easily instantiated, configured, and tested programmatically without needing a running GUI.
  7. Logical Project Structure: Organize the codebase directory structure reflecting the architectural layers (e.g., core/, ui/, models/, services/, agents/).

V. Concurrency & Threading

  1. No Blocking on Main Thread: Operations that take a significant amount of time (file I/O, network requests, complex calculations, model inference) must be performed in background threads.
  2. Use QThread Correctly: If using QtCore.QThread, use the "worker object" pattern: create a QObject subclass for the task and moveToThread() it to the QThread instance, rather than subclassing QThread itself.
  3. Use Python's threading: Python's native threading module can also be used for background tasks, but thread-safe communication back to the main thread is still critical (signals/slots are the safest way in Qt).
  4. Signals for Thread Communication: Always use signals (QtCore.Signal) to emit progress updates or results from background threads back to the main thread to be received by slots connected to GUI elements.
  5. Thread-Safe Data Access: Use appropriate synchronization primitives (e.g., threading.Lock, threading.RLock, threading.Semaphore) when multiple threads need to access or modify shared data structures.
  6. Avoid Thread Pools for GUI Updates: While thread pools (concurrent.futures.ThreadPoolExecutor) are useful for general tasks, direct GUI updates from within pool threads are prohibited. Use signals.
  7. Handle Thread Termination: Implement mechanisms for safely stopping background threads when the application exits or the task is canceled.
  8. Thread-Safe Qt Modules: Be aware that only specific Qt modules are thread-safe (e.g., QtCore.QMutex, QtCore.QSemaphore). Most GUI classes (QtWidgets) are not.

VI. Resource Management

  1. Set QObject Parents: Ensure that all QObject subclasses that are part of an object hierarchy have a parent set, so they are automatically cleaned up when the parent is deleted.
  2. Use deleteLater(): For QObject subclasses that do not have a parent or whose lifespan is not tied to a parent widget, use object.deleteLater() to schedule deletion in the event loop after pending events are processed. Avoid del object.
  3. Explicitly Close Non-Qt Resources: Always explicitly close files, database connections, network sockets, etc., using close() or with statements.
  4. Handle None Gracefully: Check for None or use techniques like the null object pattern to avoid AttributeError when dealing with potentially missing objects.
  5. Manage Database Connections: Use connection pooling or ensure database connections are opened and closed appropriately, ideally within context managers.

VII. Testing

  1. Test Business Logic Separately: Write comprehensive unit tests for core application logic that does not rely on the PyQt6 GUI.
  2. Use pytest-qt: Utilize the pytest-qt plugin for testing PyQt6 specific code, including widgets, signals, and dialogs.
  3. Write Integration Tests: Implement tests that verify the correct interaction and data flow between different decoupled components (e.g., a Presenter and a core Model).
  4. Implement GUI Tests: Write tests that simulate user interaction with the GUI (e.g., clicking buttons, typing text) using pytest-qt's tools or external GUI testing frameworks.
  5. Mock External Dependencies: Use mocking libraries (e.g., unittest.mock) to isolate code under test from external services (API calls, database, file system).
  6. Regression Tests: Create a specific test for every bug fix to ensure it doesn't reappear in the future.
  7. Maintain Code Coverage: Aim for and monitor a target code coverage percentage for tests.
  8. Easy Test Setup: Ensure the test environment is simple to set up and run for any developer.

VIII. Internationalization (i18n) & Localization (l10n)

  1. Wrap All User Strings: All user-visible strings within QObject subclasses must be wrapped using self.tr("Your text here").
  2. Use Translation Tools: Use the PyQt6/PySide6 translation tools (pylupdate6, lrelease) to manage translation files (.ts, .qm).
  3. Load Translators: Load the appropriate compiled translation (.qm) files using QtCore.QTranslator based on the application's configured language.
  4. Support Runtime Language Switching: While a restart is simplest, design the UI update logic to support changing the language preference at runtime and reloading translations.

IX. Styling

  1. Prefer Qt Style Sheets (QSS): Use QSS as the primary method for customizing the visual appearance of widgets.
  2. Organize QSS: Store QSS rules in separate files (.qss) rather than embedding them directly in Python code.
  3. Use Object Names and Classes: Leverage widget objectName and dynamic properties to create specific and maintainable QSS rules.
  4. Avoid Hardcoding Style: Do not hardcode style properties directly in Python code if they can be managed more flexibly via QSS.
  5. Design for Multiple Themes: Structure QSS files to support easy switching between different visual themes (e.g., dark/light mode).

X. Error Handling & Logging

  1. Catch Specific Exceptions: Avoid overly broad try...except blocks. Catch only the specific exceptions you expect and know how to handle.
  2. Log Errors: Use a robust logging framework (e.g., Python's logging module) to record errors, warnings, and important information with configurable levels.
  3. Handle API/Network Errors Gracefully: Implement clear error handling for external API calls or network requests, providing informative feedback to the user.
  4. Validate Data: Sanitize and validate all external data (user input, API responses, file content) to prevent unexpected errors or security issues.
  5. Report Critical Errors: For unrecoverable errors, provide a mechanism for the user to report the issue, ideally including relevant log snippets.
  6. Disconnect on Error: If a connected signal/slot interaction can fail critically, consider disconnecting temporarily or implementing robust error handling within the slot.

XI. Deployment & Packaging

  1. Use Packaging Tools: Utilize standard tools like PyInstaller or cx_Freeze to create standalone executables.
  2. Include Dependencies: Ensure the packaging process correctly bundles all necessary Python libraries, PyQt6 dependencies, Qt plugins (image formats, platforms), and resource files (translations, QSS, icons).
  3. Include Translation Files: Make sure compiled .qm translation files are correctly located relative to where the application expects them.
  4. Sign Executables: For distribution on platforms like macOS and Windows, sign the application bundle or executable for trusted installation.
  5. Provide Clear Instructions: Include documentation on how to install, uninstall, and potentially update the application.
  6. Manage Qt Plugins: Be aware of required Qt plugins (e.g., platforms/, imageformats/) and ensure they are correctly included in the bundled application.
  7. Cross-Platform Testing: Test the packaged application on all target operating systems to identify platform-specific issues.