Skip to content

11 decorators

Zuko edited this page Jan 21, 2026 · 1 revision

Decorators

@singleton, @autoStrip, @catchExceptInMsgBox, SignalBlocker

@singleton

Singleton pattern decorator:

from core.Decorators import singleton

@singleton
class MyService:
    def __init__(self):
        self.data = []

# Always returns same instance
service1 = MyService()
service2 = MyService()
assert service1 is service2

@autoStrip

Auto-strip strings in dataclass:

from dataclasses import dataclass
from core.Decorators import autoStrip

@autoStrip
@dataclass
class UserData:
    name: str
    email: str

# Automatically strips whitespace
user = UserData(name='  John  ', email='  john@example.com  ')
print(user.name)  # 'John'
print(user.email)  # 'john@example.com'

@catchExceptInMsgBox

Catch exceptions and show message box:

from core.Decorators import catchExceptInMsgBox

@catchExceptInMsgBox
def riskyOperation():
    # If exception occurs, shows message box
    raise ValueError('Something went wrong')

# With custom error message
@catchExceptInMsgBox(errorMsg='Operation failed')
def anotherOperation():
    raise ValueError('Error')

# Re-raise after showing
@catchExceptInMsgBox(reRaise=True)
def criticalOperation():
    raise ValueError('Critical error')

SignalBlocker

Context manager for blocking Qt signals:

from core.Decorators import SignalBlocker

widget = self.widgetManager.get('slider')

# Block signals during update
with SignalBlocker(widget):
    widget.setValue(50)  # No valueChanged signal emitted

Usage Examples

Singleton Service

from core.Decorators import singleton

@singleton
class CacheService:
    def __init__(self):
        self.cache = {}
    
    def get(self, key):
        return self.cache.get(key)
    
    def set(self, key, value):
        self.cache[key] = value

# Use anywhere
cache = CacheService()
cache.set('key', 'value')

Form Data with autoStrip

from dataclasses import dataclass
from core.Decorators import autoStrip

@autoStrip
@dataclass
class FormData:
    username: str
    email: str
    phone: str

# User input with whitespace
form = FormData(
    username='  john_doe  ',
    email='  john@example.com  ',
    phone='  123-456-7890  '
)

# Automatically stripped
print(form.username)  # 'john_doe'

Exception Handling

from core.Decorators import catchExceptInMsgBox

class DataService:
    @catchExceptInMsgBox(errorMsg='Failed to save data')
    def saveData(self, data):
        # If error occurs, shows message box
        with open('data.json', 'w') as f:
            json.dump(data, f)

Signal Blocking

from core.Decorators import SignalBlocker

class MyHandler(BaseCtlHandler):
    def updateSliders(self, values):
        # Block signals for batch update
        for name, value in values.items():
            widget = self.widgetManager.get(name)
            with SignalBlocker(widget):
                widget.setValue(value)

Best Practices

✅ DO

# Use @singleton for services
@singleton
class DatabaseService:
    pass

# Use SignalBlocker for programmatic updates
with SignalBlocker(widget):
    widget.setValue(value)

# Use @autoStrip for user input
@autoStrip
@dataclass
class UserInput:
    name: str

❌ DON'T

# Don't use @singleton on non-services
@singleton
class UserData:  # Wrong! Not a service
    pass

# Don't forget SignalBlocker
widget.setValue(value)  # Triggers signal!

Related Documentation

Clone this wiki locally