def test_note_deleted(fake_storage): test_notes = [ Note( guid="id1", title="test", content="test", notebookGuid="notebook1", active=True, ), Note( guid="id2", title="test", content="test", notebookGuid="notebook1", active=True, ), ] for note in test_notes: fake_storage.notes.add_note(note) fake_storage.notes.expunge_notes(["id2"]) result = list(fake_storage.notes.iter_notes("notebook1")) assert len(result) == 1 assert result[0].guid == "id1"
def test_get_notes_for_sync(fake_storage): test_notes = [ Note( guid="id1", title="name1", ), Note( guid="id2", title="name2", ), Note( guid="id3", title="name3", ), ] fake_storage.notes.add_notes_for_sync(test_notes) expected = tuple( NoteForSync(guid=n.guid, title=n.title, linked_notebook_guid=None) for n in test_notes ) result = fake_storage.notes.get_notes_for_sync() assert expected == result
def test_trash_notes_count(fake_storage): test_notes = [ Note( guid="id1", title="test", content="test", notebookGuid="test", active=True, ), Note( guid="id2", title="test", content="test", notebookGuid="test", active=False, ), Note( guid="id3", title="test", content="test", notebookGuid="test", active=False, ), ] for note in test_notes: fake_storage.notes.add_note(note) result = fake_storage.notes.get_notes_count(is_active=False) assert result == 2
def test_export_single_notes_over_existing_overwrite(cli_invoker, fake_storage, tmp_path): test_out_path = tmp_path / "test_out" test_notebooks = [ Notebook(guid="nbid1", name="name1", stack="stack1"), Notebook(guid="nbid2", name="name2", stack=None), ] test_notes = [ Note( guid="id1", title="title1", content="test", notebookGuid="nbid1", active=True, ), Note( guid="id2", title="title2", content="test", notebookGuid="nbid2", active=True, ), ] fake_storage.notebooks.add_notebooks(test_notebooks) for note in test_notes: fake_storage.notes.add_note(note) book1_existing_path = test_out_path / "stack1" / "name1" / "title1.enex" book2_existing_path = test_out_path / "name2" / "title2.enex" book1_existing_path.parent.mkdir(parents=True, exist_ok=True) book2_existing_path.parent.mkdir(parents=True, exist_ok=True) book1_existing_path.touch() book2_existing_path.touch() cli_invoker( "export", "--database", "fake_db", "--single-notes", "--overwrite", str(test_out_path), ) assert book1_existing_path.stat().st_size > 0 assert book2_existing_path.stat().st_size > 0
def test_sync_add_linked_notebook_note_with_tag(cli_invoker, mock_evernote_client, fake_storage): mock_evernote_client.fake_l_notebooks.append( Notebook( guid="nbid1", name="name1", ), ) mock_evernote_client.fake_l_tags = [ Tag(guid="tid1", name="tag1"), Tag(guid="tid2", name="tag2"), ] mock_evernote_client.fake_l_notes.append( Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", active=True, contentLength=100, tagGuids=["tid1", "tid2"], )) expected_notes = [ Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", active=True, contentLength=100, tagGuids=["tid1", "tid2"], tagNames=["tag1", "tag2"], ) ] mock_evernote_client.fake_linked_notebooks.append( LinkedNotebook(guid="id3", shardId="s100")) mock_evernote_client.fake_linked_notebook_auth_token = ( "S=200:U=ff:E=fff:C=ff:P=1:A=test222:V=2:H=ff") cli_invoker("sync", "--database", "fake_db") result_notes = list(fake_storage.notes.iter_notes("nbid1")) assert result_notes == expected_notes
def test_notes_trash(fake_storage): test_notes = [ Note( guid="id1", title="test", content="test", notebookGuid="notebook1", active=False, ), Note( guid="id2", title="test", content="test", notebookGuid="notebook2", active=False, ), Note( guid="id3", title="test", content="test", notebookGuid="notebook1", active=True, ), ] expected_notes = [ Note( guid="id1", title="test", content="test", notebookGuid="notebook1", active=False, ), Note( guid="id2", title="test", content="test", notebookGuid="notebook2", active=False, ), ] for note in test_notes: fake_storage.notes.add_note(note) result_notes = list(fake_storage.notes.iter_notes_trash()) assert result_notes == expected_notes
def test_sync_interrupt_download(cli_invoker, mock_evernote_client, fake_storage, mocker): test_notes = [Note(guid=f"id{i}", title="test") for i in range(100)] mock_evernote_client.fake_notes.extend(test_notes) def interrupter(note): if note.guid == "id10": raise KeyboardInterrupt def fake_slow_get_note(note_guid): time.sleep(0.1) return Note( guid=note_guid, title="test", content="test", notebookGuid="test", contentLength=100, active=True, ) mock_get_note = mocker.patch( "evernote_backup.evernote_client_sync.EvernoteClientSync.get_note") mock_get_note.side_effect = fake_slow_get_note mock_add_note = mocker.patch( "evernote_backup.note_storage.NoteStorage.add_note") mock_add_note.side_effect = interrupter cli_invoker("sync", "--database", "fake_db")
def test_sync_add_linked_notebook_note_error_no_access(cli_invoker, mock_evernote_client, fake_storage): mock_evernote_client.fake_l_notebooks.append( Notebook( guid="nbid1", name="name1", ), ) mock_evernote_client.fake_l_notes.append( Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", contentLength=100, active=True, )) mock_evernote_client.fake_linked_notebooks.append( LinkedNotebook(guid="id3")) mock_evernote_client.fake_linked_notebook_auth_token = ( "S=200:U=ff:E=fff:C=ff:P=1:A=test222:V=2:H=ff") mock_evernote_client.fake_auth_linked_notebook_error = True cli_invoker("sync", "--database", "fake_db") result_notebooks = list(fake_storage.notebooks.iter_notebooks()) result_notes = list(fake_storage.notes.iter_notes("nbid1")) assert result_notebooks == [] assert result_notes == []
def test_sync_add_note(cli_invoker, mock_evernote_client, fake_storage): mock_evernote_client.fake_notebooks.append( Notebook( guid="nbid1", name="name1", stack="stack1", serviceUpdated=1000, ), ) test_note = Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", active=True, contentLength=100, ) mock_evernote_client.fake_notes.append(test_note) cli_invoker("sync", "--database", "fake_db") result_notes = list(fake_storage.notes.iter_notes("nbid1")) assert result_notes == [test_note]
def test_sync_exception_while_download_retry_fail(cli_invoker, mock_evernote_client, fake_storage, mocker): test_notes = [Note(guid=f"id{i}", title="test") for i in range(100)] mock_evernote_client.fake_notes.extend(test_notes) def fake_get_note(note_guid): if note_guid == "id10": raise struct.error return Note( guid=note_guid, title="test", content="test", notebookGuid="test", contentLength=100, active=True, ) mock_get_note = mocker.patch( "evernote_backup.evernote_client_sync.EvernoteClientSync.get_note") mock_get_note.side_effect = fake_get_note with pytest.raises(RuntimeError) as excinfo: cli_invoker("sync", "--database", "fake_db") assert "Failed to download note" in str(excinfo.value)
def create_note(auth_token, note_store, note_title, note_body, note_tags, parentNotebook=None): body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" body += "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">" body += "<en-note>%s</en-note>" % note_body # strip spaces, see http://dev.evernote.com/doc/reference/Types.html#Struct_Note note_title = note_title.strip() # https://dev.evernote.com/doc/reference/javadoc/constant-values.html#com.evernote.edam.limits.Constants.EDAM_APPLICATIONDATA_VALUE_LEN_MIN if len(note_title) > 255: note_title = note_title[:255] elif not note_title: note_title = "无标题文档" logger.info(f"title: {note_title}") logger.info(f"body: {body}") # Create note object note = Note() note.title = note_title note.content = body note.tagNames = note_tags # parentNotebook is optional; if omitted, default notebook is used if parentNotebook and hasattr(parentNotebook, 'guid'): note.notebookGuid = parentNotebook.guid # Attempt to create note in Evernote account note = note_store.createNote(auth_token, note) return note
def test_export_yes_trash_single_notes(cli_invoker, fake_storage, tmp_path): test_out_path = tmp_path / "test_out" fake_storage.notes.add_note( Note( guid="id1", title="title1", content="test", notebookGuid="nbid1", active=False, ) ) cli_invoker( "export", "--database", "fake_db", "--include-trash", "--single-notes", str(test_out_path), ) book1_path = test_out_path / "Trash" / "title1.enex" assert book1_path.is_file()
def test_sync_add_note_with_res(cli_invoker, mock_evernote_client, fake_storage): mock_evernote_client.fake_notebooks.append( Notebook( guid="nbid1", name="name1", stack="stack1", serviceUpdated=1000, ), ) test_note = Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", active=True, contentLength=100, resources=[ Resource( guid="rid2", noteGuid="id1", data=Data(bodyHash=md5(b"000").digest(), size=3, body=b"000"), ) ], ) mock_evernote_client.fake_notes.append(test_note) cli_invoker("sync", "--database", "fake_db") result_notes = list(fake_storage.notes.iter_notes("nbid1")) assert result_notes == [test_note]
def saveToEvernote(history): EN_URL = 'https://sandbox.evernote.com' dev_token = "S=s1:U=8d5df:E=14a1ce2575a:C=142c5312b5c:P=1cd:A=en-devtoken:V=2:H=c3fba302a245ad5e2aa489bc02b3b873" client = EvernoteClient(token=dev_token) userStore = client.get_user_store() note_store = client.get_note_store() note = Note() note.title = "chat history" note.content = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">' content = '' for line in history: content += "<br>" + line + "</br>" note.content += '<en-note>' + content + '</en-note>' note = note_store.createNote(note) print note.content def getUserShardId(authToken, userStore): """ Get the User from userStore and return the user's shard ID """ try: user = userStore.getUser(authToken) except (EDAMUserException, EDAMSystemException), e: print "Exception while getting user's shardID:" print type(e), e return None if hasattr(user, 'shardId'): return user.shardId return None
def make_note(auth_token, note_store, title, body, date, tag, parent_notebook=None): # Create note object note = Note() note.title = title note.tagGuids = [tag] note.created = date note.updated = date note.content = ''.join([ '<?xml version="1.0" encoding="UTF-8"?>', '<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">', '<en-note>{}</en-note>'.format(body), ]) # parent_notebook is optional; if omitted, default notebook is used if parent_notebook: note.notebookGuid = parent_notebook # Attempt to create note in Evernote account try: return note_store.createNote(note) except Exception as e: # Something was wrong with the note data # See EDAMErrorCode enumeration for error code explanation # http://dev.evernote.com/documentation/reference/Errors.html#Enum_EDAMErrorCode print('whoa', e) return None
def test_export_no_export_date(cli_invoker, fake_storage, tmp_path): test_out_path = tmp_path / "test_out" test_notebooks = [ Notebook(guid="nbid1", name="name1", stack=None), ] fake_storage.notebooks.add_notebooks(test_notebooks) fake_storage.notes.add_note( Note( guid="id1", title="title1", content="test", notebookGuid="nbid1", active=True, )) cli_invoker( "export", "--database", "fake_db", "--no-export-date", str(test_out_path), ) book1_path = test_out_path / "name1.enex" with open(book1_path, "r") as f: book1_xml = f.read() assert "export-date" not in book1_xml
def test_sync_massive_note_count(cli_invoker, mock_evernote_client, fake_storage, monkeypatch): mock_evernote_client.fake_notebooks.append( Notebook( guid="nbid1", name="name1", stack="stack1", serviceUpdated=1000, ), ) for i in range(10): test_note = Note( guid=f"id{i}", title=f"title{i}", content="body1", notebookGuid="nbid1", contentLength=100, active=True, ) mock_evernote_client.fake_notes.append(test_note) monkeypatch.setattr(note_synchronizer, "THREAD_CHUNK_SIZE", 2) cli_invoker("sync", "--database", "fake_db") result_notes = sorted(fake_storage.notes.iter_notes("nbid1"), key=lambda x: int(x.guid[2:])) assert result_notes == mock_evernote_client.fake_notes
def test_sync_custom_max_chunk_results(cli_invoker, mock_evernote_client, fake_storage): mock_evernote_client.fake_notebooks.append( Notebook( guid="nbid1", name="name1", stack="stack1", serviceUpdated=1000, ), ) test_note = Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", contentLength=100, active=True, ) mock_evernote_client.fake_notes.append(test_note) test_max_chunk_results = 100 cli_invoker("sync", "--database", "fake_db", "--max-chunk-results", test_max_chunk_results) result_notes = list(fake_storage.notes.iter_notes("nbid1")) assert result_notes == [test_note] assert mock_evernote_client.last_maxEntries == test_max_chunk_results
def test_export_over_existing(cli_invoker, fake_storage, tmp_path): test_out_path = tmp_path / "test_out" test_notebooks = [ Notebook(guid="nbid1", name="name1", stack="stack1"), Notebook(guid="nbid2", name="name2", stack=None), Notebook(guid="nbid3", name="name3", stack=None), ] test_notes = [ Note( guid="id1", title="title1", content="test", notebookGuid="nbid1", active=True, ), Note( guid="id2", title="test", content="test", notebookGuid="nbid2", active=True, ), ] fake_storage.notebooks.add_notebooks(test_notebooks) for note in test_notes: fake_storage.notes.add_note(note) book1_existing_path = test_out_path / "stack1" / "name1.enex" book2_existing_path = test_out_path / "name2.enex" book1_existing_path.parent.mkdir(parents=True, exist_ok=True) book2_existing_path.parent.mkdir(parents=True, exist_ok=True) book1_existing_path.touch() book2_existing_path.touch() book1_expected_path = test_out_path / "stack1" / "name1 (1).enex" book2_expected_path = test_out_path / "name2 (1).enex" cli_invoker("export", "--database", "fake_db", str(test_out_path)) assert book1_expected_path.is_file() assert book2_expected_path.is_file()
def test_formatter_empty_note(): formatter = NoteFormatter() test_empty_note = Note() expected_empty_note = " <note>\n </note>\n" formatted_note = formatter.format_note(test_empty_note) assert formatted_note == expected_empty_note
def test_sync_add_note_with_tags(cli_invoker, mock_evernote_client, fake_storage): mock_evernote_client.fake_tags = [ Tag(guid="tid1", name="tag1"), Tag(guid="tid2", name="tag2"), ] mock_evernote_client.fake_notebooks.append( Notebook( guid="nbid1", name="name1", stack="stack1", serviceUpdated=1000, ), ) mock_evernote_client.fake_notes.append( Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", active=True, contentLength=100, tagGuids=["tid1", "tid2"], )) expected_notes = [ Note( guid="id1", title="title1", content="body1", notebookGuid="nbid1", active=True, contentLength=100, tagGuids=["tid1", "tid2"], tagNames=["tag1", "tag2"], ) ] cli_invoker("sync", "--database", "fake_db") result_notes = list(fake_storage.notes.iter_notes("nbid1")) assert result_notes == expected_notes
def fake_slow_get_note(note_guid): time.sleep(0.1) return Note( guid=note_guid, title="test", content="test", notebookGuid="test", contentLength=100, active=True, )
def share_evernote(user, article): client = get_evernote_client(user['extras']['evernote']) note_store = client.get_note_store() note = Note() note.title = article.title note.content = '<?xml version="1.0" encoding="UTF-8"?>' note.content += '<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">' note.content += '<en-note>{0}<br /><a href="{1}">[Article Link]</a></en-note>'.format( article.excerpt, article.url) note_store.createNote(note)
def get(self, file_id): client = self.get_authorized_client() if not client: return self.redirect('/auth-evernote?next={0}'.format(self.request.path)) try: file = self.get_file(file_id) except webapp2.HTTPException as http_ex: if http_ex.code == 401: return self.redirect('/auth?next={0}'.format(self.request.path)) base_url = self.request.host_url + '/edit/{0}'.format(file['id']) extension_loaded = bool(int(self.request.get('extensionLoaded', 1))) # Look for the VideoNot.es Notebook notestore = client.get_note_store() notesbooks = notestore.listNotebooks() notebook = None for a_notesbook in notesbooks: if a_notesbook.name == 'VideoNot.es': notebook = a_notesbook break if not notebook: notebook = Notebook() notebook.name = 'VideoNot.es' notebook = notestore.createNotebook(notebook) # Formatting the note in ENML content_enml = FileUtils.to_ENML(file, base_url) content_enml.append('<br></br><br></br>') content_enml.append('<a href="{0}">View in VideoNot.es</a>'.format(base_url)) if not extension_loaded: content_enml.append('<br/>') content_enml.append('(Tip: you can add snapshots of the video to your export by installing our <a href="https://chrome.google.com/webstore/detail/kmbcnighpdagelfjmlbakfnciogcelgi">Chrome Extension</a>)') # Saving the note in Evernote note = Note() note.title = file['title'] note_content = ''.join(content_enml).encode('utf-8') note.content = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note>{0}</en-note>'.format(note_content) note.content = note.content.replace('&', '&') if notebook: note.notebookGuid = notebook.guid note = notestore.createNote(note) logging.debug('VideoNot.es %s exported to Evernote: %s', file_id, note_content) logging.info('VideoNot.es %s exported to Evernote with id: %s', file_id, note.guid) # Returning to the new note in Evernote user_store = client.get_user_store() notestore_url = '/'.join(user_store.getNoteStoreUrl().split('/')[0:5]) return self.redirect(notestore_url + '/view/notebook/{0}'.format(note.guid))
def test_notes_order(fake_storage): test_notes = [ Note( guid="id5", title="test5", content="test", notebookGuid="notebook1", active=True, ), Note( guid="id4", title="test4", content="test", notebookGuid="notebook1", active=True, ), Note( guid="id2", title="test1", content="test", notebookGuid="notebook1", active=True, ), Note( guid="id1", title="test2", content="test", notebookGuid="notebook1", active=True, ), ] expected_notes_titles_order = ["test1", "test2", "test4", "test5"] for note in test_notes: fake_storage.notes.add_note(note) result_notes_titles_order = list( n.title for n in fake_storage.notes.iter_notes("notebook1") ) assert result_notes_titles_order == expected_notes_titles_order
def store_note(self, note_title, note_content): notebook_guid = self.get_notebook_guid() if notebook_guid is None: notebook_guid = self.create_default_notebook() note = Note() note.title = note_title note.content = HackzurichEvernoteClient.NOTE_BOILERPLATE.format( note_content) note.notebookGuid = notebook_guid self._note_store.createNote(note) return note.guid
def notes_local(self): """Send local notes changes to server""" for note in self.sq(models.Note).filter( and_( models.Note.action != ACTION_NONE, models.Note.action != ACTION_NOEXSIST, models.Note.action != ACTION_CONFLICT, )): self.app.log('Note %s local' % note.title) content = (u""" <!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"> <en-note>%s</en-note> """ % sanitize(html=note.content[:EDAM_NOTE_CONTENT_LEN_MAX]) ).strip().encode('utf8') soup = BeautifulStoneSoup(content, selfClosingTags=[ 'img', 'en-todo', 'en-media', 'br', 'hr', ]) kwargs = dict( title=note.title[:EDAM_NOTE_TITLE_LEN_MAX].strip().encode( 'utf8'), content=soup.prettify(), tagGuids=map( lambda tag: tag.guid, note.tags, ), ) if note.notebook: kwargs['notebookGuid'] = note.notebook.guid if note.guid: kwargs['guid'] = note.guid nt = Note(**kwargs) try: next_action = ACTION_NONE if note.action == ACTION_CHANGE: nt.resources = self._resources_for_note(note) nt = self.note_store.updateNote(self.auth_token, nt) elif note.action == ACTION_CREATE: nt.resources = self._resources_for_note(note) nt = self.note_store.createNote(self.auth_token, nt) note.guid = nt.guid elif note.action == ACTION_DELETE: self.note_store.deleteNote(self.auth_token, nt.guid) self.session.delete(note) except EDAMUserException as e: next_action = ACTION_NONE self.app.log('Note %s failed' % note.title) self.app.log(e) note.action = next_action self.session.commit()
def init_note(guid, content): # Initializing the note object note = Note() note.content = content note.guid = guid # Getting note title soup = BeautifulSoup(content, "html.parser") note.title = soup.title.text # Initializing variables resources = [] resource = None data = None binaryData = None hash = None # Getting note resources path = safeglobals.path_note % (guid, "") for filename in os.listdir(path): if "content.json" not in filename: # Reading binary data with open(os.path.join(path, filename), "rb") as f: binaryData = f.read() # Calculating hash md5 = hashlib.md5() md5.update(binaryData) hash = md5.digest() # Creating data data = Data() data.size = len(binaryData) data.bodyHash = hash data.body = binaryData # Create a new resource resource = Resource() resource.mime = getMime(filename) resource.data = data # Creating attributes attributes = ResourceAttributes() attributes.fileName = filename # Adding the resource to resource collection resource.attributes = attributes resources.append(resource) # Adding resources to the specified note note.resources = resources return note
def fake_get_note(note_guid): if note_guid == "id10": raise struct.error return Note( guid=note_guid, title="test", content="test", notebookGuid="test", contentLength=100, active=True, )
def fake_get_note(note_guid): if note_guid == "id10": raise RuntimeError("Test error") return Note( guid=note_guid, title="test", content="test", notebookGuid="test", contentLength=100, active=True, )