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()
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()
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)
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)
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)
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()
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)
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)