コード例 #1
0
    async def test_exercise(self):
        """
        Launch exercise window, start lean server, and connect signals
        for testing self.exercise. Very much like solve_exercise, except for
        - setting auto_steps,
        - connecting proof_no_goal signal to test_complete.
        """

        # TODO: box for cancelling auto_test (reprendre la main)
        log.debug(f"Preparing {self.exercise.pretty_name} for test")

        # Stop Lean server if running
        if self.servint:
            await self.servint.file_invalidated.wait()
            self.servint.stop()
            log.info("Lean server stopped!")

        # Start Lean server
        self.servint = ServerInterface(self.nursery)
        await self.servint.start()
        log.info("Lean server started")
        self.server_started.emit()

        # Start exercise window and add auto_steps
        self.exercise_window = ExerciseMainWindow(self.exercise, self.servint)
        self.exercise_window.test_mode = True

        # Connect signals
        self.exercise_window.window_closed.connect(self.close_exercise_window)
        self.servint.proof_no_goals.connect(self.test_complete)
        # The following avoid QMessageBox in firework and when goal solved
        self.exercise_window.cqfd = True

        # Show window
        self.exercise_window.show()
コード例 #2
0
    async def solve_exercise(self):
        """
        Launch exercise window, start lean server, and connect signals.
        """

        log.debug(f"Starting exercise {self.exercise.pretty_name}")

        # Stop Lean server if running
        if self.servint:
            await self.servint.file_invalidated.wait()
            self.servint.stop()
            log.info("Lean server stopped!")
            # ─────────────────── Most Important ─────────────────── #
            #  Re-initialisation of MathObject.Variables
            MathObject.clear()

        # Start Lean server
        self.servint = ServerInterface(self.nursery)
        await self.servint.start()
        log.info("Lean server started")

        # Start exercise window
        self.exercise_window = ExerciseMainWindow(self.exercise, self.servint)

        # Connect signals
        self.exercise_window.window_closed.connect(self.close_exercise_window)
        self.exercise_window.change_exercise.connect(self.choose_exercise)

        # Show window
        self.exercise_window.show()
コード例 #3
0
ファイル: __main__.py プロジェクト: dEAduction/dEAduction
    def __init__(self, nursery, exercise):
        super().__init__()
        self.log = logging.getLogger("Test qt lean")

        self.server = ServerInterface(nursery)

        self.exercise = exercise
        self.statements = self.exercise.course.statements

        self._initUI()

        # Link signals
        self.server.proof_state_change.connect(self.proof_state_update)

        # Start waiter task
        self.server.nursery.start_soon(self.server_task)
コード例 #4
0
async def main():
    """
    See file doc
    """
    log.info('Starting, loading lean file, computing objects, and storing')
    # Choose course and parse it
    dir = os.path.join(os.path.dirname(__file__))
    course_path = dir / Path('exercises_for_tests.lean')
    course = Course.from_file(course_path)

    # check for pkl file and, if it exists, process all statements
    course, unprocessed_statements, course_pkl_path = check_statements(course)

    if not unprocessed_statements:
        log.info("pkl file is up_to_date with all initial_proof_states")
        # Checking
        course = read_data(course_pkl_path)
        return
    else:
        log.info(f"Still {len(unprocessed_statements)} statements to process")

    # confirm before processing file
    print("Processing? (y/n)")
    answer = input()
    if answer == 'y':
        pass
    else:
        print('Quitting')
        return

    #########################
    # Init and start server #
    #########################
    async with trio.open_nursery() as nursery:
        servint = ServerInterface(nursery)
        await servint.start()
        try:
            log.info("Pre-processing course...")
            await get_all_proof_states(servint, course, unprocessed_statements,
                                       course_pkl_path)
        finally:
            servint.stop()  # Good job, buddy
            save_objects([course], course_pkl_path)

        # Checking
        course = read_data(course_pkl_path)
