Пример #1
0
    def send_keyword(self, end_word):
        """We send a keyword when the tag 'KEYWORD' is in the tags of end_word.
        end_word : the character of the last word

        This function is called when self.typed_char is True and:
        -a user types a non alphanum character (keypress_event). end_word is the character of the last word.
        -a user types a newline (newline_and_indent_event).
        end_word is the character of the previous instruction's last character.
        -the cursor has been moved (prev_move_cursor_event and move_cursor_event)
        end_word is the character of the previous cursor position.

        We don't simply check all keypresses because we want to prevent cases where the user types something
        like 'define' or 'assert'.
        In these cases, the user typed the keywords 'def' or 'as' but we don't want to trace these.

        self.typed_char is used to prevent sending the same keyword multiple times and
        to only trace the keywords the user effectively typed.
        """
        if end_word == "1.0":  # Bug with select all
            return
        tags = self.tag_names(end_word)
        if 'KEYWORD' in self.tag_names(end_word + "-1c"):
            index1, index2 = self.tag_prevrange('KEYWORD', end_word)
            keyword = self.get(index1, index2)
            line_number = self.get_current_line_number()
            extensions = {
                "https://www.lip6.fr/mocah/invalidURI/extensions/keyword-typed":
                keyword,
                "https://www.lip6.fr/mocah/invalidURI/extensions/filename":
                self.short_title()
            }
            self.add_context(extensions, line_number)
            tracing.send_statement("typed", "keyword", extensions)
Пример #2
0
 def send_update_changed_line(self, newline=False, force_sending=False):
     """Send a statement whenever a user modified an instruction.
     force_sending is used to force the sending (program execution, backspace over previous line)"""
     if self.old_line is None:
         return
     old_line = self.old_line
     new_line = self.create_line(old_line.line_number)
     cursor_line_number = self.get_current_line_number()
     cursor_changed_line = old_line.line_number != cursor_line_number
     # not_both_empty: Check if whether old_line, new_line or both are not empty spaces
     not_both_empty = (old_line.instruction != ""
                       and not old_line.instruction.isspace())
     not_both_empty = not_both_empty or (new_line.instruction != "" and
                                         not new_line.instruction.isspace())
     instruction_has_been_modified = old_line.instruction.strip(
     ) != new_line.instruction.strip()
     if cursor_changed_line or force_sending:
         if not_both_empty and instruction_has_been_modified:
             if new_line.line_number == 1:
                 tracing.check_modified_student_number(new_line.instruction)
             extensions = self.create_changed_line_extensions(
                 old_line, new_line)
             self.add_context(extensions, old_line.line_number)
             # print(extensions['https://www.lip6.fr/mocah/invalidURI/extensions/old-instruction'])
             # print(extensions['https://www.lip6.fr/mocah/invalidURI/extensions/new-instruction'])
             tracing.send_statement("modified", "instruction", extensions)
         if newline:  # If newline, we want old_line to be considered empty
             self.old_line = Line(cursor_line_number, "", "empty")
         else:
             self.old_line = self.create_line(cursor_line_number)
Пример #3
0
 def save_as(self, event):
     tracing.user_is_interacting()
     if self.filename:
         old_filename = self.filename
     else:
         old_filename = "Sans nom"
     filename = self.asksavefile()
     if filename:
         if self.writefile(filename):
             #self.opened=TRUE
             self.set_filename(filename)
             self.set_saved(1)
             try:
                 self.editwin.store_file_breaks()
             except AttributeError:
                 pass
             tracing.send_statement(
                 "saved-as", "file", {
                     "https://www.lip6.fr/mocah/invalidURI/extensions/old-filename":
                     os.path.basename(old_filename),
                     "https://www.lip6.fr/mocah/invalidURI/extensions/new-filename":
                     os.path.basename(filename)
                 })
     self.editwin.focus_set()
     self.updaterecentfileslist(filename)
     return "break"
Пример #4
0
 def new_file(self, event=None):
     """ Creates a new empty editor and put it into the pyEditorList """
     tracing.user_is_interacting()
     file_editor = PyEditorFrame(self.editor_list)
     self.editor_list.add(file_editor,
                          self.main_view.editor_widget,
                          text=file_editor.get_file_name())
     tracing.send_statement("created", "file")
Пример #5
0
 def copy_event(self, event):
     # Trace copy event in the output console
     first = self.index("sel.first")
     last = self.index("sel.last")
     if first != "" and last != "":
         tracing.send_statement(
             "copied", "output-console", {
                 "https://www.lip6.fr/mocah/invalidURI/extensions/text":
                 self.get(first, last)
             })
Пример #6
0
 def paste_event(self, event):
     """User pasted something"""
     pasted_text = self.clipboard_get()
     insert_index = self.index("insert")
     if pasted_text != "":
         extensions = {
             "https://www.lip6.fr/mocah/invalidURI/extensions/text":
             pasted_text,
             "https://www.lip6.fr/mocah/invalidURI/extensions/index":
             insert_index
         }
         self.add_context(extensions, int(insert_index.split('.')[0]))
         tracing.send_statement("inserted", "text", extensions)
