예제 #1
0
    def initialise(self, data_dir=None, config_dir=None,
                   filename=None, automatic_upgrades=True, debug_file=None, 
                   server_only=False):

        """The automatic upgrades of the database can be turned off by setting
        'automatic_upgrade' to False. This is mainly useful for the testsuite.

        """

        if debug_file:
            self.component_manager.debug_file = open(debug_file, "w", 0)
        self.register_components()
        # Upgrade from 1.x if needed.
        if automatic_upgrades:
            from mnemosyne.libmnemosyne.upgrades.upgrade1 import Upgrade1
            Upgrade1(self.component_manager).backup_old_dir()
        if data_dir:
            self.config().data_dir = data_dir
            self.config().config_dir = data_dir
        if config_dir:
            self.config().config_dir = config_dir
        # Upgrade config if needed.
        if automatic_upgrades:
            from mnemosyne.libmnemosyne.upgrades.upgrade3 import Upgrade3
            Upgrade3(self.component_manager).run() 
        self.activate_components()
        register_component_manager(self.component_manager,
            self.config()["user_id"])
        self.execute_user_plugin_dir()
        self.activate_saved_plugins()
        # If we are only running a sync or a review server, do not yet load
        # the database to prevent threading access issues.
        if server_only:
            if filename:
                self.config()["last_database"] = \
                    contract_path(filename, self.config().data_dir)
            return
        # Loading the database should come after all user plugins have been
        # loaded, since these could be needed e.g. for a card type in the
        # database.
        if filename and not filename.endswith(".db"):
            from mnemosyne.libmnemosyne.translator import _
            self.main_widget().show_error(\
                _("Command line argument is not a *.db file."))
            sys.exit()
        self.load_database(filename)
        # Only now that the database is loaded, we can start writing log
        # events to it. This is why we log started_scheduler and
        # loaded_database manually.
        try:
            self.log().started_program()
        except Exception, e:
            if "lock" in str(e):
                from mnemosyne.libmnemosyne.translator import _
                self.main_widget().show_error(\
                 _("Another copy of Mnemosyne is still running.") + "\n" + \
                 _("Continuing is impossible and will lead to data loss!"))
                sys.exit()
            else:
                raise e
예제 #2
0
    def test_upgrade(self):
        old_data_dir = os.path.join(os.getcwd(), "tests", "files", "basedir_bz2")
        from mnemosyne.libmnemosyne.upgrades.upgrade1 import Upgrade1
        Upgrade1(self.mnemosyne.component_manager).upgrade_from_old_data_dir(old_data_dir)
        assert self.config()["dvipng"].rstrip() == \
               "dvipng -D 300 -T tight tmp.dvi\necho"
        assert "14pt" in self.config()["latex_preamble"]
        assert self.config()["user_id"] == "f3fb13c7"
        assert self.log().log_index_of_last_upload() == 2

        assert os.path.exists(os.path.join(old_data_dir,
            "DIRECTORY_NO_LONGER_USED_BY_MNEMOSYNE2"))
        assert os.path.exists(os.path.join(self.mnemosyne.config().data_dir,
                                           "history", "a_2.bz2"))
        log = open(os.path.join(self.mnemosyne.config().data_dir, "log.txt"))
        assert log.readline().strip() == \
               "2005-11-01 09:29:08 : Imported item 82f2ed0d 0 0 0 0 0"
