Esempio n. 1
0
 def __init__(self):
     self.event = ["timer", "tick", "bar"]
     self.timer_signal = NamedSignal("timer")
     # tick
     self.tick_signal = NamedSignal("tick")
     # bar
     self.bar_signal = NamedSignal("bar")
Esempio n. 2
0
class MessageActionEvent(Enum):
    created = NamedSignal('message created')
    read = NamedSignal('message read')
    responded = NamedSignal('message responded')

    def send(self, message, **data):
        self.value.send(message, **data)

    def connect(self, func):
        self.value.connect(func)
        return func
Esempio n. 3
0
    def __init__(self):
        self.filename = None

        self.parentWindow = None
        self.editor = None

        self.createFileChooser()

        self.onNew = NamedSignal('onNew')
        self.onRead = NamedSignal('onRead')
        self.onWrite = NamedSignal('onWrite')

        self.recentFiles = RecentFiles(self)
Esempio n. 4
0
class MessageActionEvent(Enum):
    """The types of an events which can be taken on an action.
    """
    created = NamedSignal('message created')
    read = NamedSignal('message read')
    responded = NamedSignal('message responded')

    def send(self, message, **data):
        self.value.send(message, **data)

    def connect(self, func):
        self.value.connect(func)
        return func
Esempio n. 5
0
    def __init__(self, debugger):
        self.variablesToTrack = []

        self.counter = 0
        self.records = deque()
        self.recordsCropped = False

        debugger.onStart.connect(self._start)
        debugger.onFrame.connect(self.recordFrame)

        self.onAddedVariable = NamedSignal('onAddedVariable')
        self.onRemovedVariable = NamedSignal('onRemovedVariable')
        self.onRecorded = NamedSignal('onRecorded')
        self.onReset = NamedSignal('onReset')
Esempio n. 6
0
 def __init__(self, app_name, ids=uuid4()):
     """ 账户级别的相关信号 """
     self.app_name = app_name
     self.id = ids
     self.event = ['order', "trade", "contract", "warning", "position", "init", "account", "last", "log", "error"]
     self.order_signal = NamedSignal(f"{ids}+order")
     self.trade_signal = NamedSignal(f"{ids}+trade")
     self.position_signal = NamedSignal(f"{ids}+position")
     self.init_signal = NamedSignal(f"{ids}+init")
     self.account_signal = NamedSignal(f"{ids}+account")
     self.last_signal = NamedSignal(f"{ids}+last")
     self.log_signal = NamedSignal(f"{ids}+log")
     self.contract_signal = NamedSignal(f"{ids}+contract")
     self.error_signal = NamedSignal(f"{ids}+error")
     self.warning_signal = NamedSignal(f"{ids}+warning")
Esempio n. 7
0
class Watcher(object):
    MAX_RECORDS = 200

    def __init__(self, debugger):
        self.variablesToTrack = []

        self.counter = 0
        self.records = deque()
        self.recordsCropped = False

        debugger.onStart.connect(self._start)
        debugger.onFrame.connect(self.recordFrame)

        self.onAddedVariable = NamedSignal('onAddedVariable')
        self.onRemovedVariable = NamedSignal('onRemovedVariable')
        self.onRecorded = NamedSignal('onRecorded')
        self.onReset = NamedSignal('onReset')

    def reset(self):
        self.counter = 0
        self.records = deque()
        self.recordsCropped = False
        self.onReset.send(self)

    def addVariable(self, name):
        self.variablesToTrack.append(name)
        self.onAddedVariable.send(self, var=name)

    def removeVariable(self, name):
        self.variablesToTrack.remove(name)
        self.onRemovedVariable.send(self, var=name)

    def _start(self, debugger, **_):
        self.reset()

    def recordFrame(self, debugger, filename, lineno, frame, **_):
        self.counter += 1
        record = Record(self.counter, filename, lineno)

        for var in self.variablesToTrack:
            try:
                value = eval(var, frame.f_locals, frame.f_globals)
                record.variables[var] = value
            except:
                pass

        cropCount = 0
        if len(self.records) >= self.MAX_RECORDS:
            # Drop a bunch of records.
            while len(self.records) >= self.MAX_RECORDS:
                self.records.popleft()
                cropCount += 1

            self.recordsCropped = True

        self.records.append(record)
        self.onRecorded.send(self, record=record, cropped=cropCount)