Пример #7
0
 def send_deletion(self, first, last):
     if self.is_multi_line_deletion(first, last):
         self.reset_line()
         extensions = {
             "https://www.lip6.fr/mocah/invalidURI/extensions/text":
             self.get(first, last),
             "https://www.lip6.fr/mocah/invalidURI/extensions/first-index":
             first,
             "https://www.lip6.fr/mocah/invalidURI/extensions/last-index":
             last
         }
         self.add_context(extensions, int(first.split('.')[0]))
         tracing.send_statement("deleted", "text", extensions)
Пример #8
0
 def copied_event(self, event):
     """User copied something"""
     first, last = self.get_selection_indices()
     if first and last:
         extensions = {
             "https://www.lip6.fr/mocah/invalidURI/extensions/text":
             self.get(first, last),
             "https://www.lip6.fr/mocah/invalidURI/extensions/first-index":
             first,
             "https://www.lip6.fr/mocah/invalidURI/extensions/last-index":
             last
         }
         self.add_context(extensions, int(first.split('.')[0]))
         tracing.send_statement("copied", "text", extensions)
Пример #9
0
    def evaluate_action(self, *args):
        """ Evaluate the expression in the input console """
        expr = self.input_console.get()
        if not expr:
            return
        tracing.send_statement("started", "evaluation", {
            "https://www.lip6.fr/mocah/invalidURI/extensions/mode":
            tr(self.mode)
        })
        tracing.user_is_interacting()
        local_interpreter = False
        if self.interpreter is None:
            self.interpreter = InterpreterProxy(self.app.root, self.app.mode,
                                                "<<console>>")
            local_interpreter = True
            self.app.running_interpreter_proxy = self.interpreter

        callback_called = False

        # the call back
        def callback(ok, report):
            nonlocal callback_called
            if callback_called:
                return
            else:
                callback_called = True

            if ok:
                self.input_history.record(expr)

            self.input_console.delete(0, END)
            self.write_report(ok, report, 'eval')

            if local_interpreter:
                self.interpreter.kill()
                self.interpreter = None
                self.app.running_interpreter_proxy = None

            self.app.icon_widget.disable_icon_running()
            self.app.running_interpreter_callback = None
            tracing.send_statement_evaluate(report,
                                            tr(self.mode),
                                            instruction=expr)

        # non-blocking call
        self.app.icon_widget.enable_icon_running()
        self.app.running_interpreter_callback = callback
        self.interpreter.run_evaluation(expr, callback)
Пример #10
0
 def change_mode(self, event=None):
     """ Swap the python mode : full python or student """
     if self.mode == "student":
         self.mode = "full"
     else:
         self.mode = "student"
     self.icon_widget.switch_icon_mode(self.mode)
     self.console.change_mode(tr(self.mode))
     self.status_bar.change_mode(tr(self.mode))
     if event:
         tracing.user_is_interacting()
         tracing.send_statement(
             "switched", "mode", {
                 "https://www.lip6.fr/mocah/invalidURI/extensions/mode":
                 tr(self.mode)
             })
Пример #11
0
 def redo_event(self, event):
     if self.pointer >= len(self.undolist):
         self.bell()
         return "break"
     cmd = self.undolist[self.pointer]
     if self.text is not None:
         filename = self.text.short_title()
         tracing.send_statement("redid", "sequence",
                                {"https://www.lip6.fr/mocah/invalidURI/extensions/sequence-list": str(cmd),
                                 "https://www.lip6.fr/mocah/invalidURI/extensions/filename": filename})
         self.text.reset_line()
     cmd.redo(self.delegate)
     self.pointer = self.pointer + 1
     self.can_merge = False
     self.check_saved()
     return "break"
Пример #12
0
    def on_close_release(self, event):
        """Called when the button is released over the close button"""
        # Code for tracing changed tabs
        self.new_tab = self.select()
        if not self.instate([
                'pressed'
        ]) and self.old_tab != self.new_tab and self.old_tab != "":
            old_tab_filename = self.get_filename(self.old_tab)
            new_tab_filename = self.get_filename(self.new_tab)
            tracing.send_statement(
                "switched", "file", {
                    "https://www.lip6.fr/mocah/invalidURI/extensions/old-tab":
                    old_tab_filename,
                    "https://www.lip6.fr/mocah/invalidURI/extensions/current-tab":
                    new_tab_filename
                })

        # Code for closing tab
        if not self.instate(['pressed']):
            return

        element = self.identify(event.x, event.y)
        try:
            index = self.index("@%d,%d" % (event.x, event.y))
        except tk.TclError:
            return

        if "close" in element and self._active == index:
            #do the proper linking to the event
            old_tab_filename = self.get_filename(self.old_tab)
            self.close_current_editor()
            self.new_tab = self.select()
            if self.new_tab != "":
                new_tab_filename = self.get_filename(self.new_tab)
            else:
                new_tab_filename = "no tab selected"
            tracing.send_statement(
                "closed", "file", {
                    "https://www.lip6.fr/mocah/invalidURI/extensions/closed-tab":
                    old_tab_filename,
                    "https://www.lip6.fr/mocah/invalidURI/extensions/current-tab":
                    new_tab_filename
                })
            self.event_generate("<<NotebookTabClosed>>")

        self.state(["!pressed"])
        self._active = None