예제 #3
0
class Mnemosyne(Component):
    """This class groups the functionality needed to initialise and finalise
    Mnemosyne in a typical scenario.

    See also 'how to write a new frontend' in the docs for more information
    on startup and configuration of libmnemosyne.

    """
    def __init__(self,
                 upload_science_logs,
                 interested_in_old_reps,
                 asynchronous_database=False):
        """When 'upload_science_logs' is set to 'None', it means that its
        value is user-specified through the GUI. Explicitly setting this to
        True or False overrides the user choice.

        For mobile clients, it is recommended that you set
        'upload_science_logs' to 'False'. We need to specify this as an
        argument here, so that we can inject it on time to prevent the
        uploader thread from starting.

        'interested_in_old_reps' can be set to 'False' on a mobile client
        which does not show historical statistical data, in order to speed
        up the initial sync and save disk space. We've specified this as a
        non-default argument here, in order to force front-end writers to
        consider it.

        Setting 'asynchronous_database' to True increases the risk of data
        loss and should only be done to speed up the test suite.

        """

        sys.excepthook = self.handle_exception
        self.upload_science_logs = upload_science_logs
        self.interested_in_old_reps = interested_in_old_reps
        self.asynchronous_database = asynchronous_database
        self.component_manager = new_component_manager()
        self.components = [
            ("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.card_types.both_ways",
             "FrontToBackToBothWays"),
            ("mnemosyne.libmnemosyne.card_types.both_ways",
             "BothWaysToFrontToBack"),
            ("mnemosyne.libmnemosyne.card_types.vocabulary",
             "FrontToBackToVocabulary"),
            ("mnemosyne.libmnemosyne.card_types.vocabulary",
             "BothWaysToVocabulary"),
            ("mnemosyne.libmnemosyne.card_types.vocabulary",
             "VocabularyToFrontToBack"),
            ("mnemosyne.libmnemosyne.card_types.vocabulary",
             "VocabularyToBothWays"),
            ("mnemosyne.libmnemosyne.render_chains.default_render_chain",
             "DefaultRenderChain"),
            ("mnemosyne.libmnemosyne.render_chains.plain_text_chain",
             "PlainTextChain"),
            ("mnemosyne.libmnemosyne.render_chains.sync_to_card_only_client",
             "SyncToCardOnlyClient"),
            ("mnemosyne.libmnemosyne.render_chains.card_browser_render_chain",
             "CardBrowserRenderChain"),
            ("mnemosyne.libmnemosyne.filters.latex",
             "CheckForUpdatedLatexFiles"),
            ("mnemosyne.libmnemosyne.filters.latex", "LatexFilenamesFromData"),
            ("mnemosyne.libmnemosyne.filters.latex", "DeleteUnusedLatexFiles"),
            ("mnemosyne.libmnemosyne.filters.latex", "PreprocessClozeLatex"),
            ("mnemosyne.libmnemosyne.filters.latex",
             "PostprocessQAClozeLatex"),
            ("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.card_types.sentence", "SentencePlugin"),
            ("mnemosyne.libmnemosyne.criteria.default_criterion",
             "DefaultCriterion"),
            ("mnemosyne.libmnemosyne.databases.SQLite_criterion_applier",
             "DefaultCriterionApplier"),
            ("mnemosyne.libmnemosyne.plugins.cramming_plugin",
             "CrammingPlugin"),
            ("mnemosyne.libmnemosyne.statistics_pages.schedule", "Schedule"),
            ("mnemosyne.libmnemosyne.statistics_pages.retention_score",
             "RetentionScore"),
            ("mnemosyne.libmnemosyne.statistics_pages.cards_added",
             "CardsAdded"),
            ("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"),
            ("mnemosyne.libmnemosyne.file_formats.mnemosyne1_mem",
             "Mnemosyne1Mem"),
            ("mnemosyne.libmnemosyne.file_formats.mnemosyne1_xml",
             "Mnemosyne1XML"),
            ("mnemosyne.libmnemosyne.file_formats.mnemosyne2_cards",
             "Mnemosyne2Cards"),
            ("mnemosyne.libmnemosyne.file_formats.mnemosyne2_db",
             "Mnemosyne2Db"),
            ("mnemosyne.libmnemosyne.file_formats.tsv", "Tsv"),
            ("mnemosyne.libmnemosyne.file_formats.supermemo_7_txt",
             "SuperMemo7Txt"),
            ("mnemosyne.libmnemosyne.file_formats.smconv_XML", "Smconv_XML"),
            ("mnemosyne.libmnemosyne.file_formats.cuecard_wcu", "CuecardWcu")
        ]
        self.extra_components_for_plugin = {}

    def handle_exception(self, type, value, tb):
        body = "An unexpected error has occurred.\n" + \
            "Please forward the following info to the developers:\n\n" + \
            "Traceback (innermost last):\n"
        list = traceback.format_tb(tb, limit=None) + \
               traceback.format_exception_only(type, value)
        body = body + "%-20s %s" % ("".join(list[:-1]), list[-1])
        try:
            if sys.platform != "win32":
                sys.stderr.write(body)
            self.main_widget().show_error(body)
        except:
            sys.stderr.write(body)

    def initialise(self,
                   data_dir=None,
                   config_dir=None,
                   filename=None,
                   automatic_upgrades=True,
                   debug_file=None,
                   server_only=False):
        """The automatic upgrades of the database can be turned off by setting
        'automatic_upgrade' to False. This is mainly useful for the testsuite.

        """

        if debug_file:
            self.component_manager.debug_file = open(debug_file, "w", 0)
        self.register_components()
        # Upgrade from 1.x if needed.
        if automatic_upgrades:
            from mnemosyne.libmnemosyne.upgrades.upgrade1 import Upgrade1
            Upgrade1(self.component_manager).backup_old_dir()
        if data_dir:
            self.config().data_dir = data_dir
            self.config().config_dir = data_dir
        if config_dir:
            self.config().config_dir = config_dir
        # Upgrade config if needed.
        if automatic_upgrades:
            from mnemosyne.libmnemosyne.upgrades.upgrade3 import Upgrade3
            Upgrade3(self.component_manager).run()
        self.activate_components()
        register_component_manager(self.component_manager,
                                   self.config()["user_id"])
        self.execute_user_plugin_dir()
        self.activate_saved_plugins()
        # If we are only running a sync or a review server, do not yet load
        # the database to prevent threading access issues.
        if server_only:
            if filename:
                self.config()["last_database"] = \
                    contract_path(filename, self.config().data_dir)
            return
        # Loading the database should come after all user plugins have been
        # loaded, since these could be needed e.g. for a card type in the
        # database.
        if filename and not filename.endswith(".db"):
            from mnemosyne.libmnemosyne.translator import _
            self.main_widget().show_error(\
                _("Command line argument is not a *.db file."))
            sys.exit()
        self.load_database(filename)
        # Only now that the database is loaded, we can start writing log
        # events to it. This is why we log started_scheduler and
        # loaded_database manually.
        try:
            self.log().started_program()
        except Exception, e:
            if "lock" in str(e):
                from mnemosyne.libmnemosyne.translator import _
                self.main_widget().show_error(\
                 _("Another copy of Mnemosyne is still running.") + "\n" + \
                 _("Continuing is impossible and will lead to data loss!"))
                sys.exit()
            else:
                raise e
        self.log().started_scheduler()
        self.log().loaded_database()
        self.log().future_schedule()
        # Upgrade from 1.x if needed.
        if automatic_upgrades:
            from mnemosyne.libmnemosyne.upgrades.upgrade1 import Upgrade1
            Upgrade1(self.component_manager).run()
        # Finally, we can activate the main widget.
        self.main_widget().activate()