Esempio n. 8
0
class Watcher(object):
    MAX_RECORDS = 200

    def __init__(self, debugger):
        self.variablesToTrack = []

        self.counter = 0
        self.records = deque()
        self.recordsCropped = False

        debugger.onStart.connect(self._start)
        debugger.onFrame.connect(self.recordFrame)

        self.onAddedVariable = NamedSignal('onAddedVariable')
        self.onRemovedVariable = NamedSignal('onRemovedVariable')
        self.onRecorded = NamedSignal('onRecorded')
        self.onReset = NamedSignal('onReset')

    def reset(self):
        self.counter = 0
        self.records = deque()
        self.recordsCropped = False
        self.onReset.send(self)

    def addVariable(self, name):
        self.variablesToTrack.append(name)
        self.onAddedVariable.send(self, var=name)

    def removeVariable(self, name):
        self.variablesToTrack.remove(name)
        self.onRemovedVariable.send(self, var=name)

    def _start(self, debugger, **_):
        self.reset()

    def recordFrame(self, debugger, filename, lineno, frame, **_):
        self.counter += 1
        record = Record(self.counter, filename, lineno)

        for var in self.variablesToTrack:
            try:
                value = eval(var, frame.f_locals, frame.f_globals)
                record.variables[var] = value
            except:
                pass

        cropCount = 0
        if len(self.records) >= self.MAX_RECORDS:
            # Drop a bunch of records.
            while len(self.records) >= self.MAX_RECORDS:
                self.records.popleft()
                cropCount += 1

            self.recordsCropped = True

        self.records.append(record)
        self.onRecorded.send(self, record=record, cropped=cropCount)
Esempio n. 9
0
    def __init__(self):
        self.lock = Lock()
        self.isRunning = False
        self.runningThread = None
        #self._threadLaunched = Semaphore(0)

        self.debugger = Debugger(self)
        self.debugMode = False

        self.namespace = {}
        self.initialNamespace = {}
        self.initialNames = set()

        self.beforeRun = NamedSignal('afterLock')
        self.onException = NamedSignal('onException')
        self.afterRun = NamedSignal('beforeUnlock')

        self.onDebugSet = NamedSignal('onDebugSet')
Esempio n. 10
0
    def __init__(self, debugger):
        self.variablesToTrack = []

        self.counter = 0
        self.records = deque()
        self.recordsCropped = False

        debugger.onStart.connect(self._start)
        debugger.onFrame.connect(self.recordFrame)

        self.onAddedVariable = NamedSignal('onAddedVariable')
        self.onRemovedVariable = NamedSignal('onRemovedVariable')
        self.onRecorded = NamedSignal('onRecorded')
        self.onReset = NamedSignal('onReset')
Esempio n. 11
0
    def __init__(self, interpreter):
        """
        Connects the debugger to the interpreter.
        """
        super(Debugger, self).__init__()
        self.interpreter = interpreter
        self.speed = self.DEFAULT_SPEED
        self.targetFilenames = set()
        self.running = False

        self.onSpeedSet = NamedSignal('onSpeedSet')

        self.onStart = NamedSignal('onStart')
        self.onStop = NamedSignal('onStop')
        self.onFrame = NamedSignal('onFrame')
Esempio n. 12
0
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)
Esempio n. 13
0
    def __init__(self):
        self.lock = Lock()
        self.isRunning = False
        self.runningThread = None
        self._threadLaunched = Semaphore(0)

        self.debugger = Debugger(self)
        self.debugMode = False

        self.namespace = {}
        self.initialNamespace = {}
        self.initialNames = set()

        self.beforeRun = NamedSignal('afterLock')
        self.onException = NamedSignal('onException')
        self.afterRun = NamedSignal('beforeUnlock')

        self.onDebugSet = NamedSignal('onDebugSet')