Пример #13
0
    def check_user_state(self):
        """
        Send a statement of the state of the user. User has 3 state: idle, interacting or typing
        """
        last_typing_time, last_interacting_time = tracing.get_action_timestamps(
        )
        elapsed_typing_time = time.time(
        ) - last_typing_time if last_typing_time else None
        elapsed_interacting_time = time.time(
        ) - last_interacting_time if last_interacting_time else None
        inactivity_threshhold = 30
        new_state = ""
        if elapsed_typing_time is not None and elapsed_interacting_time is not None:
            if self.state == "idle":
                if elapsed_typing_time < inactivity_threshhold:
                    new_state = "typing"
                elif elapsed_interacting_time < inactivity_threshhold:
                    new_state = "interacting"
            elif self.state == "interacting":
                if elapsed_typing_time < inactivity_threshhold:
                    new_state = "typing"
                elif elapsed_interacting_time > inactivity_threshhold:
                    new_state = "idle"
            elif self.state == "typing" and elapsed_typing_time > inactivity_threshhold:
                if elapsed_interacting_time < 30:
                    new_state = "interacting"
        elif elapsed_typing_time is not None:
            if self.state == "idle" and elapsed_typing_time < inactivity_threshhold:
                new_state = "typing"
            elif self.state == "typing" and elapsed_typing_time > inactivity_threshhold:
                new_state = "idle"
        elif elapsed_interacting_time is not None:
            if self.state == "idle" and elapsed_interacting_time < inactivity_threshhold:
                new_state = "interacting"
            elif self.state == "interacting" and elapsed_interacting_time > inactivity_threshhold:
                new_state = "idle"

        if new_state:
            tracing.send_statement("entered", new_state + "-state")
            self.state = new_state
        self.root.after(1000, self.check_user_state)
Пример #14
0
 def save(self, event):
     tracing.user_is_interacting()
     if not self.filename:
         self.save_as(event)
     else:
         if self.writefile(self.filename):
             tracing.send_statement(
                 "saved", "file", {
                     "https://www.lip6.fr/mocah/invalidURI/extensions/filename":
                     os.path.basename(self.filename)
                 })
             self.set_saved(True)
             try:
                 self.editwin.store_file_breaks()
             except AttributeError:  # may be a PyShell
                 pass
     self.editwin.focus_set()
     if not self.filename:
         return None
     else:
         return self.filename
Пример #15
0
    def run_module(self, event=None):
        """ Run the code : give the file name and code will be run from the source file """

        tracing.user_is_interacting()
        # already running
        if self.running_interpreter_callback:
            if self.running_interpreter_proxy and self.running_interpreter_proxy.process.is_alive(
            ):
                report = RunReport()
                report.set_header("\n====== STOP ======\n")
                report.add_execution_error('error',
                                           tr('User interruption'),
                                           class_name='UserTerminatedError')
                report.set_footer("\n==================\n")
                self.running_interpreter_callback(False, report)
            self.running_interpreter_callback = None
            return

        # not (yet) running

        if self.editor_list.get_size() == 0:
            self.main_view.console.no_file_to_run_message()
            return

        reply = self.editor_list.get_current_editor().maybesave_run()
        if (reply != "cancel"):
            self.editor_list.get_current_editor().send_update_changed_line(
                force_sending=True)
            tracing.send_statement(
                "started", "execution", {
                    "https://www.lip6.fr/mocah/invalidURI/extensions/mode":
                    tr(self.mode)
                })
            tracing.save_execution_start()
            file_name = self.editor_list.get_current_editor().long_title()
            self.update_title()
            self.status_bar.update_save_label(file_name)
            self.console.run(file_name)
Пример #16
0
 def open(self, event=None):
     """ Open a file in the text editor """
     tracing.user_is_interacting()
     file_editor = PyEditorFrame(self.editor_list, open=True)
     if (self.editor_list.focusOn(file_editor.long_title()) == False):
         if (file_editor.isOpen()):
             self.editor_list.add(file_editor,
                                  self.main_view.editor_widget,
                                  text=file_editor.get_file_name())
             extensions = {
                 "https://www.lip6.fr/mocah/invalidURI/extensions/filename":
                 file_editor.get_file_name()
             }
             with open(file_editor.long_title(), "r") as source:
                 text = source.read()
                 extensions[
                     "https://www.lip6.fr/mocah/invalidURI/extensions/text"] = text
                 extensions[
                     "https://www.lip6.fr/mocah/invalidURI/extensions/filelength"] = len(
                         text)
             tracing.send_statement("opened", "file", extensions)
         #not clean, io should be handled here and should not require creation of PyEditor widget
         else:
             file_editor.destroy()