コード例 #5
0
async def main():
    """
    See file doc
    """
    # Choose course and parse it
    course = select_course()
    # check for pkl file and, if it exists, find all unprocessed statements
    course, unprocessed_statements, course_pkl_path = check_statements(course)

    if not unprocessed_statements:
        log.info("pkl fle is up_to_date with all initial_proof_states")
        # Checking
        read_data(course_pkl_path)
        return
    else:
        log.info(f"Still {len(unprocessed_statements)} statements to process")

    # confirm before processing file
    print("Processing? (y/n)")
    answer = input()
    if answer == 'y':
        pass
    else:
        print('Quitting')
        return

    #########################
    # Init and start server #
    #########################
    async with trio.open_nursery() as nursery:
        servint = ServerInterface(nursery)
        await servint.start()
        try:
            log.info("Pre-processing course...")
            await get_all_proof_states(servint, course, unprocessed_statements,
                                       course_pkl_path)
        finally:
            servint.stop()  # Good job, buddy
            save_objects([course], course_pkl_path)

        # Checking
        read_data(course_pkl_path)
コード例 #6
0
class Container(QObject):
    """
    This class is responsible for keeping the memory of open windows
    (CoEx starter and exercise window), launching the windows when
    needed, and connecting relevant signals (when windows are closed,
    when a new exercise is chosen, or when user wants to change
    exercise) to the corresponding launching methods. Note that in PyQt
    signals have to be hosted by a QObject.

    :attribute exercises: list of exercises to be launched one after another
    without asking user. Useful for testing.
    """

    close_chooser_window = Signal()
    close_exercise_window = Signal()
    server_started = Signal()
    test_complete = Signal()  # For testing only

    def __init__(self, nursery, exercise=None):
        super().__init__()

        self.exercise_window: ExerciseMainWindow = None
        self.chooser_window: StartCoExStartup = None
        self.servint: ServerInterface = None
        self.exercise: Exercise = exercise
        self.nursery: trio.Nursery = nursery
        self.exercises: [Exercise] = []
        self.auto_test: bool = False
        self.report: [[str]] = []

    @Slot()
    def choose_exercise(self):
        """
        Launch chooser window and connect signals. This is the first method
        that will be called by main().
        """

        log.debug("Choosing new exercise")
        if not self.chooser_window:
            # Start chooser window
            self.chooser_window = StartCoExStartup(exercise=self.exercise)

            # Connect signals
            self.chooser_window.exercise_chosen.connect(self.start_exercise)
            self.chooser_window.window_closed.connect(
                self.close_chooser_window)
            self.chooser_window.quit_deaduction.connect(self.quit_deaduction)

            # Show window
            self.chooser_window.show()
        else:
            # Focus on chooser window
            self.chooser_window.raise_()
            self.chooser_window.activateWindow()

    @Slot()
    def start_exercise(self, exercise):
        """
        Just a synchronous front-end to the async method solve_exercise
        (apparently slots may not be asynchronous functions).
        """

        self.chooser_window = None  # So that exiting d∃∀duction works
        self.exercise = exercise
        if self.exercise_window:
            # Close window but do not tell main() since a new exercise
            # window will be launched immediately!!
            self.exercise_window.window_closed.disconnect()
            self.exercise_window.close()

        self.nursery.start_soon(self.solve_exercise)

    async def solve_exercise(self):
        """
        Launch exercise window, start lean server, and connect signals.
        """

        log.debug(f"Starting exercise {self.exercise.pretty_name}")

        # Stop Lean server if running
        if self.servint:
            await self.servint.file_invalidated.wait()
            self.servint.stop()
            log.info("Lean server stopped!")
            # ─────────────────── Most Important ─────────────────── #
            #  Re-initialisation of MathObject.Variables
            MathObject.clear()

        # Start Lean server
        self.servint = ServerInterface(self.nursery)
        await self.servint.start()
        log.info("Lean server started")

        # Start exercise window
        self.exercise_window = ExerciseMainWindow(self.exercise, self.servint)

        # Connect signals
        self.exercise_window.window_closed.connect(self.close_exercise_window)
        self.exercise_window.change_exercise.connect(self.choose_exercise)

        # Show window
        self.exercise_window.show()

    async def test_exercise(self):
        """
        Launch exercise window, start lean server, and connect signals
        for testing self.exercise. Very much like solve_exercise, except for
        - setting auto_steps,
        - connecting proof_no_goal signal to test_complete.
        """

        # TODO: box for cancelling auto_test (reprendre la main)
        log.debug(f"Preparing {self.exercise.pretty_name} for test")

        # Stop Lean server if running
        if self.servint:
            await self.servint.file_invalidated.wait()
            self.servint.stop()
            log.info("Lean server stopped!")

        # Start Lean server
        self.servint = ServerInterface(self.nursery)
        await self.servint.start()
        log.info("Lean server started")
        self.server_started.emit()

        # Start exercise window and add auto_steps
        self.exercise_window = ExerciseMainWindow(self.exercise, self.servint)
        self.exercise_window.test_mode = True

        # Connect signals
        self.exercise_window.window_closed.connect(self.close_exercise_window)
        self.servint.proof_no_goals.connect(self.test_complete)
        # The following avoid QMessageBox in firework and when goal solved
        self.exercise_window.cqfd = True

        # Show window
        self.exercise_window.show()

    @Slot()
    def quit_deaduction(self):
        if self.exercise_window:
            self.exercise_window.close()
            # Just in case signal is disconnected
            self.close_exercise_window.emit()
        if self.chooser_window:
            self.chooser_window.close()
            self.close_chooser_window.emit()