Esempio n. 14
0
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)
Esempio n. 15
0
class CommandDocument(DefaultStyledDocument):
    """
    This is the document subclass used for the JES command window.
    Its only responsibilities compared to a normal document are protecting
    everything written by the program up to the last prompt, and keeping
    the History up to date with what the current prompt text is.
    """
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)

    def setTheme(self, themeName):
        """
        Updates all the existing styles, and recolors the command window
        to match the new styles if any text is present.
        """
        # Pick our fonts!
        self.defaultFontFamily = \
            UIManager.getDefaults().getFont("EditorPane.font").getFamily()
        self.monoFontFamily = 'Monospaced'

        # Check that the theme exists
        if themeName not in THEMES:
            themeName = DEFAULT_THEME_NAME

        self.themeName = themeName
        self.theme = theme = THEMES[themeName]

        # Set the default style
        baseStyle = self.getStyle('default')
        StyleConstants.setBackground(baseStyle, theme.backgroundColor)
        self._setStyle(baseStyle, theme.defaultStyle)

        # Set the pretty text styles
        existingStyles = set(self.getStyleNames())
        for name in ALL_STYLES:
            if name in existingStyles:
                style = self.getStyle(name)
            else:
                style = self.addStyle(name, baseStyle)

            styleSpec = theme.styles.get(name, (None, None))
            styleSpec = ((theme.defaultStyle[0]
                          if styleSpec[0] is None else styleSpec[0]),
                         (theme.defaultStyle[1]
                          if styleSpec[1] is None else styleSpec[1]))
            self._setStyle(style, styleSpec)

        self._recolorDocument()
        self.onThemeSet.send(self)

    def _recolorDocument(self):
        # Reapply character styles to the text in the transcript
        offset = 0
        for styleName, text in self.transcript:
            length = len(text)
            self.setCharacterAttributes(offset, length,
                                        self.getStyle(styleName), False)
            offset += length

        # Reapply character styles to the user input
        if self.responseStyle:
            self.setCharacterAttributes(offset,
                                        self.getLength() - offset,
                                        self.getStyle(self.responseStyle),
                                        False)

    def _setStyle(self, attrSet, styleSpec):
        flags, color = styleSpec

        StyleConstants.setForeground(attrSet, color)

        if flags & MONOSPACE:
            StyleConstants.setFontFamily(attrSet, self.monoFontFamily)
        else:
            StyleConstants.setFontFamily(attrSet, self.defaultFontFamily)

    def getBackgroundColor(self):
        """
        Returns the background color that this document's editor window
        should have.
        """
        return self.theme.backgroundColor

    def getDefaultTextColor(self):
        """
        Returns the default text color. (The theme really should specify one!)
        """
        return self.theme.defaultStyle[1]

    def setFontSize(self, size):
        """
        Updates the document to have the provided font size.
        """
        # First, we need to resize all the existing text.
        attr = SimpleAttributeSet()
        StyleConstants.setFontSize(attr, size)
        self.setCharacterAttributes(0, self.getLength(), attr, False)

        # Next, ensure that new text is given the proper size.
        for name in self.getStyleNames():
            StyleConstants.setFontSize(self.getStyle(name), size)

    def append(self, text, style):
        """
        Writes text at the end of the document, in a specific style.
        """
        self.transcript.append(TranscriptLine(style, text))
        self.insertString(self.getLength(), text, self.getStyle(style))

    def openPrompt(self, promptText, promptStyle, responseStyle):
        """
        Indicates a prompt to draw on the screen, and starts displaying
        user input in response. This requires the history to have already
        been activated.
        """
        if self.promptText is not None:
            raise Exception("A prompt is currently being displayed!")

        self.promptText = promptText
        self.promptStyle = promptStyle
        self.responseStyle = responseStyle

        self.resumePrompt()

    def closePrompt(self):
        """
        Suspends the prompt, then resets it so a different prompt can be
        displayed. After this, you should either commit or close the history.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.suspendPrompt()
        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

    def resumePrompt(self):
        """
        Draws the prompt and starts allowing user input again,
        also locking the program from writing before the prompt.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.ensureNewline(self.promptStyle)
        self.append(self.promptText, self.promptStyle)

        self.inputLimit = self.getLength()
        self.filter.enable(self.inputLimit, self.getStyle(self.responseStyle))
        self.listener.enable(self.inputLimit)

        self.setResponseText(self.history.getCurrentInput())

    def suspendPrompt(self):
        """
        Stops allowing user input and moves the caret to the next line,
        so content can be printed to the command window by the program
        without restriction.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        inputLength = self.getLength() - self.inputLimit
        text = self.getText(self.inputLimit, inputLength)
        self.transcript.append(TranscriptLine(self.responseStyle, text))

        self.filter.disable()
        self.listener.disable()
        self.inputLimit = None
        self.ensureNewline(self.responseStyle)

    def setResponseText(self, text):
        """
        Replaces the current response text with some new text.
        """
        if self.inputLimit is None:
            raise Exception("A prompt is not being displayed!")

        offset = self.inputLimit
        self.replace(offset,
                     self.getLength() - offset, text,
                     self.getStyle(self.responseStyle))

    def ensureNewline(self, style):
        """
        Ensures that there's a newline at the end of the buffer,
        so that anything appended will appear at the start of the line.
        """
        length = self.getLength()
        if length != 0 and self.getText(length - 1, 1) != '\n':
            self.append('\n', style)

    def clear(self):
        """
        Erase everything in the document.
        """
        self.transcripts.append([])
        self.transcript = self.transcripts[-1]
        self.remove(0, self.getLength())
Esempio n. 16
0
class Interpreter(object):
    """
    This contains a Python interpreter state. It starts out empty,
    but ready to run code.
    """
    def __init__(self):
        self.lock = Lock()
        self.isRunning = False
        self.runningThread = None
        self._threadLaunched = Semaphore(0)

        self.debugger = Debugger(self)
        self.debugMode = False

        self.namespace = {}
        self.initialNamespace = {}
        self.initialNames = set()

        self.beforeRun = NamedSignal('afterLock')
        self.onException = NamedSignal('onException')
        self.afterRun = NamedSignal('beforeUnlock')

        self.onDebugSet = NamedSignal('onDebugSet')

    def toggleDebugMode(self):
        """
        Flips the debug mode setting.
        """
        self.setDebugMode(not self.debugMode)

    def setDebugMode(self, mode):
        """
        Sets the debug mode to true or false.
        """
        mode = bool(mode)
        self.debugMode = mode
        self.onDebugSet.send(self, debugMode=mode)

    def initialize(self, initCode):
        """
        Create an "initial context" for the interpreter, by running code.
        The `initCode` function provided is passed the interpreter as an
        argument, and it can either manipulate its namespace dictionary
        directly, or run files or code fragments.
        """
        # Reset the context to blanks.
        self.namespace = {}
        self.initialNamespace = None
        self.initialNames = None

        # Call the function.
        initCode(self)

        # Capture the variables from the function.
        # (Lock to ensure that all the threads launched by initCode
        # have finished.)
        with self.lock:
            self.initialNamespace = self.namespace.copy()
            self.initialNames = set(self.initialNamespace.keys())

    def quickReset(self):
        """
        Restores the context that was present after the last call to
        initialize. (Changes to mutable objects will be included!)
        """
        self.namespace = self.initialNamespace.copy()

    def runFile(self, filename, setDunderFile=True):
        """
        Executes a file in the interpreter context (in a separate thread).

        (setDunderFile controls whether the __file__ variable is available.)
        """
        extraVars = {'__file__': filename} if setDunderFile else {}
        thread = ExecFileThread(self, filename, extraVars)
        return self._launchThread(thread)

    def runCodeFragment(self, fragment):
        """
        Executes some code in the interpreter context (in a separate thread).
        """
        if self.debugMode:
            return self.debugCodeFragment(fragment)
        else:
            return self.runCodeFragmentDirect(fragment)

    def runCodeFragmentDirect(self, fragment):
        """
        Executes some code in the interpreter context, without activating
        the debugger if it's enabled.
        """
        thread = ExecThread(self, fragment, {})
        return self._launchThread(thread)

    def debugCodeFragment(self, fragment):
        """
        Executes some code in the debugger, even if debug mode is disabled.
        """
        thread = DebugThread(self, fragment, {})
        return self._launchThread(thread)

    def _launchThread(self, thread):
        """
        Fires off a thread, and waits for it to acquire the interpreter
        lock before returning. This is used to serialize execution.
        """
        thread.start()
        self._threadLaunched.acquire()
        return thread

    def stopThread(self):
        """
        Kills whatever thread happens to be running now.
        """
        if self.runningThread is None:
            raise RuntimeError("Can't stop while thread isn't running")
        self.runningThread.tryStop()
Esempio n. 17
0
class CommandDocument(DefaultStyledDocument):
    """
    This is the document subclass used for the JES command window.
    Its only responsibilities compared to a normal document are protecting
    everything written by the program up to the last prompt, and keeping
    the History up to date with what the current prompt text is.
    """
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)

    def setTheme(self, themeName):
        """
        Updates all the existing styles, and recolors the command window
        to match the new styles if any text is present.
        """
        # Pick our fonts!
        self.defaultFontFamily = \
            UIManager.getDefaults().getFont("EditorPane.font").getFamily()
        self.monoFontFamily = 'Monospaced'

        # Check that the theme exists
        if themeName not in THEMES:
            themeName = DEFAULT_THEME_NAME

        self.themeName = themeName
        self.theme = theme = THEMES[themeName]

        # Set the default style
        baseStyle = self.getStyle('default')
        StyleConstants.setBackground(baseStyle, theme.backgroundColor)
        self._setStyle(baseStyle, theme.defaultStyle)

        # Set the pretty text styles
        existingStyles = set(self.getStyleNames())
        for name in ALL_STYLES:
            if name in existingStyles:
                style = self.getStyle(name)
            else:
                style = self.addStyle(name, baseStyle)

            styleSpec = theme.styles.get(name, (None, None))
            styleSpec = (
                (theme.defaultStyle[0] if styleSpec[0] is None else styleSpec[0]),
                (theme.defaultStyle[1] if styleSpec[1] is None else styleSpec[1])
            )
            self._setStyle(style, styleSpec)

        self._recolorDocument()
        self.onThemeSet.send(self)

    def _recolorDocument(self):
        # Reapply character styles to the text in the transcript
        offset = 0
        for styleName, text in self.transcript:
            length = len(text)
            self.setCharacterAttributes(offset, length,
                                        self.getStyle(styleName), False)
            offset += length

        # Reapply character styles to the user input
        if self.responseStyle:
            self.setCharacterAttributes(offset, self.getLength() - offset,
                                        self.getStyle(self.responseStyle),
                                        False)

    def _setStyle(self, attrSet, styleSpec):
        flags, color = styleSpec

        StyleConstants.setForeground(attrSet, color)

        if flags & MONOSPACE:
            StyleConstants.setFontFamily(attrSet, self.monoFontFamily)
        else:
            StyleConstants.setFontFamily(attrSet, self.defaultFontFamily)

    def getBackgroundColor(self):
        """
        Returns the background color that this document's editor window
        should have.
        """
        return self.theme.backgroundColor

    def getDefaultTextColor(self):
        """
        Returns the default text color. (The theme really should specify one!)
        """
        return self.theme.defaultStyle[1]

    def setFontSize(self, size):
        """
        Updates the document to have the provided font size.
        """
        # First, we need to resize all the existing text.
        attr = SimpleAttributeSet()
        StyleConstants.setFontSize(attr, size)
        self.setCharacterAttributes(0, self.getLength(), attr, False)

        # Next, ensure that new text is given the proper size.
        for name in self.getStyleNames():
            StyleConstants.setFontSize(self.getStyle(name), size)

    def append(self, text, style):
        """
        Writes text at the end of the document, in a specific style.
        """
        self.transcript.append(TranscriptLine(style, text))
        self.insertString(self.getLength(), text, self.getStyle(style))

    def openPrompt(self, promptText, promptStyle, responseStyle):
        """
        Indicates a prompt to draw on the screen, and starts displaying
        user input in response. This requires the history to have already
        been activated.
        """
        if self.promptText is not None:
            raise Exception("A prompt is currently being displayed!")

        self.promptText = promptText
        self.promptStyle = promptStyle
        self.responseStyle = responseStyle

        self.resumePrompt()

    def closePrompt(self):
        """
        Suspends the prompt, then resets it so a different prompt can be
        displayed. After this, you should either commit or close the history.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.suspendPrompt()
        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

    def resumePrompt(self):
        """
        Draws the prompt and starts allowing user input again,
        also locking the program from writing before the prompt.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.ensureNewline(self.promptStyle)
        self.append(self.promptText, self.promptStyle)

        self.inputLimit = self.getLength()
        self.filter.enable(self.inputLimit, self.getStyle(self.responseStyle))
        self.listener.enable(self.inputLimit)

        self.setResponseText(self.history.getCurrentInput())

    def suspendPrompt(self):
        """
        Stops allowing user input and moves the caret to the next line,
        so content can be printed to the command window by the program
        without restriction.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        inputLength = self.getLength() - self.inputLimit
        text = self.getText(self.inputLimit, inputLength)
        self.transcript.append(TranscriptLine(self.responseStyle, text))

        self.filter.disable()
        self.listener.disable()
        self.inputLimit = None
        self.ensureNewline(self.responseStyle)

    def setResponseText(self, text):
        """
        Replaces the current response text with some new text.
        """
        if self.inputLimit is None:
            raise Exception("A prompt is not being displayed!")

        offset = self.inputLimit
        self.replace(offset, self.getLength() - offset, text, self.getStyle(self.responseStyle))

    def ensureNewline(self, style):
        """
        Ensures that there's a newline at the end of the buffer,
        so that anything appended will appear at the start of the line.
        """
        length = self.getLength()
        if length != 0 and self.getText(length - 1, 1) != '\n':
            self.append('\n', style)

    def clear(self):
        """
        Erase everything in the document.
        """
        self.transcripts.append([])
        self.transcript = self.transcripts[-1]
        self.remove(0, self.getLength())
