class MyServer(Server): program_name = "Mnemosyne" program_version = "test" capabilities = "TODO" def __init__(self): shutil.rmtree(os.path.abspath("dot_sync_server"), ignore_errors=True) self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True) self.mnemosyne.components.insert( 0, ("mnemosyne.libmnemosyne.gui_translator", "GetTextGuiTranslator")) self.mnemosyne.components.append(("test_sync", "Widget")) self.mnemosyne.gui_for_component["ScheduledForgottenNew"] = \ [("mnemosyne_test", "TestReviewWidget")] self.mnemosyne.initialise(os.path.abspath("dot_sync_server"), automatic_upgrades=False) self.mnemosyne.config().change_user_id("user_id") self.mnemosyne.review_controller().reset() self.supports_binary_transfer = lambda x: False # Add 20 cards to database. card_type = self.mnemosyne.card_type_with_id("1") for i in range(20): fact_data = {"f": "question %d" % (i, ), "b": "answer"} self.mnemosyne.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default" ])[0] self.mnemosyne.database().save() self.mnemosyne.database().release_connection() def authorise(self, login, password): return login == "user" and password == "pass" def load_database(self, database_name): self.mnemosyne.database().load(database_name) return self.mnemosyne.database() def unload_database(self, database): self.mnemosyne.database().release_connection() # Dirty way to make sure we restart the server and create a new database # (as opposed to keep sending old history back and forth)' self.wsgi_server.stop() def run(self): Server.__init__(self, "client_machine_id", 8186, self.mnemosyne.main_widget()) self.serve_until_stopped()
class MyServer(Server): program_name = "Mnemosyne" program_version = "test" capabilities = "TODO" def __init__(self): shutil.rmtree(os.path.abspath("dot_sync_server"), ignore_errors=True) self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True) self.mnemosyne.components.insert(0, ("mnemosyne.libmnemosyne.translator", "GetTextTranslator")) self.mnemosyne.components.append(("test_sync", "Widget")) self.mnemosyne.components.append(("mnemosyne_test", "TestReviewWidget")) self.mnemosyne.initialise(os.path.abspath("dot_sync_server"), automatic_upgrades=False) self.mnemosyne.config().change_user_id("user_id") self.mnemosyne.review_controller().reset() self.supports_binary_transfer = lambda x : False # Add 20 cards to database. card_type = self.mnemosyne.card_type_with_id("1") for i in range (20): fact_data = {"f": "question %d" % (i,), "b": "answer"} self.mnemosyne.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] self.mnemosyne.database().save() self.mnemosyne.database().release_connection() def authorise(self, login, password): return login == "user" and password == "pass" def load_database(self, database_name): self.mnemosyne.database().load(database_name) return self.mnemosyne.database() def unload_database(self, database): self.mnemosyne.database().release_connection() # Dirty way to make sure we restart the server and create a new database # (as opposed to keep sending old history back and forth)' self.wsgi_server.stop() def run(self): Server.__init__(self, "client_machine_id", 8186, self.mnemosyne.main_widget()) self.serve_until_stopped()
class MyServer(Server): program_name = "Mnemosyne" program_version = "test" capabilities = "TODO" stop_after_sync = True def __init__(self): os.system("rm -rf sync_from_here") self.mnemosyne = Mnemosyne() self.mnemosyne.components.insert(0, ("mnemosyne.libmnemosyne.translator", "GetTextTranslator")) self.mnemosyne.components.append(("test_sync", "Widget")) self.mnemosyne.components.append(\ ("mnemosyne.libmnemosyne.ui_components.dialogs", "ProgressDialog")) self.mnemosyne.components.append(\ ("mnemosyne.libmnemosyne.ui_components.review_widget", "ReviewWidget")) self.mnemosyne.initialise(os.path.abspath("sync_from_here")) self.mnemosyne.config().change_user_id("user_id") self.mnemosyne.review_controller().reset() # Add 20 cards to database. card_type = self.mnemosyne.card_type_by_id("1") for i in range (20): fact_data = {"q": "question %d" % (i,), "a": "answer"} self.mnemosyne.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] self.mnemosyne.database().save() def authorise(self, login, password): return login == "user" and password == "pass" def open_database(self, database_name): return self.mnemosyne.database() def run(self): Server.__init__(self, "client_machine_id", "192.168.2.54", 8186, self.mnemosyne.main_widget()) # Because we stop_after_sync is True, serve_forever will actually stop # after one sync. self.serve_forever() self.mnemosyne.finalise()
class WebServer(Component): def __init__(self, port, data_dir, config_dir, filename, **kwds): if "client_on_same_machine_as_server" in kwds: self.client_on_same_machine_as_server = \ kwds["client_on_same_machine_as_server"] del kwds["client_on_same_machine_as_server"] else: self.client_on_same_machine_as_server = False super().__init__(**kwds) self.wsgi_server = None self.port = port self.data_dir = data_dir self.config_dir = config_dir self.filename = filename # When restarting the server, make sure we discard info from the # browser resending the form from the previous session. self.is_just_started = True self.is_mnemosyne_loaded = False self.is_shutting_down = False def activate(self): Component.activate(self) # Late import to speed up application startup. from cheroot import wsgi self.wsgi_server = wsgi.Server(\ ("0.0.0.0", self.port), self.wsgi_app, server_name="localhost", numthreads=1, timeout=5) # We need to set the timeout relatively low, otherwise it will take # too long for the server to process a 'stop' request. def serve_until_stopped(self): try: self.wsgi_server.start() # Sets self.wsgi_server.ready except KeyboardInterrupt: self.wsgi_server.stop() self.unload_mnemosyne() def stop(self): if self.wsgi_server: self.wsgi_server.stop() self.unload_mnemosyne() def load_mnemosyne(self): self.mnemosyne = Mnemosyne(upload_science_logs=True, interested_in_old_reps=True) self.mnemosyne.components.insert( 0, (("mnemosyne.libmnemosyne.gui_translators.gettext_gui_translator", "GetTextGuiTranslator"))) self.mnemosyne.components.append(\ ("mnemosyne.libmnemosyne.ui_components.main_widget", "MainWidget")) self.mnemosyne.components.append(\ ("mnemosyne.web_server.web_server_render_chain", "WebServerRenderChain")) self.mnemosyne.gui_for_component["ScheduledForgottenNew"] = [\ ("mnemosyne.web_server.review_wdgt", "ReviewWdgt")] self.mnemosyne.gui_for_component["NewOnly"] = [\ ("mnemosyne.web_server.review_wdgt", "ReviewWdgt")] self.mnemosyne.gui_for_component["CramAll"] = [\ ("mnemosyne.web_server.review_wdgt", "ReviewWdgt")] self.mnemosyne.gui_for_component["CramRecent"] = [\ ("mnemosyne.web_server.review_wdgt", "ReviewWdgt")] self.mnemosyne.initialise(self.data_dir, config_dir=self.config_dir, filename=self.filename, automatic_upgrades=False) self.save_after_n_reps = self.mnemosyne.config()["save_after_n_reps"] self.mnemosyne.config()["save_after_n_reps"] = 1 self.mnemosyne.config()["study_mode"] = "ScheduledForgottenNew" self.mnemosyne.config()["QA_split"] = "fixed" self.mnemosyne.review_widget().set_client_on_same_machine_as_server(\ self.client_on_same_machine_as_server) self.mnemosyne.controller().reset_study_mode() self.is_mnemosyne_loaded = True self.release_database_after_timeout = \ ReleaseDatabaseAfterTimeout(self.port) self.release_database_after_timeout.start() def unload_mnemosyne(self): if not self.is_mnemosyne_loaded: return self.mnemosyne.config()["save_after_n_reps"] = self.save_after_n_reps self.mnemosyne.finalise() self.is_mnemosyne_loaded = False def wsgi_app(self, environ, start_response): filename = environ["PATH_INFO"] if filename == "/status": response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return [b"200 OK"] # Sometimes, even after the user has clicked 'exit' in the page, # a browser sends a request for e.g. an audio file. if self.is_shutting_down and filename != "/release_database": response_headers = [("Content-type", "text/html")] start_response("503 Service Unavailable", response_headers) return [b"Server stopped"] # Load database if needed. if not self.is_mnemosyne_loaded and filename != "/release_database": self.load_mnemosyne() self.release_database_after_timeout.ping() # All our request return to the root page, so if the path is '/', # return the html of the review widget. if filename == "/": # Process clicked buttons in the form. form = cgi.FieldStorage(fp=environ["wsgi.input"], environ=environ) if "show_answer" in form and not self.is_just_started: self.mnemosyne.review_widget().show_answer() page = self.mnemosyne.review_widget().to_html() elif "grade" in form and not self.is_just_started: grade = int(form["grade"].value) self.mnemosyne.review_widget().grade_answer(grade) page = self.mnemosyne.review_widget().to_html() elif "star" in form: self.mnemosyne.controller().star_current_card() page = self.mnemosyne.review_widget().to_html() elif "exit" in form: self.unload_mnemosyne() page = "Server stopped" self.wsgi_server.stop() self.stop_server_after_timeout = \ StopServerAfterTimeout(self.wsgi_server) self.stop_server_after_timeout.start() self.is_shutting_down = True else: page = self.mnemosyne.review_widget().to_html() if self.is_just_started: self.is_just_started = False # Serve the web page. response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return [page] elif filename == "/release_database": self.unload_mnemosyne() response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return [b"200 OK"] # We need to serve a media file. else: # Late import to speed up application startup. from webob import Request from webob.static import FileApp full_path = self.mnemosyne.database().media_dir() for word in filename.split("/"): full_path = os.path.join(full_path, word) request = Request(environ) if os.path.exists(full_path): etag = "%s-%s-%s" % (os.path.getmtime(full_path), os.path.getsize(full_path), hash(full_path)) else: etag = "none" app = FileApp(full_path, etag=etag) return app(request)(environ, start_response)
("mnemosyne.libmnemosyne.statistics_pages.cards_learned", "CardsLearned"), ("mnemosyne.libmnemosyne.statistics_pages.grades", "Grades"), ("mnemosyne.libmnemosyne.statistics_pages.easiness", "Easiness"), ("mnemosyne.libmnemosyne.statistics_pages.current_card", "CurrentCard"), ("main_wdgt", "MainWdgt")] mnemosyne.initialise(data_dir, filename=filename) # Sync before starting the review server. if mnemosyne.main_widget().show_question(\ "Perform sync?", "Yes", "No", "") == 0: mnemosyne.controller().sync(sync_server, sync_port, sync_username, sync_password) # Make sure the config gets picked up when starting a new # Mnemosyne instance in the web server. mnemosyne.config().save() # Start review server. mnemosyne.database().release_connection() from mnemosyne.web_server.web_server import WebServerThread web_server_thread = WebServerThread\ (mnemosyne.component_manager, is_server_local=True) web_server_thread.daemon = True web_server_thread.start() if mnemosyne.main_widget().show_question(\ "Review server started. Either let Mnemosyne start Chrome, or, if you have problems with sound, start Firefox yourself and go to 127.0.0.1:8513, otherwise click below to start Chrome.", "Start Chrome", "Don't start Chrome", "") == 0: mnemosyne.main_widget().start_native_browser()
class TestCardType(MnemosyneTest): def setup(self): self.initialise_data_dir() self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True, asynchronous_database=True) self.mnemosyne.components.insert( 0, ("mnemosyne.libmnemosyne.translators.gettext_translator", "GetTextTranslator")) self.mnemosyne.components.append(\ ("test_card_type", "DecoratedThreeSided")) self.mnemosyne.components.append(\ ("test_card_type", "Widget")) self.mnemosyne.components.append(\ ("mnemosyne_test", "TestReviewWidget")) self.mnemosyne.initialise(os.path.abspath("dot_test"), automatic_upgrades=False) self.review_controller().reset() def test_card_types(self): card_type = self.card_type_with_id("1") assert self.database().is_in_use(card_type) is False assert card_type.fact_key_with_name("Front") == "f" assert card_type.is_fact_data_valid({"f": "foo"}) == True assert self.card_type_with_id("1") == self.card_type_with_id("1") assert self.card_type_with_id("1") != None def test_database(self): card_type = self.card_type_with_id("1") card_type.fact_views[0].type_answer = True card_type.fact_views[0].extra_data = {"b": "b"} card_type = self.controller().clone_card_type(\ card_type, ("1 clone")) card_type.extra_data = {"b": "b"} self.database().update_card_type(card_type) self.mnemosyne.component_manager.unregister(card_type) card_type_out = self.database().card_type(card_type.id, is_id_internal=False) assert card_type_out.id == "1::1 clone" assert card_type_out.fact_key_with_name("Front") == "f" assert card_type_out.required_fact_keys == ["f"] assert card_type_out.is_fact_data_valid({"f": "foo"}) == True assert card_type_out.is_fact_data_valid({"q": "foo"}) == False assert card_type_out.fact_key_names() == ["Front", "Back"] assert card_type_out.fact_keys_and_names == card_type.fact_keys_and_names assert card_type_out.unique_fact_keys == card_type.unique_fact_keys assert card_type_out.keyboard_shortcuts == card_type.keyboard_shortcuts assert card_type_out.fact_views[0].type_answer == True assert card_type_out.fact_views[0].extra_data == {"b": "b"} assert card_type_out.extra_data == {"b": "b"} assert len(card_type.fact_views) == 1 assert len(card_type_out.fact_views) == 1 assert card_type_out.fact_views[0].id == \ card_type.fact_views[0].id assert card_type_out.fact_views[0].name == \ card_type.fact_views[0].name assert card_type_out.fact_views[0].q_fact_keys == \ card_type.fact_views[0].q_fact_keys assert card_type_out.fact_views[0].a_fact_keys == \ card_type.fact_views[0].a_fact_keys assert card_type_out.fact_views[0].a_on_top_of_q == \ card_type.fact_views[0].a_on_top_of_q # Reset global variables. self.mnemosyne.component_manager.register(card_type) card_type = self.card_type_with_id("1") card_type.fact_views[0].type_answer = False card_type.fact_views[0].extra_data = {} card_type_orig = self.database().card_type("1", is_id_internal=False) assert card_type_orig.fact_views[0].type_answer == False def test_rename_two_clones(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(\ card_type, "2 clone") self.controller().rename_card_type(card_type_1, "1 clone new") assert set([c.name for c in self.card_types() if \ self.database().is_user_card_type(c)]) == \ set(["1 clone new", "2 clone"]) def test_rename_two_clones_b(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(\ card_type, "2 clone") self.controller().rename_card_type(card_type_2, "2 clone new") assert set([c.name for c in self.card_types() if \ self.database().is_user_card_type(c)]) == \ set(["1 clone", "2 clone new"]) def test_delete(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(\ card_type, "2 clone") self.controller().delete_card_type(card_type_1) card_type_out = self.database().card_type(card_type_2.id, is_id_internal=False) assert card_type_out.fact_views[0].id == \ card_type_2.fact_views[0].id assert card_type_out.fact_views[0].name == \ card_type_2.fact_views[0].name assert card_type_out.fact_views[0].q_fact_keys == \ card_type_2.fact_views[0].q_fact_keys assert card_type_out.fact_views[0].a_fact_keys == \ card_type_2.fact_views[0].a_fact_keys assert card_type_out.fact_views[0].a_on_top_of_q == \ card_type_2.fact_views[0].a_on_top_of_q assert card_type_out.fact_views[1].id == \ card_type_2.fact_views[1].id assert card_type_out.fact_views[1].name == \ card_type_2.fact_views[1].name assert card_type_out.fact_views[1].q_fact_keys == \ card_type_2.fact_views[1].q_fact_keys assert card_type_out.fact_views[1].a_fact_keys == \ card_type_2.fact_views[1].a_fact_keys assert card_type_out.fact_views[1].a_on_top_of_q == \ card_type_2.fact_views[1].a_on_top_of_q def test_delete_with_formatting(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(\ card_type, "2 clone") self.config().set_card_type_property("background_colour", "black", card_type_1) self.controller().delete_card_type(card_type_1) def test_cannot_delete(self): global last_error last_error = None card_type = self.card_type_with_id("1") self.controller().delete_card_type(card_type) assert "in use" in last_error last_error = None card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(\ card_type, "2 clone") fact_data = {"f": "question", "b": "answer"} old_card = self.controller().create_new_cards(fact_data, card_type_1, grade=-1, tag_names=["default"])[0] self.controller().delete_card_type(card_type_1) assert "in use" in last_error last_error = None def test_rename(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") self.controller().rename_card_type(card_type_1, "newname") card_type_out = self.database().card_type(card_type_1.id, is_id_internal=False) assert card_type_out.name == "newname" def test_cannot_rename(self): global last_error last_error = None card_type = self.card_type_with_id("1") self.controller().rename_card_type(card_type, "newname") assert last_error.startswith("Cannot rename") last_error = None def test_cannot_rename_duplicate(self): global last_error last_error = None card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") self.controller().rename_card_type(card_type_1, "Vocabulary") assert "in use" in last_error last_error = None def test_has_clones(self): global last_error last_error = None card_type = self.card_type_with_id("1") assert self.database().has_clones(card_type) == False card_type_1 = self.controller().clone_card_type(\ card_type, "1 clone") card_type_2 = self.controller().clone_card_type(\ card_type_1, "1 clone clone") assert self.database().has_clones(card_type) == True assert self.database().has_clones(card_type_1) == True self.controller().delete_card_type(card_type_1) assert "clone" in last_error last_error = None def test_clone_of_clone(self): card_type = self.card_type_with_id("1") assert self.database().is_user_card_type(card_type) == False card_type.fact_views[0].type_answer = True card_type.fact_views[0].extra_data = {"b": "b"} card_type = self.controller().clone_card_type(\ card_type, ("1 clone")) assert self.database().is_user_card_type(card_type) == True card_type = self.controller().clone_card_type(\ card_type, ("1 clone cloned")) assert self.database().is_user_card_type(card_type) == True card_type.extra_data = {"b": "b"} self.database().update_card_type(card_type) self.mnemosyne.component_manager.unregister(card_type) card_type_out = self.database().card_type(card_type.id, is_id_internal=False) assert card_type_out.fact_key_with_name("Front") == "f" assert card_type_out.required_fact_keys == ["f"] assert card_type_out.is_fact_data_valid({"f": "foo"}) == True assert card_type_out.fact_keys_and_names == card_type.fact_keys_and_names assert card_type_out.unique_fact_keys == card_type.unique_fact_keys assert card_type_out.keyboard_shortcuts == card_type.keyboard_shortcuts assert card_type_out.fact_views[0].type_answer == True assert card_type_out.fact_views[0].extra_data == {"b": "b"} assert card_type_out.extra_data == {"b": "b"} assert len(card_type.fact_views) == 1 assert len(card_type_out.fact_views) == 1 assert card_type_out.fact_views[0].id == \ card_type.fact_views[0].id assert card_type_out.fact_views[0].name == \ card_type.fact_views[0].name assert card_type_out.fact_views[0].q_fact_keys == \ card_type.fact_views[0].q_fact_keys assert card_type_out.fact_views[0].a_fact_keys == \ card_type.fact_views[0].a_fact_keys assert card_type_out.fact_views[0].a_on_top_of_q == \ card_type.fact_views[0].a_on_top_of_q # Reset global variables. self.mnemosyne.component_manager.register(card_type) card_type.fact_views[0].type_answer = False card_type.fact_views[0].extra_data = {} fact_data = {"f": "question", "b": "answer"} card = self.mnemosyne.controller().create_new_cards( fact_data, card_type, grade=-1, tag_names=["default"])[0] path = self.mnemosyne.database().path() self.mnemosyne.database().unload() self.mnemosyne.database().load(path) def test_decorators(self): fact_data = { "f": "foreign word", "p_1": "pronunciation", "m_1": "translation" } card_type = self.card_type_with_id("3_decorated") card = self.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] assert "What is the translation of foreign word?" in card.question() def test_properties(self): card_type = self.card_type_with_id("1") self.config().set_card_type_property("font", "myfont", card_type) self.config().set_card_type_property("background_colour", "mycolour", card_type) card_type = self.controller().clone_card_type(\ card_type, ("1 clone")) assert self.config().card_type_property("font", card_type, 'f') == "myfont" assert self.config().card_type_property("background_colour", card_type) == "mycolour"
class TestPlugin(MnemosyneTest): def setup(self): self.initialise_data_dir() self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True, asynchronous_database=True) self.mnemosyne.components.insert( 0, ("mnemosyne.libmnemosyne.gui_translators.gettext_gui_translator", "GetTextGuiTranslator")) self.mnemosyne.components.append(\ ("test_plugin", "Widget")) self.mnemosyne.gui_for_component["ScheduledForgottenNew"] = \ [("mnemosyne_test", "TestReviewWidget")] self.mnemosyne.initialise(os.path.abspath("dot_test"), automatic_upgrades=False) self.review_controller().reset() @raises(AssertionError) def test_1(self): from mnemosyne.libmnemosyne.plugin import Plugin p = Plugin(self.mnemosyne.component_manager) def test_2(self): from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.libmnemosyne.plugin import Plugin class MyCardType(FrontToBack): id = "666" class MyPlugin(Plugin): name = "myplugin" description = "MyPlugin" components = [MyCardType] supported_API_level = 3 p = MyPlugin(self.mnemosyne.component_manager) old_length = len(self.card_types()) p.activate() assert len(self.card_types()) == old_length + 1 p.deactivate() assert len(self.card_types()) == old_length p.activate() fact_data = {"f": "question", "b": "answer"} card_type = self.card_type_with_id("666") self.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"]) p.deactivate() # Pops up an information box that this is not possible. global last_error assert last_error.startswith("Cannot deactivate") last_error = "" def test_deactivate_clone(self): from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.libmnemosyne.plugin import Plugin class MyCardType(FrontToBack): id = "666" class MyPlugin(Plugin): name = "myplugin" description = "MyPlugin" components = [MyCardType] supported_API_level = 3 p = MyPlugin(self.mnemosyne.component_manager) old_length = len(self.card_types()) p.activate() assert len(self.card_types()) == old_length + 1 p.deactivate() assert len(self.card_types()) == old_length p.activate() card_type = self.mnemosyne.card_type_with_id("666") self.mnemosyne.controller().clone_card_type(card_type, "new_name") p.deactivate() # Pops up an information box that this is not possible. global last_error assert last_error.startswith("Cannot deactivate") last_error = "" def test_3(self): from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.libmnemosyne.plugin import Plugin class MyCardType(FrontToBack): id = "666" class MyPlugin(Plugin): name = "myplugin" description = "MyPlugin" components = [MyCardType] supported_API_level = 3 p = MyPlugin(self.mnemosyne.component_manager) old_length = len(self.card_types()) p.activate() assert len(self.card_types()) == old_length + 1 p.deactivate() assert len(self.card_types()) == old_length p.activate() fact_data = {"f": "question", "b": "answer"} card_type = self.card_type_with_id("666") card = self.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] fact = card.fact self.controller().delete_facts_and_their_cards([fact]) p.deactivate() # Should work without problems. def test_4(self): from mnemosyne.libmnemosyne.plugin import Plugin from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.pyqt_ui.card_type_wdgt_generic import GenericCardTypeWdgt class RedGenericCardTypeWdgt(GenericCardTypeWdgt): used_for = FrontToBack def __init__(self, parent, component_manager): GenericCardTypeWdgt.__init__(self, component_manager, parent, FrontToBack()) class RedPlugin(Plugin): name = "Red" description = "Red widget for front-to-back cards" components = [RedGenericCardTypeWdgt] supported_API_level = 3 p = RedPlugin(self.mnemosyne.component_manager) p.activate() assert self.mnemosyne.component_manager.current\ ("generic_card_type_widget", used_for=FrontToBack) != None p.deactivate() assert self.mnemosyne.component_manager.current\ ("generic_card_type_widget", used_for=FrontToBack) == None def test_5(self): for plugin in self.plugins(): component = plugin.components[0] if component.component_type == "card_type" and component.id == "4": plugin.activate() plugin.activate() @raises(NotImplementedError) def test_6(self): from mnemosyne.libmnemosyne.hook import Hook Hook(self.mnemosyne.component_manager).run() def test_install_plugin(self): global filename filename = os.path.join(os.getcwd(), "tests", "files", "hide_toolbar.plugin") self.controller().install_plugin() assert os.path.exists( os.path.join(os.getcwd(), "dot_test", "plugins", "plugin_data")) assert len(self.plugins()) == 4 # Try to install twice. self.controller().install_plugin() assert len(self.plugins()) == 4 # Uninstall. for plugin in self.plugins(): if plugin.__class__.__name__ == "HideToolbarPlugin": self.controller().delete_plugin(plugin) break assert not os.path.exists( os.path.join(os.getcwd(), "dot_test", "plugins", "plugin_data")) assert not os.path.exists( os.path.join(os.getcwd(), "dot_test", "plugins", "HideToolbarPlugin.manifest")) assert os.path.exists(os.path.join(os.getcwd(), "dot_test", "plugins")) assert len(self.plugins()) == 3 # Try to reinstall immediately. self.controller().install_plugin() assert len(self.plugins()) == 4 def test_install_plugin_cancel(self): global filename filename = "" self.controller().install_plugin() def test_install_plugin_missing(self): global filename global last_error filename = os.path.join(os.getcwd(), "tests", "files", "hide_toolbar_missing.plugin") self.controller().install_plugin() assert last_error.startswith("No plugin found") last_error = None def test_install_plugin_corrupt(self): global filename global last_error filename = os.path.join(os.getcwd(), "tests", "files", "hide_toolbar_corrupt.plugin") self.controller().install_plugin() assert last_error.startswith("Error when running") last_error = None
class WebServer(Component): def __init__(self, component_manager, port, data_dir, config_dir, filename, is_server_local=False): Component.__init__(self, component_manager) self.port = port self.data_dir = data_dir self.config_dir = config_dir self.filename = filename self.is_server_local = is_server_local # When restarting the server, make sure we discard info from the # browser resending the form from the previous session. self.is_just_started = True self.is_mnemosyne_loaded = False self.is_shutting_down = False self.wsgi_server = wsgiserver.CherryPyWSGIServer(\ ("0.0.0.0", port), self.wsgi_app, server_name="localhost", numthreads=1, timeout=5) # We need to set the timeout relatively low, otherwise it will take # too long for the server to process a 'stop' request. def serve_until_stopped(self): try: self.wsgi_server.start() # Sets self.wsgi_server.ready except KeyboardInterrupt: self.wsgi_server.stop() self.unload_mnemosyne() def stop(self): self.wsgi_server.stop() self.unload_mnemosyne() def load_mnemosyne(self): self.mnemosyne = Mnemosyne(upload_science_logs=True, interested_in_old_reps=True) self.mnemosyne.components.insert(0, ( ("mnemosyne.libmnemosyne.translators.gettext_translator", "GetTextTranslator"))) self.mnemosyne.components.append(\ ("mnemosyne.libmnemosyne.ui_components.main_widget", "MainWidget")) self.mnemosyne.components.append(\ ("mnemosyne.web_server.review_wdgt", "ReviewWdgt")) self.mnemosyne.components.append(\ ("mnemosyne.web_server.web_server_render_chain", "WebServerRenderChain")) self.mnemosyne.initialise(self.data_dir, config_dir=self.config_dir, filename=self.filename, automatic_upgrades=False) self.mnemosyne.review_controller().set_render_chain("web_server") self.save_after_n_reps = self.mnemosyne.config()["save_after_n_reps"] self.mnemosyne.config()["save_after_n_reps"] = 1 self.mnemosyne.start_review() self.mnemosyne.review_widget().set_is_server_local(\ self.is_server_local) self.is_mnemosyne_loaded = True self.release_database_after_timeout = \ ReleaseDatabaseAfterTimeout(self.port) self.release_database_after_timeout.start() def unload_mnemosyne(self): if not self.is_mnemosyne_loaded: return self.mnemosyne.config()["save_after_n_reps"] = self.save_after_n_reps self.mnemosyne.finalise() self.is_mnemosyne_loaded = False def wsgi_app(self, environ, start_response): filename = environ["PATH_INFO"].decode("utf-8") if filename == "/status": response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return ["200 OK"] # Sometimes, even after the user has clicked 'exit' in the page, # a browser sends a request for e.g. an audio file. if self.is_shutting_down and filename != "/release_database": response_headers = [("Content-type", "text/html")] start_response("503 Service Unavailable", response_headers) return ["Server stopped"] # Load database if needed. if not self.is_mnemosyne_loaded and filename != "/release_database": self.load_mnemosyne() self.release_database_after_timeout.ping() # All our request return to the root page, so if the path is '/', # return the html of the review widget. if filename == "/": # Process clicked buttons in the form. form = cgi.FieldStorage(fp=environ["wsgi.input"], environ=environ) if "show_answer" in form and not self.is_just_started: self.mnemosyne.review_widget().show_answer() page = self.mnemosyne.review_widget().to_html() elif "grade" in form and not self.is_just_started: grade = int(form["grade"].value) self.mnemosyne.review_widget().grade_answer(grade) page = self.mnemosyne.review_widget().to_html() elif "star" in form: self.mnemosyne.controller().star_current_card() page = self.mnemosyne.review_widget().to_html() elif "exit" in form: self.unload_mnemosyne() page = "Server stopped" self.wsgi_server.stop() self.stop_server_after_timeout = \ StopServerAfterTimeout(self.wsgi_server) self.stop_server_after_timeout.start() self.is_shutting_down = True else: page = self.mnemosyne.review_widget().to_html() if self.is_just_started: self.is_just_started = False # Serve the web page. response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return [page] elif filename == "/release_database": self.unload_mnemosyne() response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return ["200 OK"] # We need to serve a media file. else: full_path = self.mnemosyne.database().media_dir() for word in filename.split("/"): full_path = os.path.join(full_path, word) request = Request(environ) # Check if file exists, but work around Android not reporting # the correct filesystem encoding. try: exists = os.path.exists(full_path) except (UnicodeEncodeError, UnicodeDecodeError): _ENCODING = sys.getfilesystemencoding() or \ locale.getdefaultlocale()[1] or "utf-8" full_path = full_path.encode(_ENCODING) if os.path.exists(full_path): etag = "%s-%s-%s" % (os.path.getmtime(full_path), os.path.getsize(full_path), hash(full_path)) else: etag = "none" app = FileApp(full_path, etag=etag) return app(request)(environ, start_response)
class WebServer(Component): def __init__(self, component_manager, port, data_dir, config_dir, filename, is_server_local=False): Component.__init__(self, component_manager) self.port = port self.data_dir = data_dir self.config_dir = config_dir self.filename = filename self.is_server_local = is_server_local # When restarting the server, make sure we discard info from the # browser resending the form from the previous session. self.is_just_started = True self.is_mnemosyne_loaded = False self.is_shutting_down = False self.wsgi_server = wsgiserver.CherryPyWSGIServer(\ ("0.0.0.0", port), self.wsgi_app, server_name="localhost", numthreads=1, timeout=5) # We need to set the timeout relatively low, otherwise it will take # too long for the server to process a 'stop' request. def serve_until_stopped(self): try: self.wsgi_server.start() # Sets self.wsgi_server.ready except KeyboardInterrupt: self.wsgi_server.stop() self.unload_mnemosyne() def stop(self): self.wsgi_server.stop() self.unload_mnemosyne() def load_mnemosyne(self): self.mnemosyne = Mnemosyne(upload_science_logs=True, interested_in_old_reps=True) self.mnemosyne.components.insert( 0, (("mnemosyne.libmnemosyne.translators.gettext_translator", "GetTextTranslator"))) self.mnemosyne.components.append(\ ("mnemosyne.libmnemosyne.ui_components.main_widget", "MainWidget")) self.mnemosyne.components.append(\ ("mnemosyne.web_server.review_wdgt", "ReviewWdgt")) self.mnemosyne.components.append(\ ("mnemosyne.web_server.web_server_render_chain", "WebServerRenderChain")) self.mnemosyne.initialise(self.data_dir, config_dir=self.config_dir, filename=self.filename, automatic_upgrades=False) self.mnemosyne.review_controller().set_render_chain("web_server") self.save_after_n_reps = self.mnemosyne.config()["save_after_n_reps"] self.mnemosyne.config()["save_after_n_reps"] = 1 self.mnemosyne.start_review() self.mnemosyne.review_widget().set_is_server_local(\ self.is_server_local) self.is_mnemosyne_loaded = True self.release_database_after_timeout = \ ReleaseDatabaseAfterTimeout(self.port) self.release_database_after_timeout.start() def unload_mnemosyne(self): if not self.is_mnemosyne_loaded: return self.mnemosyne.config()["save_after_n_reps"] = self.save_after_n_reps self.mnemosyne.finalise() self.is_mnemosyne_loaded = False def wsgi_app(self, environ, start_response): filename = environ["PATH_INFO"].decode("utf-8") if filename == "/status": response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return ["200 OK"] # Sometimes, even after the user has clicked 'exit' in the page, # a browser sends a request for e.g. an audio file. if self.is_shutting_down and filename != "/release_database": response_headers = [("Content-type", "text/html")] start_response("503 Service Unavailable", response_headers) return ["Server stopped"] # Load database if needed. if not self.is_mnemosyne_loaded and filename != "/release_database": self.load_mnemosyne() self.release_database_after_timeout.ping() # All our request return to the root page, so if the path is '/', # return the html of the review widget. if filename == "/": # Process clicked buttons in the form. form = cgi.FieldStorage(fp=environ["wsgi.input"], environ=environ) if "show_answer" in form and not self.is_just_started: self.mnemosyne.review_widget().show_answer() page = self.mnemosyne.review_widget().to_html() elif "grade" in form and not self.is_just_started: grade = int(form["grade"].value) self.mnemosyne.review_widget().grade_answer(grade) page = self.mnemosyne.review_widget().to_html() elif "star" in form: self.mnemosyne.controller().star_current_card() page = self.mnemosyne.review_widget().to_html() elif "exit" in form: self.unload_mnemosyne() page = "Server stopped" self.wsgi_server.stop() self.stop_server_after_timeout = \ StopServerAfterTimeout(self.wsgi_server) self.stop_server_after_timeout.start() self.is_shutting_down = True else: page = self.mnemosyne.review_widget().to_html() if self.is_just_started: self.is_just_started = False # Serve the web page. response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return [page] elif filename == "/release_database": self.unload_mnemosyne() response_headers = [("Content-type", "text/html")] start_response("200 OK", response_headers) return ["200 OK"] # We need to serve a media file. else: full_path = self.mnemosyne.database().media_dir() for word in filename.split("/"): full_path = os.path.join(full_path, word) request = Request(environ) # Check if file exists, but work around Android not reporting # the correct filesystem encoding. try: exists = os.path.exists(full_path) except (UnicodeEncodeError, UnicodeDecodeError): _ENCODING = sys.getfilesystemencoding() or \ locale.getdefaultlocale()[1] or "utf-8" full_path = full_path.encode(_ENCODING) if os.path.exists(full_path): etag = "%s-%s-%s" % (os.path.getmtime(full_path), os.path.getsize(full_path), hash(full_path)) else: etag = "none" app = FileApp(full_path, etag=etag) return app(request)(environ, start_response)
class MyClient(Client): program_name = "Mnemosyne" program_version = "test" capabilities = "TODO" def __init__(self): shutil.rmtree(os.path.abspath("dot_sync_client"), ignore_errors=True) self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True) self.mnemosyne.components = [ ("mnemosyne.libmnemosyne.translator", "NoTranslation"), ("mnemosyne.libmnemosyne.databases.SQLite", "SQLite"), ("mnemosyne.libmnemosyne.configuration", "Configuration"), ("mnemosyne.libmnemosyne.loggers.database_logger", "DatabaseLogger"), ("mnemosyne.libmnemosyne.schedulers.SM2_mnemosyne", "SM2Mnemosyne"), ("mnemosyne.libmnemosyne.stopwatch", "Stopwatch"), ("mnemosyne.libmnemosyne.card_types.front_to_back", "FrontToBack"), ("mnemosyne.libmnemosyne.card_types.both_ways", "BothWays"), ("mnemosyne.libmnemosyne.card_types.vocabulary", "Vocabulary"), ("mnemosyne.libmnemosyne.renderers.html_css", "HtmlCss"), ("mnemosyne.libmnemosyne.filters.escape_to_html", "EscapeToHtml"), ("mnemosyne.libmnemosyne.filters.expand_paths", "ExpandPaths"), ("mnemosyne.libmnemosyne.filters.latex", "Latex"), ("mnemosyne.libmnemosyne.render_chains.default_render_chain", "DefaultRenderChain"), ("mnemosyne.libmnemosyne.render_chains.plain_text_chain", "PlainTextChain"), ("mnemosyne.libmnemosyne.controllers.default_controller", "DefaultController"), ("mnemosyne.libmnemosyne.review_controllers.SM2_controller", "SM2Controller"), ("mnemosyne.libmnemosyne.card_types.map", "MapPlugin"), ("mnemosyne.libmnemosyne.card_types.cloze", "ClozePlugin"), ("mnemosyne.libmnemosyne.criteria.default_criterion", "DefaultCriterion"), ("mnemosyne.libmnemosyne.databases.SQLite_criterion_applier", "DefaultCriterionApplier"), ("mnemosyne.libmnemosyne.plugins.cramming_plugin", "CrammingPlugin") ] self.mnemosyne.components.append(("benchmark_sync_client", "Widget")) self.mnemosyne.components.append(("benchmark_sync_client", "MyReviewWidget")) self.mnemosyne.initialise(os.path.abspath(os.path.join(os.getcwd(), "dot_sync_client")), automatic_upgrades=False) self.mnemosyne.config().change_user_id("user_id") self.check_for_edited_local_media_files = False self.do_backup = False self.mnemosyne.review_controller().reset() # Do 200 reviews. card_type = self.mnemosyne.card_type_with_id("1") fact_data = {"f": "question", "b": "answer"} card = self.mnemosyne.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] self.mnemosyne.database().save() self.mnemosyne.review_controller().show_new_question() for i in range(200): self.mnemosyne.review_controller().show_answer() self.mnemosyne.review_controller().grade_answer(0) Client.__init__(self, "client_machine_id", self.mnemosyne.database(), self.mnemosyne.main_widget()) def do_sync(self): #self.BUFFER_SIZE = 10*8192 #self.behind_proxy = True self.sync("localhost", 8186, "user", "pass") self.mnemosyne.database().save()
class TestCardType(MnemosyneTest): def setup(self): self.initialise_data_dir() self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True, asynchronous_database=True) self.mnemosyne.components.insert( 0, ("mnemosyne.libmnemosyne.translators.gettext_translator", "GetTextTranslator") ) self.mnemosyne.components.append(("test_card_type", "DecoratedThreeSided")) self.mnemosyne.components.append(("test_card_type", "Widget")) self.mnemosyne.components.append(("mnemosyne_test", "TestReviewWidget")) self.mnemosyne.initialise(os.path.abspath("dot_test"), automatic_upgrades=False) self.review_controller().reset() def test_card_types(self): card_type = self.card_type_with_id("1") assert self.database().is_in_use(card_type) is False assert card_type.fact_key_with_name("Front") == "f" assert card_type.is_fact_data_valid({"f": "foo"}) == True assert self.card_type_with_id("1") == self.card_type_with_id("1") assert self.card_type_with_id("1") != None def test_database(self): card_type = self.card_type_with_id("1") card_type.fact_views[0].type_answer = True card_type.fact_views[0].extra_data = {"b": "b"} card_type = self.controller().clone_card_type(card_type, ("1 clone")) card_type.extra_data = {"b": "b"} self.database().update_card_type(card_type) self.mnemosyne.component_manager.unregister(card_type) card_type_out = self.database().card_type(card_type.id, is_id_internal=False) assert card_type_out.id == "1::1 clone" assert card_type_out.fact_key_with_name("Front") == "f" assert card_type_out.required_fact_keys == ["f"] assert card_type_out.is_fact_data_valid({"f": "foo"}) == True assert card_type_out.is_fact_data_valid({"q": "foo"}) == False assert card_type_out.fact_key_names() == ["Front", "Back"] assert card_type_out.fact_keys_and_names == card_type.fact_keys_and_names assert card_type_out.unique_fact_keys == card_type.unique_fact_keys assert card_type_out.keyboard_shortcuts == card_type.keyboard_shortcuts assert card_type_out.fact_views[0].type_answer == True assert card_type_out.fact_views[0].extra_data == {"b": "b"} assert card_type_out.extra_data == {"b": "b"} assert len(card_type.fact_views) == 1 assert len(card_type_out.fact_views) == 1 assert card_type_out.fact_views[0].id == card_type.fact_views[0].id assert card_type_out.fact_views[0].name == card_type.fact_views[0].name assert card_type_out.fact_views[0].q_fact_keys == card_type.fact_views[0].q_fact_keys assert card_type_out.fact_views[0].a_fact_keys == card_type.fact_views[0].a_fact_keys assert card_type_out.fact_views[0].a_on_top_of_q == card_type.fact_views[0].a_on_top_of_q # Reset global variables. self.mnemosyne.component_manager.register(card_type) card_type = self.card_type_with_id("1") card_type.fact_views[0].type_answer = False card_type.fact_views[0].extra_data = {} card_type_orig = self.database().card_type("1", is_id_internal=False) assert card_type_orig.fact_views[0].type_answer == False def test_rename_two_clones(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(card_type, "2 clone") self.controller().rename_card_type(card_type_1, "1 clone new") assert set([c.name for c in self.card_types() if self.database().is_user_card_type(c)]) == set( ["1 clone new", "2 clone"] ) def test_rename_two_clones_b(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(card_type, "2 clone") self.controller().rename_card_type(card_type_2, "2 clone new") assert set([c.name for c in self.card_types() if self.database().is_user_card_type(c)]) == set( ["1 clone", "2 clone new"] ) def test_delete(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(card_type, "2 clone") self.controller().delete_card_type(card_type_1) card_type_out = self.database().card_type(card_type_2.id, is_id_internal=False) assert card_type_out.fact_views[0].id == card_type_2.fact_views[0].id assert card_type_out.fact_views[0].name == card_type_2.fact_views[0].name assert card_type_out.fact_views[0].q_fact_keys == card_type_2.fact_views[0].q_fact_keys assert card_type_out.fact_views[0].a_fact_keys == card_type_2.fact_views[0].a_fact_keys assert card_type_out.fact_views[0].a_on_top_of_q == card_type_2.fact_views[0].a_on_top_of_q assert card_type_out.fact_views[1].id == card_type_2.fact_views[1].id assert card_type_out.fact_views[1].name == card_type_2.fact_views[1].name assert card_type_out.fact_views[1].q_fact_keys == card_type_2.fact_views[1].q_fact_keys assert card_type_out.fact_views[1].a_fact_keys == card_type_2.fact_views[1].a_fact_keys assert card_type_out.fact_views[1].a_on_top_of_q == card_type_2.fact_views[1].a_on_top_of_q def test_delete_with_formatting(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(card_type, "2 clone") self.config().set_card_type_property("background_colour", "black", card_type_1) self.controller().delete_card_type(card_type_1) def test_cannot_delete(self): global last_error last_error = None card_type = self.card_type_with_id("1") self.controller().delete_card_type(card_type) assert "in use" in last_error last_error = None card_type_1 = self.controller().clone_card_type(card_type, "1 clone") card_type = self.card_type_with_id("2") card_type_2 = self.controller().clone_card_type(card_type, "2 clone") fact_data = {"f": "question", "b": "answer"} old_card = self.controller().create_new_cards(fact_data, card_type_1, grade=-1, tag_names=["default"])[0] self.controller().delete_card_type(card_type_1) assert "in use" in last_error last_error = None def test_rename(self): card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(card_type, "1 clone") self.controller().rename_card_type(card_type_1, "newname") card_type_out = self.database().card_type(card_type_1.id, is_id_internal=False) assert card_type_out.name == "newname" def test_cannot_rename(self): global last_error last_error = None card_type = self.card_type_with_id("1") self.controller().rename_card_type(card_type, "newname") assert last_error.startswith("Cannot rename") last_error = None def test_cannot_rename_duplicate(self): global last_error last_error = None card_type = self.card_type_with_id("1") card_type_1 = self.controller().clone_card_type(card_type, "1 clone") self.controller().rename_card_type(card_type_1, "Vocabulary") assert "in use" in last_error last_error = None def test_has_clones(self): global last_error last_error = None card_type = self.card_type_with_id("1") assert self.database().has_clones(card_type) == False card_type_1 = self.controller().clone_card_type(card_type, "1 clone") card_type_2 = self.controller().clone_card_type(card_type_1, "1 clone clone") assert self.database().has_clones(card_type) == True assert self.database().has_clones(card_type_1) == True self.controller().delete_card_type(card_type_1) assert "clone" in last_error last_error = None def test_clone_of_clone(self): card_type = self.card_type_with_id("1") assert self.database().is_user_card_type(card_type) == False card_type.fact_views[0].type_answer = True card_type.fact_views[0].extra_data = {"b": "b"} card_type = self.controller().clone_card_type(card_type, ("1 clone")) assert self.database().is_user_card_type(card_type) == True card_type = self.controller().clone_card_type(card_type, ("1 clone cloned")) assert self.database().is_user_card_type(card_type) == True card_type.extra_data = {"b": "b"} self.database().update_card_type(card_type) self.mnemosyne.component_manager.unregister(card_type) card_type_out = self.database().card_type(card_type.id, is_id_internal=False) assert card_type_out.fact_key_with_name("Front") == "f" assert card_type_out.required_fact_keys == ["f"] assert card_type_out.is_fact_data_valid({"f": "foo"}) == True assert card_type_out.fact_keys_and_names == card_type.fact_keys_and_names assert card_type_out.unique_fact_keys == card_type.unique_fact_keys assert card_type_out.keyboard_shortcuts == card_type.keyboard_shortcuts assert card_type_out.fact_views[0].type_answer == True assert card_type_out.fact_views[0].extra_data == {"b": "b"} assert card_type_out.extra_data == {"b": "b"} assert len(card_type.fact_views) == 1 assert len(card_type_out.fact_views) == 1 assert card_type_out.fact_views[0].id == card_type.fact_views[0].id assert card_type_out.fact_views[0].name == card_type.fact_views[0].name assert card_type_out.fact_views[0].q_fact_keys == card_type.fact_views[0].q_fact_keys assert card_type_out.fact_views[0].a_fact_keys == card_type.fact_views[0].a_fact_keys assert card_type_out.fact_views[0].a_on_top_of_q == card_type.fact_views[0].a_on_top_of_q # Reset global variables. self.mnemosyne.component_manager.register(card_type) card_type.fact_views[0].type_answer = False card_type.fact_views[0].extra_data = {} fact_data = {"f": "question", "b": "answer"} card = self.mnemosyne.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] path = self.mnemosyne.database().path() self.mnemosyne.database().unload() self.mnemosyne.database().load(path) def test_decorators(self): fact_data = {"f": "foreign word", "p_1": "pronunciation", "m_1": "translation"} card_type = self.card_type_with_id("3_decorated") card = self.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] assert "What is the translation of foreign word?" in card.question() def test_properties(self): card_type = self.card_type_with_id("1") self.config().set_card_type_property("font", "myfont", card_type) self.config().set_card_type_property("background_colour", "mycolour", card_type) card_type = self.controller().clone_card_type(card_type, ("1 clone")) assert self.config().card_type_property("font", card_type, "f") == "myfont" assert self.config().card_type_property("background_colour", card_type) == "mycolour"
class MyClient(Client): program_name = "Mnemosyne" program_version = "test" capabilities = "TODO" def __init__(self): shutil.rmtree(os.path.abspath("dot_sync_client"), ignore_errors=True) self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True) self.mnemosyne.components = [ ("mnemosyne.libmnemosyne.translator", "NoTranslation"), ("mnemosyne.libmnemosyne.databases.SQLite", "SQLite"), ("mnemosyne.libmnemosyne.configuration", "Configuration"), ("mnemosyne.libmnemosyne.loggers.database_logger", "DatabaseLogger"), ("mnemosyne.libmnemosyne.schedulers.SM2_mnemosyne", "SM2Mnemosyne"), ("mnemosyne.libmnemosyne.stopwatch", "Stopwatch"), ("mnemosyne.libmnemosyne.card_types.front_to_back", "FrontToBack"), ("mnemosyne.libmnemosyne.card_types.both_ways", "BothWays"), ("mnemosyne.libmnemosyne.card_types.vocabulary", "Vocabulary"), ("mnemosyne.libmnemosyne.renderers.html_css", "HtmlCss"), ("mnemosyne.libmnemosyne.filters.escape_to_html", "EscapeToHtml"), ("mnemosyne.libmnemosyne.filters.expand_paths", "ExpandPaths"), ("mnemosyne.libmnemosyne.filters.latex", "Latex"), ("mnemosyne.libmnemosyne.render_chains.default_render_chain", "DefaultRenderChain"), ("mnemosyne.libmnemosyne.render_chains.plain_text_chain", "PlainTextChain"), ("mnemosyne.libmnemosyne.controllers.default_controller", "DefaultController"), ("mnemosyne.libmnemosyne.review_controllers.SM2_controller", "SM2Controller"), ("mnemosyne.libmnemosyne.card_types.map", "MapPlugin"), ("mnemosyne.libmnemosyne.card_types.cloze", "ClozePlugin"), ("mnemosyne.libmnemosyne.criteria.default_criterion", "DefaultCriterion"), ("mnemosyne.libmnemosyne.databases.SQLite_criterion_applier", "DefaultCriterionApplier"), ("mnemosyne.libmnemosyne.plugins.cramming_plugin", "CrammingPlugin") ] self.mnemosyne.components.append(("benchmark_sync_client", "Widget")) self.mnemosyne.components.append(("benchmark_sync_client", "MyReviewWidget")) self.mnemosyne.initialise(os.path.abspath(os.path.join(os.getcwdu(), "dot_sync_client")), automatic_upgrades=False) self.mnemosyne.config().change_user_id("user_id") self.check_for_edited_local_media_files = False self.do_backup = False self.mnemosyne.review_controller().reset() # Do 200 reviews. card_type = self.mnemosyne.card_type_with_id("1") fact_data = {"f": "question", "b": "answer"} card = self.mnemosyne.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] self.mnemosyne.database().save() self.mnemosyne.review_controller().show_new_question() for i in range(200): self.mnemosyne.review_controller().show_answer() self.mnemosyne.review_controller().grade_answer(0) Client.__init__(self, "client_machine_id", self.mnemosyne.database(), self.mnemosyne.main_widget()) def do_sync(self): #self.BUFFER_SIZE = 10*8192 #self.behind_proxy = True self.sync("localhost", 8186, "user", "pass") self.mnemosyne.database().save()
class TestPlugin(MnemosyneTest): def setup(self): self.initialise_data_dir() self.mnemosyne = Mnemosyne(upload_science_logs=False, interested_in_old_reps=True, asynchronous_database=True) self.mnemosyne.components.insert(0, ("mnemosyne.libmnemosyne.translators.gettext_translator", "GetTextTranslator")) self.mnemosyne.components.append(\ ("test_plugin", "Widget")) self.mnemosyne.components.append(\ ("mnemosyne_test", "TestReviewWidget")) self.mnemosyne.initialise(os.path.abspath("dot_test"), automatic_upgrades=False) self.review_controller().reset() @raises(AssertionError) def test_1(self): from mnemosyne.libmnemosyne.plugin import Plugin p = Plugin(self.mnemosyne.component_manager) def test_2(self): from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.libmnemosyne.plugin import Plugin class MyCardType(FrontToBack): id = "666" class MyPlugin(Plugin): name = "myplugin" description = "MyPlugin" components = [MyCardType] p = MyPlugin(self.mnemosyne.component_manager) old_length = len(self.card_types()) p.activate() assert len(self.card_types()) == old_length + 1 p.deactivate() assert len(self.card_types()) == old_length p.activate() fact_data = {"f": "question", "b": "answer"} card_type = self.card_type_with_id("666") self.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"]) p.deactivate() # Pops up an information box that this is not possible. global last_error assert last_error.startswith("Cannot deactivate") last_error = "" def test_deactivate_clone(self): from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.libmnemosyne.plugin import Plugin class MyCardType(FrontToBack): id = "666" class MyPlugin(Plugin): name = "myplugin" description = "MyPlugin" components = [MyCardType] p = MyPlugin(self.mnemosyne.component_manager) old_length = len(self.card_types()) p.activate() assert len(self.card_types()) == old_length + 1 p.deactivate() assert len(self.card_types()) == old_length p.activate() card_type = self.mnemosyne.card_type_with_id("666") self.mnemosyne.controller().clone_card_type(card_type, "new_name") p.deactivate() # Pops up an information box that this is not possible. global last_error assert last_error.startswith("Cannot deactivate") last_error = "" def test_3(self): from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.libmnemosyne.plugin import Plugin class MyCardType(FrontToBack): id = "666" class MyPlugin(Plugin): name = "myplugin" description = "MyPlugin" components = [MyCardType] p = MyPlugin(self.mnemosyne.component_manager) old_length = len(self.card_types()) p.activate() assert len(self.card_types()) == old_length + 1 p.deactivate() assert len(self.card_types()) == old_length p.activate() fact_data = {"f": "question", "b": "answer"} card_type = self.card_type_with_id("666") card = self.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] fact = card.fact self.controller().delete_facts_and_their_cards([fact]) p.deactivate() # Should work without problems. def test_4(self): from mnemosyne.libmnemosyne.plugin import Plugin from mnemosyne.libmnemosyne.card_types.front_to_back import FrontToBack from mnemosyne.pyqt_ui.card_type_wdgt_generic import GenericCardTypeWdgt class RedGenericCardTypeWdgt(GenericCardTypeWdgt): used_for = FrontToBack def __init__(self, parent, component_manager): GenericCardTypeWdgt.__init__(self, component_manager, parent, FrontToBack()) class RedPlugin(Plugin): name = "Red" description = "Red widget for front-to-back cards" components = [RedGenericCardTypeWdgt] p = RedPlugin(self.mnemosyne.component_manager) p.activate() assert self.mnemosyne.component_manager.current\ ("generic_card_type_widget", used_for=FrontToBack) != None p.deactivate() assert self.mnemosyne.component_manager.current\ ("generic_card_type_widget", used_for=FrontToBack) == None def test_5(self): for plugin in self.plugins(): component = plugin.components[0] if component.component_type == "card_type" and component.id == "4": plugin.activate() plugin.activate() @raises(NotImplementedError) def test_6(self): from mnemosyne.libmnemosyne.hook import Hook Hook(self.mnemosyne.component_manager).run() def test_install_plugin(self): global filename filename = os.path.join(os.getcwd(), "tests", "files", "hide_toolbar.plugin") self.controller().install_plugin() assert os.path.exists(os.path.join(os.getcwd(), "dot_test", "plugins", "plugin_data")) assert len(self.plugins()) == 5 # Try to install twice. self.controller().install_plugin() assert len(self.plugins()) == 5 # Uninstall. for plugin in self.plugins(): if plugin.__class__.__name__ == "HideToolbarPlugin": self.controller().delete_plugin(plugin) break assert not os.path.exists(os.path.join(os.getcwd(), "dot_test", "plugins", "plugin_data")) assert not os.path.exists(os.path.join(os.getcwd(), "dot_test", "plugins", "HideToolbarPlugin.manifest")) assert os.path.exists(os.path.join(os.getcwd(), "dot_test", "plugins")) assert len(self.plugins()) == 4 # Try to reinstall immediately. self.controller().install_plugin() assert len(self.plugins()) == 5 def test_install_plugin_cancel(self): global filename filename = "" self.controller().install_plugin() def test_install_plugin_missing(self): global filename global last_error filename = os.path.join(os.getcwd(), "tests", "files", "hide_toolbar_missing.plugin") self.controller().install_plugin() assert last_error.startswith("No plugin found") last_error = None def test_install_plugin_corrupt(self): global filename global last_error filename = os.path.join(os.getcwd(), "tests", "files", "hide_toolbar_corrupt.plugin") self.controller().install_plugin() assert last_error.startswith("Error when running") last_error = None
class MyClient(Client): program_name = "Mnemosyne" program_version = "test" capabilities = "TODO" def __init__(self): self.mnemosyne = Mnemosyne() self.mnemosyne.components = [ ("mnemosyne.libmnemosyne.translator", "NoTranslation"), ("mnemosyne.libmnemosyne.databases.SQLite", "SQLite"), ("mnemosyne.libmnemosyne.configuration", "Configuration"), ("mnemosyne.libmnemosyne.loggers.database_logger", "DatabaseLogger"), ("mnemosyne.libmnemosyne.schedulers.SM2_mnemosyne", "SM2Mnemosyne"), ("mnemosyne.libmnemosyne.stopwatch", "Stopwatch"), ("mnemosyne.libmnemosyne.card_types.front_to_back", "FrontToBack"), ("mnemosyne.libmnemosyne.card_types.both_ways", "BothWays"), ("mnemosyne.libmnemosyne.card_types.three_sided", "ThreeSided"), ("mnemosyne.libmnemosyne.renderers.html_css_old", "HtmlCssOld"), ("mnemosyne.libmnemosyne.filters.escape_to_html", "EscapeToHtml"), ("mnemosyne.libmnemosyne.filters.expand_paths", "ExpandPaths"), ("mnemosyne.libmnemosyne.filters.latex", "Latex"), ("mnemosyne.libmnemosyne.controllers.default_controller", "DefaultController"), ("mnemosyne.libmnemosyne.review_controllers.SM2_controller", "SM2Controller"), ("mnemosyne.libmnemosyne.card_types.map", "MapPlugin"), ("mnemosyne.libmnemosyne.card_types.cloze", "ClozePlugin"), ("mnemosyne.libmnemosyne.activity_criteria.default_criterion", "DefaultCriterion"), ("mnemosyne.libmnemosyne.databases.SQLite_criterion_applier", "DefaultCriterionApplier"), ("mnemosyne.libmnemosyne.plugins.cramming_plugin", "CrammingPlugin") ] self.mnemosyne.components.append(("benchmark_sync_client", "Widget")) self.mnemosyne.components.append(\ ("mnemosyne.libmnemosyne.ui_components.review_widget", "ReviewWidget")) self.mnemosyne.components.append(\ ("mnemosyne.libmnemosyne.ui_components.dialogs", "ProgressDialog")) self.mnemosyne.initialise(os.path.abspath(os.path.join(os.getcwdu(), "dot_benchmark"))) self.mnemosyne.config().change_user_id("user_id") self.mnemosyne.review_controller().reset() # Do 200 reviews. card_type = self.mnemosyne.card_type_by_id("1") fact_data = {"q": "question", "a": "answer"} card = self.mnemosyne.controller().create_new_cards(fact_data, card_type, grade=-1, tag_names=["default"])[0] self.mnemosyne.database().save() self.mnemosyne.review_controller().new_question() for i in range(200): self.mnemosyne.review_controller().show_answer() self.mnemosyne.review_controller().grade_answer(0) Client.__init__(self, "client_machine_id", self.mnemosyne.database(), self.mnemosyne.main_widget()) def do_sync(self): self.sync("192.168.2.54", 8186, "user", "pass") self.mnemosyne.database().save()