def __init__(self, path=None): from mnemosyne.script import Mnemosyne try: self.mnemo = Mnemosyne(path) # Activate the Cloze plugin # Note: The import needs to be here, since it relies on the # presence of the translation engine, which is initialized with # the mnemosyne object. from mnemosyne.libmnemosyne.card_types.cloze import ClozePlugin for plugin in self.mnemo.plugins(): if isinstance(plugin, ClozePlugin): plugin.activate() break except SystemExit: raise KnowledgeException( "Mnemosyne is running. Please close it and reopen the file.")
def main(argv): output_path = '' try: opts, args = getopt.getopt(argv,"ho:",["help","opath="]) except getopt.GetoptError: print 'export_cards_by_tag.py -o <outputpath>' sys.exit(2) for opt, arg in opts: if opt == '-h': print 'export_cards_by_tag.py -o <outputpath>' sys.exit() elif opt in ("-o", "--opath"): output_path = arg mnemosyne = Mnemosyne(data_dir) for _tag in collect_tags(mnemosyne.database()): export_cards(mnemosyne.database(), output_path, _tag) mnemosyne.finalise()
def __init__(self, path=None): from mnemosyne.script import Mnemosyne try: self.mnemo = Mnemosyne(path) # Activate the Cloze plugin # Note: The import needs to be here, since it relies on the # presence of the translation engine, which is initialized with # the mnemosyne object. from mnemosyne.libmnemosyne.card_types.cloze import ClozePlugin for plugin in self.mnemo.plugins(): if isinstance(plugin, ClozePlugin): plugin.activate() break except SystemExit: raise KnowledgeException( "Mnemosyne is running. Please close it and reopen the file." )
def test_sanity(): from mnemosyne.script import Mnemosyne mnemo = Mnemosyne('/tmp/')
# # Script to import audio and pictures from the Rosetta Stone V2 into a Sentence # card type. # Adapt it your own need. It uses linux external tools, so it needs to be # modified to run under Windows. import os import shutil from mnemosyne.script import Mnemosyne # 'data_dir = None' will use the default sysem location, edit as appropriate. data_dir = None mnemosyne = Mnemosyne(data_dir) # Answer questions coming from libmnemosyne. def show_question(question, option0, option1, option2): # Aswer 'no' when adding duplicate cards. if question.startswith("There is already"): return 2 # Answer 'yes' for making tag active. if question.startswith("Make tag"): return 0 else: raise NotImplementedError mnemosyne.main_widget().show_question = show_question
import copy from mnemosyne.script import Mnemosyne from mnemosyne.libmnemosyne.utils import MnemosyneError # 'data_dir = None' will use the default system location, edit as appropriate. data_dir = "C:\dot_test" mnemosyne = Mnemosyne(data_dir) created = {} modified = {} for _card_id, _fact_id in mnemosyne.database().cards(): card = mnemosyne.database().card(_card_id, is_id_internal=True) created[card.id] = card.creation_time modified[card.id] = card.modification_time mnemosyne.finalise() # write data_dir = None mnemosyne = Mnemosyne(data_dir) for id in created: print(id) mnemosyne.database().con.execute( """update cards set creation_time=?, modification_time=? where id=?""", (created[id], modified[id], id)) try: card = mnemosyne.database().card(id, is_id_internal=False) mnemosyne.log().edited_card(card)
# # find_and_replace.py <*****@*****.**> # import copy from mnemosyne.script import Mnemosyne # 'data_dir = None' will use the default system location, edit as appropriate. data_dir = None mnemosyne = Mnemosyne(data_dir) find_string = "\xa0" replace_string = " " for _card_id, _fact_id in mnemosyne.database().cards(): card = mnemosyne.database().card(_card_id, is_id_internal=True) changed = False new_fact_data = copy.copy(card.fact.data) for fact_key in card.fact.data: if find_string in card.fact[fact_key]: new_fact_data[fact_key] = \ card.fact[fact_key].replace(find_string, replace_string) print((new_fact_data[fact_key])) changed = True if changed: mnemosyne.controller().edit_card_and_sisters(card, new_fact_data, card.card_type, [tag.name for tag in card.tags], {}) mnemosyne.finalise()
import os import time import shutil import subprocess HOUR = 60 * 60 # Seconds in an hour. DAY = 24 * HOUR # Seconds in a day. silence = os.path.abspath("silence.mp3") SILENCE_FACTOR = 1.2 # Silence will be 120% of audio length. from mnemosyne.script import Mnemosyne # 'data_dir = None' will use the default sysem location, edit as appropriate. data_dir = None mnemosyne = Mnemosyne(data_dir) # Use mplayer to determine the lenght of an mp3 file. re_length = re.compile(r"""ID_LENGTH=([0-9]*\.[0-9])""", re.DOTALL | re.IGNORECASE) def determine_length(filename): out = subprocess.check_output(["mplayer", "-really-quiet","-vo", "null", "-ao", "null", "-frames", "0", "-identify", filename]) return float(re_length.search(out).group(1)) # Collect all the facts which are either still due or reviewed today. facts = set() for cursor in mnemosyne.database().con.execute("""select _id from cards where active=1 and grade!=-1 and (?>=next_rep or ?<=last_rep)""", (mnemosyne.scheduler().adjusted_now(), time.time() - DAY)): card = mnemosyne.database().card(cursor[0], is_id_internal=True)
# # find_and_replace.py <*****@*****.**> # import copy from mnemosyne.script import Mnemosyne # 'data_dir = None' will use the default system location, edit as appropriate. data_dir = None mnemosyne = Mnemosyne(data_dir) find_string = u"\xa0" replace_string = " " for _card_id, _fact_id in mnemosyne.database().cards(): card = mnemosyne.database().card(_card_id, is_id_internal=True) changed = False new_fact_data = copy.copy(card.fact.data) for fact_key in card.fact.data: if find_string in card.fact[fact_key]: new_fact_data[fact_key] = \ card.fact[fact_key].replace(find_string, replace_string) print new_fact_data[fact_key] changed = True if changed: mnemosyne.controller().edit_card_and_sisters(card, new_fact_data, card.card_type, [tag.name for tag in card.tags], {}) mnemosyne.finalise()
# # add_card.py <*****@*****.**> # from mnemosyne.script import Mnemosyne # 'data_dir = None' will use the default system location, edit as appropriate. data_dir = None mnemosyne = Mnemosyne(data_dir) # For info on the card types and their different fields, see # libmnemosyne/card_types fact_data = {"f": "front", "b": "back"} card_type = mnemosyne.card_type_with_id("1") mnemosyne.controller().create_new_cards(fact_data, card_type, grade=4, tag_names=["tag_1", "tag_2"]) mnemosyne.finalise()
class MnemosyneProxy(SRSProxy): """ An abstraction over Mnemosyne interface. """ CLOSE_MODEL = "5" DEFAULT_DECK = None DEFAULT_MODEL = "1" SYMBOL_EQ_OPEN = "<$>" SYMBOL_EQ_CLOSE = "</$>" def __init__(self, path=None): from mnemosyne.script import Mnemosyne try: self.mnemo = Mnemosyne(path) # Activate the Cloze plugin # Note: The import needs to be here, since it relies on the # presence of the translation engine, which is initialized with # the mnemosyne object. from mnemosyne.libmnemosyne.card_types.cloze import ClozePlugin for plugin in self.mnemo.plugins(): if isinstance(plugin, ClozePlugin): plugin.activate() break except SystemExit: raise KnowledgeException( "Mnemosyne is running. Please close it and reopen the file." ) def cleanup(self): self.mnemo.finalise() del self.mnemo def extract_data(self, fields, model): """ Extracts the data dict from the given fields, depending on the model being used. """ # Transform the fields data to mnemosyne format if model == self.CLOSE_MODEL: data = {'text': fields.get("Text")} else: data = { 'f': fields.get("Front"), 'b': fields.get("Back"), } return data def add_note(self, deck, model, fields, tags=None): """ Adds a new fact with specified fields, model name and tags. Returns the ID of the fact. """ # Pre-process data in fields fields = self.process_all(fields) data = self.extract_data(fields, model) # Convert the deck name to the tag tags = (tags or set()) if deck is not None: tags.add(deck.replace('.', '::')) try: card_type = self.mnemo.card_type_with_id(model) except KeyError: raise KnowledgeException("Model (card type) '{0}' does " "not exist".format(model)) controller = self.mnemo.controller() try: cards = controller.create_new_cards( data, card_type, grade=-1, tag_names=tags, check_for_duplicates=False, save=False, ) except AssertionError: raise KnowledgeException("Fact '{0}' could not be added, it " "most likely contains invalid " "data".format(fields)) # We expect exactly one card created for regular cards, # or at least one for closes if model == self.DEFAULT_MODEL: assert len(cards) == 1 elif model == self.CLOSE_MODEL: assert len(cards) >= 1 # Return the fact ID return cards[0].fact.id def update_note(self, identifier, fields, deck=None, model=None, tags=None): # Get the fact from Mnemosyne db = self.mnemo.database() try: fact = db.fact(identifier, is_id_internal=False) except TypeError: # Mnemosyne raises TypeError in case ID is not found raise FactNotFoundException("Fact with ID '{0}' could not be found" .format(identifier)) cards = db.cards_from_fact(fact) if not cards: raise FactNotFoundException("Fact with ID '{0}' does not have any" "cards assigned".format(identifier)) # Convert the deck name to the tag tags = (tags or set()) if deck is not None: tags.add(deck.replace('.', '::')) # Pre-process data in fields fields = self.process_all(fields) # Transform the fields data to mnemosyne format data = self.extract_data(fields, model) current_data = fact.data current_tags = set([tag.name for tag in cards[0].tags]) # Bail out if no modifications to be performed if current_tags == tags and current_data == data: return # Update the fact card_type = self.mnemo.card_type_with_id(model) new, edited, deleted = card_type.edit_fact(fact, data) fact.data = data db.update_fact(fact) # Create, delete and edit all cards that were affected by this update # This mainly happens with card types that generate multiple cards, like # questions with multiple closes for card in deleted: db.delete_card(card) for card in new: db.add_card(card) for card in edited: db.update_card(card) # Refetch the list of cards cards = db.cards_from_fact(fact) # Set new tags for each card old_tag_objects = set() new_tag_objects = db.get_or_create_tags_with_names(tags) # Fetch the current time modification_time = int(time.time()) for card in cards: old_tag_objects |= card.tags card.modification_time = modification_time card.tags = new_tag_objects db.update_card(card) # Remove redundant tags for tag in old_tag_objects: db.delete_tag_if_unused(tag) def commit(self): db = self.mnemo.database() db.save()
# # export_stats.py <*****@*****.**> # HOUR = 60 * 60 # Seconds in an hour. DAY = 24 * HOUR # Seconds in a day. from mnemosyne.script import Mnemosyne from openSM2sync.log_entry import EventTypes # 'data_dir = None' will use the default sysem location, edit as appropriate. data_dir = None mnemosyne = Mnemosyne(data_dir) for n in range(-10, 0): start_of_day = mnemosyne.database().start_of_day_n_days_ago(abs(n)) print n, mnemosyne.database().con.execute(\ """select avg(grade) from log where ?<=timestamp and timestamp<? and event_type=? and scheduled_interval!=0""", (start_of_day, start_of_day + DAY, EventTypes.REPETITION)).\ fetchone()[0] mnemosyne.finalise()
class MnemosyneProxy(SRSProxy): """ An abstraction over Mnemosyne interface. """ CLOSE_MODEL = "5" DEFAULT_DECK = None DEFAULT_MODEL = "1" SYMBOL_EQ_OPEN = "<$>" SYMBOL_EQ_CLOSE = "</$>" SYMBOL_B_OPEN = "<b>" SYMBOL_B_CLOSE = "</b>" SYMBOL_I_OPEN = "<i>" SYMBOL_I_CLOSE = "</i>" SYMBOL_IMG_OPEN = "<img src=\"" SYMBOL_IMG_CLOSE = "\">" def __init__(self, path=None): from mnemosyne.script import Mnemosyne try: self.mnemo = Mnemosyne(path) # Activate the Cloze plugin # Note: The import needs to be here, since it relies on the # presence of the translation engine, which is initialized with # the mnemosyne object. from mnemosyne.libmnemosyne.card_types.cloze import ClozePlugin for plugin in self.mnemo.plugins(): if isinstance(plugin, ClozePlugin): plugin.activate() break except SystemExit: raise KnowledgeException( "Mnemosyne is running. Please close it and reopen the file.") def cleanup(self): try: self.mnemo.finalise() except Exception as e: pass del self.mnemo def extract_data(self, fields, model): """ Extracts the data dict from the given fields, depending on the model being used. """ # Transform the fields data to mnemosyne format if model == self.CLOSE_MODEL: data = {'text': fields.get("Text")} else: data = { 'f': fields.get("Front"), 'b': fields.get("Back"), } return data def add_media_file(self, filename): """ Adds a new media file to the media directory. """ from mnemosyne.libmnemosyne.utils import copy_file_to_dir, contract_path media_dir = self.mnemo.database().media_dir() # Make sure the path is proper absolute filesystem path filename_expanded = os.path.expanduser(filename) if os.path.isabs(filename_expanded): filename_abs = filename_expanded else: filename_abs = os.path.join( os.path.dirname(utils.get_absolute_filepath()), filename_expanded) copy_file_to_dir(filename_abs, media_dir) return contract_path(filename_abs, media_dir) def add_note(self, deck, model, fields, tags=None): """ Adds a new fact with specified fields, model name and tags. Returns the ID of the fact. """ # Pre-process data in fields fields = self.process_all(fields) data = self.extract_data(fields, model) # Convert the deck name to the tag tags = (tags or set()) if deck is not None: tags.add(deck.replace('.', '::')) try: card_type = self.mnemo.card_type_with_id(model) except KeyError: raise KnowledgeException("Model (card type) '{0}' does " "not exist".format(model)) controller = self.mnemo.controller() try: cards = controller.create_new_cards( data, card_type, grade=-1, tag_names=tags, check_for_duplicates=False, save=False, ) except AssertionError: raise KnowledgeException("Fact '{0}' could not be added, it " "most likely contains invalid " "data".format(fields)) # We expect exactly one card created for regular cards, # or at least one for closes if model == self.DEFAULT_MODEL: assert len(cards) == 1 elif model == self.CLOSE_MODEL: assert len(cards) >= 1 # Return the fact ID return cards[0].fact.id def update_note(self, identifier, fields, deck=None, model=None, tags=None): # Get the fact from Mnemosyne db = self.mnemo.database() try: fact = db.fact(identifier, is_id_internal=False) except TypeError: # Mnemosyne raises TypeError in case ID is not found raise FactNotFoundException( "Fact with ID '{0}' could not be found".format(identifier)) cards = db.cards_from_fact(fact) if not cards: raise FactNotFoundException("Fact with ID '{0}' does not have any" "cards assigned".format(identifier)) # Convert the deck name to the tag tags = (tags or set()) if deck is not None: tags.add(deck.replace('.', '::')) # Pre-process data in fields fields = self.process_all(fields) # Transform the fields data to mnemosyne format data = self.extract_data(fields, model) current_data = fact.data current_tags = set([tag.name for tag in cards[0].tags]) # Bail out if no modifications to be performed if current_tags == tags and current_data == data: return # Update the fact card_type = self.mnemo.card_type_with_id(model) new, edited, deleted = card_type.edit_fact(fact, data) fact.data = data db.update_fact(fact) # Create, delete and edit all cards that were affected by this update # This mainly happens with card types that generate multiple cards, like # questions with multiple closes for card in deleted: db.delete_card(card) for card in new: db.add_card(card) for card in edited: db.update_card(card) # Refetch the list of cards cards = db.cards_from_fact(fact) # Set new tags for each card old_tag_objects = set() new_tag_objects = db.get_or_create_tags_with_names(tags) # Fetch the current time modification_time = int(time.time()) for card in cards: old_tag_objects |= card.tags card.modification_time = modification_time card.tags = new_tag_objects db.update_card(card) # Remove redundant tags for tag in old_tag_objects: db.delete_tag_if_unused(tag) def commit(self): db = self.mnemo.database() db.save()
def test_execute(self): # First, run sanity checks success = False for i in range(5): if self.check_sanity(soft=True): success = True break else: self.teardown() self.setup() if not success: self.check_sanity(soft=False) # Then load the input if self.viminput: # Unindent the lines lines = [l[4:] for l in self.viminput.strip('\n').splitlines()] self.write_buffer(lines) # Do the stuff self.execute() # Check expected output if self.vimoutput: lines = [ l[4:] for l in self.vimoutput.strip('\n').splitlines()[:-1] ] # Replace any identifiers in the output by {identifier} # placeholder buffer_lines = [ re.sub('@(?P<identifier>[^\s]+)\s*$', '{identifier}', line) for line in self.read_buffer() ] assert buffer_lines == lines if self.notes: import sys from mnemosyne.script import Mnemosyne from pony import orm know_db = orm.Database('sqlite', self.db_file) class Mapping(know_db.Entity): knowledge_id = orm.PrimaryKey(str) fact_id = orm.Required(str) know_db.generate_mapping() @orm.db_session def backend_get(knowledge_id): mapping = Mapping.get(knowledge_id=knowledge_id) # If mapping not found in the local database, raise an exception if mapping is None: raise errors.MappingNotFoundException(knowledge_id) return mapping.fact_id mnemosyne = Mnemosyne(self.dir) db = mnemosyne.database() identifiers = filter(lambda x: x is not None, [ re.search('@(?P<identifier>[^\s]+)\s*$', line) for line in self.read_buffer() ]) # We need to translate the identifiers to Mnemosyne identifiers # using backend translated_identifiers = [ backend_get(identifier.group('identifier')) for identifier in identifiers ] facts = [ db.fact(identifier, is_id_internal=False) for identifier in translated_identifiers ] for index, fact in enumerate(facts): expected_fact = self.notes[index] assert expected_fact.get('text') == fact.data.get('text') assert expected_fact.get('front') == fact.data.get('f') assert expected_fact.get('back') == fact.data.get('b') cards = db.cards_from_fact(fact) tags = expected_fact.get('tags') or ['__UNTAGGED__'] assert set(tags) == set([tag.name for tag in cards[0].tags]) # Assert that expected number of cards have been generated assert len(db.cards_from_fact(fact)) == expected_fact.get( 'count', 1) # Assert that all facts have been tested assert len(facts) == len(self.notes) # Assert that all facts have been obtained assert len(facts) == db.fact_count()
# # export_to_pdf.py <*****@*****.**> # # Quick and dirty script to export the latest 100 Arabic cards to a pdf file # Requires unoconv from libreoffice. # 'data_dir = None' will use the default sysem location, edit as appropriate. data_dir = None cards_to_export = 100 text_in_tag = "Arabic" import os from mnemosyne.script import Mnemosyne mnemosyne = Mnemosyne(data_dir) f = file("mnemosyne.txt", "w") _fact_ids = [] count = 0 for cursor in mnemosyne.database().con.execute(\ """select _id, _fact_id from cards order by creation_time desc"""): card = mnemosyne.database().card(cursor[0], is_id_internal=True) if card.fact._id not in _fact_ids and text_in_tag in card.tag_string(): count += 1 if count == cards_to_export: break _fact_ids.append(card.fact._id) q = card.question(render_chain="plain_text").encode("utf-8") a = card.answer(render_chain="plain_text").encode("utf-8")
# # export_to_pdf.py <*****@*****.**> # # Quick and dirty script to export the latest 100 Arabic cards to a pdf file # Requires unoconv from libreoffice. # 'data_dir = None' will use the default sysem location, edit as appropriate. data_dir = None cards_to_export = 100 text_in_tag = "Arabic" import os from mnemosyne.script import Mnemosyne mnemosyne = Mnemosyne(data_dir) f = file("mnemosyne.txt", "w") _fact_ids = [] count = 0 for cursor in mnemosyne.database().con.execute(\ """select _id, _fact_id from cards order by creation_time desc"""): card = mnemosyne.database().card(cursor[0], is_id_internal=True) if card.fact._id not in _fact_ids and text_in_tag in card.tag_string(): count += 1 if count == cards_to_export: break _fact_ids.append(card.fact._id ) q = card.question(render_chain="plain_text").encode("utf-8") a = card.answer(render_chain="plain_text").encode("utf-8")
import os import time import shutil import subprocess HOUR = 60 * 60 # Seconds in an hour. DAY = 24 * HOUR # Seconds in a day. silence = os.path.abspath("silence.mp3") SILENCE_FACTOR = 1.2 # Silence will be 120% of audio length. from mnemosyne.script import Mnemosyne # 'data_dir = None' will use the default sysem location, edit as appropriate. data_dir = None mnemosyne = Mnemosyne(data_dir) # Use mplayer to determine the lenght of an mp3 file. re_length = re.compile(r"""ID_LENGTH=([0-9]*\.[0-9])""", re.DOTALL | re.IGNORECASE) def determine_length(filename): out = subprocess.check_output([ "mplayer", "-really-quiet", "-vo", "null", "-ao", "null", "-frames", "0", "-identify", filename ]) return float(re_length.search(out).group(1)) # Collect all the facts which are either still due or reviewed today.
def test_execute(self): # First, run sanity checks success = False for i in range(5): if self.check_sanity(soft=True): success = True break else: self.teardown() self.setup() if not success: self.check_sanity(soft=False) # Then load the input if self.viminput: # Unindent the lines lines = [l[4:] for l in self.viminput.strip('\n').splitlines()] self.write_buffer(lines) # Do the stuff self.execute() # Check expected output if self.vimoutput: lines = [ l[4:] for l in self.vimoutput.strip('\n').splitlines()[:-1] ] # Replace any identifiers in the output by {identifier} # placeholder buffer_lines = [ re.sub('@(?P<identifier>[^\s]+)\s*$', '{identifier}', line) for line in self.read_buffer() ] assert buffer_lines == lines if self.notes: import sys from mnemosyne.script import Mnemosyne mnemosyne = Mnemosyne(self.dir) db = mnemosyne.database() identifiers = filter(lambda x: x is not None, [ re.search('@(?P<identifier>[^\s]+)\s*$', line) for line in self.read_buffer() ]) facts = [ db.fact(identifier.group('identifier'), is_id_internal=False) for identifier in identifiers ] for index, fact in enumerate(facts): expected_fact = self.notes[index] assert expected_fact.get('text') == fact.data.get('text') assert expected_fact.get('front') == fact.data.get('f') assert expected_fact.get('back') == fact.data.get('b') cards = db.cards_from_fact(fact) tags = expected_fact.get('tags') or ['__UNTAGGED__'] assert set(tags) == set([tag.name for tag in cards[0].tags]) # Assert that expected number of cards have been generated assert len(db.cards_from_fact(fact)) == expected_fact.get('count', 1) # Assert that all facts have been tested assert len(facts) == len(self.notes) # Assert that all facts have been obtained assert len(facts) == db.fact_count()