Esempio n. 18
0
 def register(self, name, doc=None, subscriber=None):
     self.update({name: NamedSignal(name, doc)})
     if subscriber:
         self[name].connect(subscriber)
Esempio n. 19
0
class Debugger(Pdb, object):
    #: When the debugger's speed is set to this, execution proceeds
    #: at 1 statement per second. Double this is 2 statements per second,
    #: half this is a statement every 2 seconds.
    UNIT_SPEED = 20.0

    #: The lowest speed you (should) be able to set the debugger to.
    #: You can technically set it to any nonnegative integral speed,
    #: but sticking above this is preferred.
    #: (A speed setting of 2 is a statement every 10 seconds.)
    MIN_SPEED = 2

    #: When the debugger's speed is set to this, the speed is ignored.
    #: Statements are simply run as fast as possible.
    MAX_SPEED = int(3 * UNIT_SPEED)

    #: The default speed setting for the debugger.
    #: (Twice unit speed is 2 statements per second.)
    DEFAULT_SPEED = int(2 * UNIT_SPEED)

    def __init__(self, interpreter):
        """
        Connects the debugger to the interpreter.
        """
        super(Debugger, self).__init__()
        self.interpreter = interpreter
        self.speed = self.DEFAULT_SPEED
        self.targetFilenames = set()
        self.running = False

        self.onSpeedSet = NamedSignal('onSpeedSet')

        self.onStart = NamedSignal('onStart')
        self.onStop = NamedSignal('onStop')
        self.onFrame = NamedSignal('onFrame')

    def starting(self):
        """
        Fires the debugger's start signal.
        """
        self.running = True
        self.onStart.send(self)

    def stopping(self):
        """
        Fires the debugger's stop signal.
        """
        self.running = False
        self.onStop.send(self)

    def setSpeed(self, speed):
        """
        Sets a new speed for the debugger. This fires onSpeedSet.
        """
        speed = int(speed)
        if speed > self.MAX_SPEED:
            speed = self.MAX_SPEED
        elif speed <= 0:
            raise ValueError("Speed must be a positive integer")

        self.speed = speed
        self.onSpeedSet.send(self, newSpeed=speed)

    def setTargetFilenames(self, filenames):
        """
        Sets the set of filenames which will make the debugger stop.
        """
        self.targetFilenames = set(filenames)


    ###
    ### PDB INTERCEPTION METHODS
    ###

    # Overrides Pdb.interaction
    # This is used whever the debugger would step
    def interaction(self, frame, traceback):
        currentFilename = frame.f_code.co_filename

        if currentFilename in self.targetFilenames:
            lineno = frame.f_lineno

            self.onFrame.send(self,
                filename=currentFilename, lineno=lineno,
                frame=frame, traceback=traceback
            )

            if self.interpreter.runningThread.stopSignal:
                raise ThreadDeath

            if self.speed < self.MAX_SPEED:
                period = self.UNIT_SPEED / self.speed
                time.sleep(period)

            if self.interpreter.runningThread.stopSignal:
                raise ThreadDeath

    # Overrides pdb.user_line
    def user_line(self, frame):
        """This function is called when we stop or break at this line."""
        self.interaction(frame, None)

    # Overrides pdb.user_return
    def user_return(self, frame, return_value):
        pass

    # Overrides pdb.user_return
    def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
        pass