コード例 #7
0
ファイル: __main__.py プロジェクト: dEAduction/dEAduction
async def main():
    """
    See file doc.
    """

    cenv.init()
    cdirs.init()
    inst.init()

    #############################################
    # Search course or directory from arguments #
    #############################################
    dir_, course = coex_from_argv()
    if dir_:
        courses = get_courses_from_dir(dir_)
    elif course:
        courses = [course]
    else:
        course = select_course()
        courses = [course]

    # Process each course
    for course in courses:
        # Check for pkl file and, if it exists, find all unprocessed statements
        course, unprocessed_statements, course_pkl_path \
            = check_statements(course)

        if not unprocessed_statements:
            log.info("pkl fle is up_to_date with all initial_proof_states")
            # Checking
            read_data(course_pkl_path)
            continue
        else:
            log.info(f"Still {len(unprocessed_statements)} "
                     f"statements to process")

        # confirm before processing file
        print("Processing? (y/n)")
        answer = input()
        if answer == 'y':
            pass
        else:
            print('Quitting')
            return

        #########################
        # Init and start server #
        #########################
        async with trio.open_nursery() as nursery:
            servint = ServerInterface(nursery)
            await servint.start()
            try:
                log.info("Pre-processing course...")
                await get_all_proof_states(servint, course,
                                           unprocessed_statements,
                                           course_pkl_path)
            except UnicodeDecodeError:
                log.error("UnicodeDecodeError")
            finally:
                servint.stop()  # Good job, buddy
                save_objects([course], course_pkl_path)

            # Checking
            read_data(course_pkl_path)