Esempio n. 20
0
 def proc_sig(sig:NamedSignal):
     result = sig.send(sender, **kwargs)
     results.extend([{'name':fn.__name__, 'result':r} for fn, r in result])
Esempio n. 21
0
class Interpreter(object):
    """
    This contains a Python interpreter state. It starts out empty,
    but ready to run code.
    """
    def __init__(self):
        self.lock = Lock()
        self.isRunning = False
        self.runningThread = None
        #self._threadLaunched = Semaphore(0)

        self.debugger = Debugger(self)
        self.debugMode = False

        self.namespace = {}
        self.initialNamespace = {}
        self.initialNames = set()

        self.beforeRun = NamedSignal('afterLock')
        self.onException = NamedSignal('onException')
        self.afterRun = NamedSignal('beforeUnlock')

        self.onDebugSet = NamedSignal('onDebugSet')

    def toggleDebugMode(self):
        """
        Flips the debug mode setting.
        """
        self.setDebugMode(not self.debugMode)

    def setDebugMode(self, mode):
        """
        Sets the debug mode to true or false.
        """
        mode = bool(mode)
        self.debugMode = mode
        self.onDebugSet.send(self, debugMode=mode)

    def initialize(self, initCode):
        """
        Create an "initial context" for the interpreter, by running code.
        The `initCode` function provided is passed the interpreter as an
        argument, and it can either manipulate its namespace dictionary
        directly, or run files or code fragments.
        """
        # Reset the context to blanks.
        self.namespace = {}
        self.initialNamespace = None
        self.initialNames = None

        # Call the function.
        initCode(self)

        # Capture the variables from the function.
        # (Lock to ensure that all the threads launched by initCode
        # have finished.)
        with self.lock:
            self.initialNamespace = self.namespace.copy()
            self.initialNames = set(self.initialNamespace.keys())

    def quickReset(self):
        """
        Restores the context that was present after the last call to
        initialize. (Changes to mutable objects will be included!)
        """
        self.namespace = self.initialNamespace.copy()

    def runFile(self, filename, setDunderFile=True):
        """
        Executes a file in the interpreter context (in a separate thread).

        (setDunderFile controls whether the __file__ variable is available.)
        """
        extraVars = {'__file__': filename} if setDunderFile else {}
        thread = ExecFileThread(self, filename, extraVars)
        return self._launchThread(thread)

    def runCodeFragment(self, fragment):
        """
        Executes some code in the interpreter context (in a separate thread).
        """
        if self.debugMode:
            return self.debugCodeFragment(fragment)
        else:
            return self.runCodeFragmentDirect(fragment)

    def runCodeFragmentDirect(self, fragment):
        """
        Executes some code in the interpreter context, without activating
        the debugger if it's enabled.
        """
        thread = ExecThread(self, fragment, {})
        return self._launchThread(thread)

    def debugCodeFragment(self, fragment):
        """
        Executes some code in the debugger, even if debug mode is disabled.
        """
        thread = DebugThread(self, fragment, {})
        return self._launchThread(thread)

    def _launchThread(self, thread):
        """
        Fires off a thread, and waits for it to acquire the interpreter
        lock before returning. This is used to serialize execution.
        """
        thread.start()
        #self._threadLaunched.acquire()
        return thread

    def stopThread(self):
        """
        Kills whatever thread happens to be running now.
        """
        if self.runningThread is None:
            raise RuntimeError("Can't stop while thread isn't running")
        self.runningThread.tryStop()