コード例 #8
0
ファイル: __main__.py プロジェクト: dEAduction/dEAduction
class ExerciseWindow(QWidget):
    closed = Signal()

    def __init__(self, nursery, exercise):
        super().__init__()
        self.log = logging.getLogger("Test qt lean")

        self.server = ServerInterface(nursery)

        self.exercise = exercise
        self.statements = self.exercise.course.statements

        self._initUI()

        # Link signals
        self.server.proof_state_change.connect(self.proof_state_update)

        # Start waiter task
        self.server.nursery.start_soon(self.server_task)

        # Update initial proof state
        #self.proof_state_update(self.server.proof_state)

    async def server_task(self):
        await self.server.start()
        await self.server.exercise_set(self.exercise)
        async with qtrio.enter_emissions_channel(
                signals=[self.closed, self.send.clicked, self.undo.clicked
                         ]) as emissions:
            async for emission in emissions.channel:
                if emission.is_from(self.closed):
                    break
                elif emission.is_from(self.send.clicked):
                    await self.go_send()
                elif emission.is_from(self.undo.clicked):
                    await self.go_undo()

        self.server.stop()

    async def go_send(self):
        self.log.info("Send file to lean")
        self.freeze(True)

        txt = self.edit.toPlainText()
        try:
            await self.server.code_set("add", txt)
        except exceptions.FailedRequestError as ex:
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Critical)
            msg.setWindowTitle("Failed lean request")
            msg.setText("I am broken :'(")

            detailed = ""
            for err in ex.errors:
                detailed += f"* at {err.pos_line} : {err.text}\n"

            msg.setDetailedText(detailed)
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()

        self.freeze(False)

    async def go_undo(self):
        self.log.info("Undo")
        self.freeze(True)
        await self.server.history_undo()
        self.edit.setPlainText(self.server.lean_file.inner_contents)
        self.freeze(False)

    def closeEvent(self, ev):
        super().closeEvent(ev)
        self.closed.emit()

    def _initUI(self):
        # Create widgets
        self.objects = PropobjList()
        self.properties = PropobjList()

        self.goal = Goal("TODO")

        self.edit = QPlainTextEdit()
        self.send = QPushButton("Send to lean")
        self.undo = QPushButton("Undo")

        self.deflist = QListWidget()

        # --> Build deflist
        for st in self.statements:
            self.deflist.addItem(st.pretty_name)

        # --> Link signal
        self.deflist.itemClicked.connect(self.add_statement_name)

        # Create layouts
        goal_layout = QHBoxLayout()
        main_layout = QVBoxLayout()
        workspace_layout = QHBoxLayout()
        propobj_layout = QVBoxLayout()
        tools_layout = QVBoxLayout()
        btns_layout = QHBoxLayout()

        # Create QGroupBox to have titles
        propobj_gb = QGroupBox('Properties and objects')
        self.tools_gb = QGroupBox('Lean code')

        # Put widgets in layouts and group boxes
        goal_layout.addStretch()
        goal_layout.addWidget(self.goal)
        goal_layout.addStretch()

        # Add space below goal
        goal_layout.setContentsMargins(0, 10, 0, 30)  #LTRB

        # Build propobj layout
        propobj_layout.addWidget(self.objects)
        propobj_layout.addWidget(self.properties)
        propobj_gb.setLayout(propobj_layout)

        # Build tools layout
        btns_layout.addWidget(self.send)
        btns_layout.addWidget(self.undo)

        tools_layout.addWidget(self.deflist)
        tools_layout.addWidget(self.edit)
        tools_layout.addLayout(btns_layout)

        self.tools_gb.setLayout(tools_layout)

        # Build workspace layout
        workspace_layout.addWidget(propobj_gb)
        workspace_layout.addWidget(self.tools_gb)

        # Don't forget me
        main_layout.addLayout(goal_layout)
        main_layout.addLayout(workspace_layout)
        self.setWindowTitle("d∃∀duction")
        self.setLayout(main_layout)
        self.show()

    def freeze(self, state: bool):
        self.tools_gb.setEnabled(not state)

    @Slot(QListWidgetItem)
    def add_statement_name(self, item):
        st = self.statements[self.deflist.row(item)]
        self.edit.insertPlainText(st.lean_name)

    @Slot(ProofState)
    def proof_state_update(self, po: ProofState):
        # Update goal
        # log.debug("Updating goal")
        goal = po.goals[0]
        target = goal.target.math_type.format_as_utf8()

        self.goal.setText(target)

        # Update properties and objects
        self.properties.clear()
        self.objects.clear()
        for type_, instances in goal.math_types:
            utf8 = type_.format_as_utf8(is_math_type=True)

            for obj in instances:
                txt = f"{obj.format_as_utf8()} : {utf8}"
                if obj.is_prop(): self.properties.addItem(txt)
                else: self.objects.addItem(txt)