Example #1
0
    def helper_save_note(self, k, note):
        """Save a single note to disc.

        """

        if self.config.notes_as_txt:
            t = utils.get_note_title_file(note)
            if t and not note.get('deleted'):
                if k in self.titlelist:
                    logging.debug('Writing note : %s %s' %
                                  (t, self.titlelist[k]))
                    if self.titlelist[k] != t:
                        dfn = os.path.join(self.config.txt_path,
                                           self.titlelist[k])
                        if os.path.isfile(dfn):
                            logging.debug('Delete file %s ' % (dfn, ))
                            os.unlink(dfn)
                        else:
                            logging.debug('File not exits %s ' % (dfn, ))
                else:
                    logging.debug('Key not in list %s ' % (k, ))

                self.titlelist[k] = t
                fn = os.path.join(self.config.txt_path, t)
                try:
                    with codecs.open(fn, mode='wb', encoding='utf-8') as f:
                        c = note.get('content')
                        if isinstance(c, str):
                            c = unicode(c, 'utf-8')
                        else:
                            c = unicode(c)

                        f.write(c)
                except IOError as e:
                    logging.error('NotesDB_save: Error opening %s: %s' %
                                  (fn, str(e)))
                    raise WriteError('Error opening note file')

                except ValueError as e:
                    logging.error('NotesDB_save: Error writing %s: %s' %
                                  (fn, str(e)))
                    raise WriteError('Error writing note file')

            elif t and note.get('deleted') and k in self.titlelist:
                dfn = os.path.join(self.config.txt_path, self.titlelist[k])
                if os.path.isfile(dfn):
                    logging.debug('Delete file %s ' % (dfn, ))
                    os.unlink(dfn)

        fn = self.helper_key_to_fname(k)
        if not self.config.simplenote_sync and note.get('deleted'):
            if os.path.isfile(fn):
                os.unlink(fn)
        else:
            json.dump(note, codecs.open(fn, 'wb', encoding='utf-8'), indent=2)

        # record that we saved this to disc.
        note['savedate'] = time.time()
Example #2
0
    def helper_save_note(self, k, note):
        """Save a single note to disc.
        
        """

        if self.config.notes_as_txt:
            t = utils.get_note_title_file(note)
            if t and not note.get('deleted'):
                if k in self.titlelist:
                    logging.debug('Writing note : %s %s' % (t,self.titlelist[k] ))
                    if self.titlelist[k] != t:
                        dfn = os.path.join(self.config.txt_path, self.titlelist[k])
                        if os.path.isfile(dfn):
                            logging.debug('Delete file %s ' % (dfn, ))
                            os.unlink(dfn)
                        else:
                            logging.debug('File not exits %s ' % (dfn, ))
                else:
                    logging.debug('Key not in list %s ' % (k, ))

                self.titlelist[k] = t
                fn = os.path.join(self.config.txt_path, t)
                with codecs.open(fn, mode='wb', encoding='utf-8') as f:  
                    c = note.get('content')
                    if isinstance(c, str):
                        c = unicode(c, 'utf-8')
                    else:
                        c = unicode(c)
                    
                    f.write(c)
            elif t and note.get('deleted') and k in self.titlelist:
                dfn = os.path.join(self.config.txt_path, self.titlelist[k])
                if os.path.isfile(dfn):
                    logging.debug('Delete file %s ' % (dfn, ))
                    os.unlink(dfn)
        
        fn = self.helper_key_to_fname(k)
        if not self.config.simplenote_sync and note.get('deleted'):
            if os.path.isfile(fn):
                os.unlink(fn)
        else:
            json.dump(note, open(fn, 'wb'), indent=2)

        # record that we saved this to disc.
        note['savedate'] = time.time()
Example #3
0
    def sync_full(self):
        """Perform a full bi-directional sync with server.
        
        This follows the recipe in the SimpleNote 2.0 API documentation.
        After this, it could be that local keys have been changed, so
        reset any views that you might have.
        """
        
        local_updates = {}
        local_deletes = {}
        now = time.time()

        self.notify_observers('progress:sync_full', utils.KeyValueObject(msg='Starting full sync.'))
        # 1. go through local notes, if anything changed or new, update to server
        for ni,lk in enumerate(self.notes.keys()):
            n = self.notes[lk]
            if not n.get('key') or float(n.get('modifydate')) > float(n.get('syncdate')):
                uret = self.simplenote.update_note(n)
                if uret[1] == 0:
                    # replace n with uret[0]
                    # if this was a new note, our local key is not valid anymore
                    del self.notes[lk]
                    # in either case (new or existing note), save note at assigned key
                    k = uret[0].get('key')
                    # we merge the note we got back (content coud be empty!)
                    n.update(uret[0])
                    # and put it at the new key slot
                    self.notes[k] = n
                    
                    # record that we just synced
                    uret[0]['syncdate'] = now
                    
                    # whatever the case may be, k is now updated
                    local_updates[k] = True
                    if lk != k:
                        # if lk was a different (purely local) key, should be deleted
                        local_deletes[lk] = True
                        
                    self.notify_observers('progress:sync_full', utils.KeyValueObject(msg='Synced modified note %d to server.' % (ni,)))
                        
                else:
                    raise SyncError("Sync step 1 error - Could not update note to server")
             
        # 2. if remote syncnum > local syncnum, update our note; if key is new, add note to local.
        # this gets the FULL note list, even if multiple gets are required
        self.notify_observers('progress:sync_full', utils.KeyValueObject(msg='Retrieving full note list from server, could take a while.'))       
        nl = self.simplenote.get_note_list()
        if nl[1] == 0:
            nl = nl[0]
            self.notify_observers('progress:sync_full', utils.KeyValueObject(msg='Retrieved full note list from server.'))
            
        else:
            raise SyncError('Could not get note list from server.')
        
        server_keys = {}
        lennl = len(nl)
        sync_from_server_errors = 0
        for ni,n in enumerate(nl):
            k = n.get('key')
            server_keys[k] = True
            # this works, only because in phase 1 we rewrite local keys to
            # server keys when we get an updated not back from the server
            if k in self.notes:
                # we already have this
                # check if server n has a newer syncnum than mine
                if int(n.get('syncnum')) > int(self.notes[k].get('syncnum', -1)):
                    # and the server is newer
                    ret = self.simplenote.get_note(k)
                    if ret[1] == 0:
                        self.notes[k].update(ret[0])
                        local_updates[k] = True
                        # in both cases, new or newer note, syncdate is now.
                        self.notes[k]['syncdate'] = now
                        self.notify_observers('progress:sync_full', utils.KeyValueObject(msg='Synced newer note %d (%d) from server.' % (ni,lennl)))

                    else:
                        logging.error('Error syncing newer note %s from server: %s' % (k, ret[0]))
                        sync_from_server_errors+=1

            else:
                # new note
                ret = self.simplenote.get_note(k)
                if ret[1] == 0:
                    self.notes[k] = ret[0]
                    local_updates[k] = True
                    # in both cases, new or newer note, syncdate is now.
                    self.notes[k]['syncdate'] = now
                    self.notify_observers('progress:sync_full', utils.KeyValueObject(msg='Synced new note %d (%d) from server.' % (ni,lennl)))

                else:
                    logging.error('Error syncing new note %s from server: %s' % (k, ret[0]))
                    sync_from_server_errors+=1

        # 3. for each local note not in server index, remove.     
        for lk in self.notes.keys():
            if lk not in server_keys:
                if self.config.notes_as_txt:
                    tfn = os.path.join(self.config.txt_path, utils.get_note_title_file(self.notes[lk]))
                    if os.path.isfile(tfn):
                        os.unlink(tfn)
                del self.notes[lk]
                local_deletes[lk] = True
                
        # sync done, now write changes to db_path
        for uk in local_updates.keys():
            self.helper_save_note(uk, self.notes[uk])
            
        for dk in local_deletes.keys():
            fn = self.helper_key_to_fname(dk)
            if os.path.exists(fn):
                os.unlink(fn)

        self.notify_observers('progress:sync_full', utils.KeyValueObject(msg='Full sync complete.'))

        return sync_from_server_errors
Example #4
0
    def __init__(self, config):
        utils.SubjectMixin.__init__(self)
        
        self.config = config
        
        # create db dir if it does not exist
        if not os.path.exists(config.db_path):
            os.mkdir(config.db_path)
            
        self.db_path = config.db_path

        # create txt Notes dir if it does not exist
        if self.config.notes_as_txt and not os.path.exists(config.txt_path):
            os.mkdir(config.txt_path)
        
        now = time.time()    
        # now read all .json files from disk
        fnlist = glob.glob(self.helper_key_to_fname('*'))
        txtlist = glob.glob(self.config.txt_path + '/*.txt')
        txtlist += glob.glob(self.config.txt_path + '/*.mkdn')

        # removing json files and force full full sync if using text files
        # and none exists and json files are there
        if self.config.notes_as_txt and not txtlist and fnlist:
            logging.debug('Forcing resync: using text notes, first usage')
            for fn in fnlist:
                os.unlink(fn)
            fnlist = []

        self.notes = {}
        if self.config.notes_as_txt:
            self.titlelist = {}

        for fn in fnlist:
            try:
                n = json.load(open(fn, 'rb'))
                if self.config.notes_as_txt:
                    nt = utils.get_note_title_file(n)
                    tfn = os.path.join(self.config.txt_path, nt)
                    if os.path.isfile(tfn):
                        self.titlelist[n.get('key')] = nt
                        txtlist.remove(tfn)
                        if os.path.getmtime(tfn) > os.path.getmtime(fn):
                            logging.debug('Text note was changed: %s' % (fn,))
                            #with open(tfn, mode='r') as f:  
                            with codecs.open(tfn, mode='rb', encoding='utf-8') as f:  
                                c = f.read()

                            n['content'] = c
                            n['modifydate'] = os.path.getmtime(tfn)
                    else:
                        logging.debug('Deleting note : %s' % (fn,))
                        if not self.config.simplenote_sync:
                            os.unlink(fn)
                            continue
                        else:
                            n['deleted'] = 1
                            n['modifydate'] = now

            except ValueError, e:
                logging.error('Error parsing %s: %s' % (fn, str(e)))

            else:
                # we always have a localkey, also when we don't have a note['key'] yet (no sync)
                localkey = os.path.splitext(os.path.basename(fn))[0]
                self.notes[localkey] = n
                # we maintain in memory a timestamp of the last save
                # these notes have just been read, so at this moment
                # they're in sync with the disc.
                n['savedate'] = now
Example #5
0
    def sync_full(self):
        """Perform a full bi-directional sync with server.
        
        This follows the recipe in the SimpleNote 2.0 API documentation.
        After this, it could be that local keys have been changed, so
        reset any views that you might have.
        """

        local_updates = {}
        local_deletes = {}
        now = time.time()

        self.notify_observers('progress:sync_full',
                              utils.KeyValueObject(msg='Starting full sync.'))
        # 1. go through local notes, if anything changed or new, update to server
        for ni, lk in enumerate(self.notes.keys()):
            n = self.notes[lk]
            if not n.get('key') or float(n.get('modifydate')) > float(
                    n.get('syncdate')):
                uret = self.simplenote.update_note(n)
                if uret[1] == 0:
                    # replace n with uret[0]
                    # if this was a new note, our local key is not valid anymore
                    del self.notes[lk]
                    # in either case (new or existing note), save note at assigned key
                    k = uret[0].get('key')
                    # we merge the note we got back (content coud be empty!)
                    n.update(uret[0])
                    # and put it at the new key slot
                    self.notes[k] = n

                    # record that we just synced
                    uret[0]['syncdate'] = now

                    # whatever the case may be, k is now updated
                    local_updates[k] = True
                    if lk != k:
                        # if lk was a different (purely local) key, should be deleted
                        local_deletes[lk] = True

                    self.notify_observers(
                        'progress:sync_full',
                        utils.KeyValueObject(
                            msg='Synced modified note %d to server.' % (ni, )))

                else:
                    raise SyncError(
                        "Sync step 1 error - Could not update note to server")

        # 2. if remote syncnum > local syncnum, update our note; if key is new, add note to local.
        # this gets the FULL note list, even if multiple gets are required
        self.notify_observers(
            'progress:sync_full',
            utils.KeyValueObject(
                msg='Retrieving full note list from server, could take a while.'
            ))
        nl = self.simplenote.get_note_list()
        if nl[1] == 0:
            nl = nl[0]
            self.notify_observers(
                'progress:sync_full',
                utils.KeyValueObject(
                    msg='Retrieved full note list from server.'))

        else:
            raise SyncError('Could not get note list from server.')

        server_keys = {}
        lennl = len(nl)
        sync_from_server_errors = 0
        for ni, n in enumerate(nl):
            k = n.get('key')
            server_keys[k] = True
            # this works, only because in phase 1 we rewrite local keys to
            # server keys when we get an updated not back from the server
            if k in self.notes:
                # we already have this
                # check if server n has a newer syncnum than mine
                if int(n.get('syncnum')) > int(self.notes[k].get(
                        'syncnum', -1)):
                    # and the server is newer
                    ret = self.simplenote.get_note(k)
                    if ret[1] == 0:
                        self.notes[k].update(ret[0])
                        local_updates[k] = True
                        # in both cases, new or newer note, syncdate is now.
                        self.notes[k]['syncdate'] = now
                        self.notify_observers(
                            'progress:sync_full',
                            utils.KeyValueObject(
                                msg='Synced newer note %d (%d) from server.' %
                                (ni, lennl)))

                    else:
                        logging.error(
                            'Error syncing newer note %s from server: %s' %
                            (k, ret[0]))
                        sync_from_server_errors += 1

            else:
                # new note
                ret = self.simplenote.get_note(k)
                if ret[1] == 0:
                    self.notes[k] = ret[0]
                    local_updates[k] = True
                    # in both cases, new or newer note, syncdate is now.
                    self.notes[k]['syncdate'] = now
                    self.notify_observers(
                        'progress:sync_full',
                        utils.KeyValueObject(
                            msg='Synced new note %d (%d) from server.' %
                            (ni, lennl)))

                else:
                    logging.error('Error syncing new note %s from server: %s' %
                                  (k, ret[0]))
                    sync_from_server_errors += 1

        # 3. for each local note not in server index, remove.
        for lk in self.notes.keys():
            if lk not in server_keys:
                if self.config.notes_as_txt:
                    tfn = os.path.join(
                        self.config.txt_path,
                        utils.get_note_title_file(self.notes[lk]))
                    if os.path.isfile(tfn):
                        os.unlink(tfn)
                del self.notes[lk]
                local_deletes[lk] = True

        # sync done, now write changes to db_path
        for uk in local_updates.keys():
            self.helper_save_note(uk, self.notes[uk])

        for dk in local_deletes.keys():
            fn = self.helper_key_to_fname(dk)
            if os.path.exists(fn):
                os.unlink(fn)

        self.notify_observers('progress:sync_full',
                              utils.KeyValueObject(msg='Full sync complete.'))

        return sync_from_server_errors
Example #6
0
    def __init__(self, config):
        utils.SubjectMixin.__init__(self)

        self.config = config

        # create db dir if it does not exist
        if not os.path.exists(config.db_path):
            os.mkdir(config.db_path)

        self.db_path = config.db_path

        # create txt Notes dir if it does not exist
        if self.config.notes_as_txt and not os.path.exists(config.txt_path):
            os.mkdir(config.txt_path)

        now = time.time()
        # now read all .json files from disk
        fnlist = glob.glob(self.helper_key_to_fname('*'))
        txtlist = glob.glob(self.config.txt_path + '/*.txt')
        txtlist += glob.glob(self.config.txt_path + '/*.mkdn')

        # removing json files and force full full sync if using text files
        # and none exists and json files are there
        if self.config.notes_as_txt and not txtlist and fnlist:
            logging.debug('Forcing resync: using text notes, first usage')
            for fn in fnlist:
                os.unlink(fn)
            fnlist = []

        self.notes = {}
        if self.config.notes_as_txt:
            self.titlelist = {}

        for fn in fnlist:
            try:
                n = json.load(open(fn, 'rb'))
                if self.config.notes_as_txt:
                    nt = utils.get_note_title_file(n)
                    tfn = os.path.join(self.config.txt_path, nt)
                    if os.path.isfile(tfn):
                        self.titlelist[n.get('key')] = nt
                        txtlist.remove(tfn)
                        if os.path.getmtime(tfn) > os.path.getmtime(fn):
                            logging.debug('Text note was changed: %s' % (fn, ))
                            #with open(tfn, mode='r') as f:
                            with codecs.open(tfn, mode='rb',
                                             encoding='utf-8') as f:
                                c = f.read()

                            n['content'] = c
                            n['modifydate'] = os.path.getmtime(tfn)
                    else:
                        logging.debug('Deleting note : %s' % (fn, ))
                        if not self.config.simplenote_sync:
                            os.unlink(fn)
                            continue
                        else:
                            n['deleted'] = 1
                            n['modifydate'] = now

            except ValueError, e:
                logging.error('Error parsing %s: %s' % (fn, str(e)))

            else:
                # we always have a localkey, also when we don't have a note['key'] yet (no sync)
                localkey = os.path.splitext(os.path.basename(fn))[0]
                self.notes[localkey] = n
                # we maintain in memory a timestamp of the last save
                # these notes have just been read, so at this moment
                # they're in sync with the disc.
                n['savedate'] = now
Example #7
0
    def sync_full_unthreaded(self):
        """Perform a full bi-directional sync with server.

        After this, it could be that local keys have been changed, so
        reset any views that you might have.
        """

        try:
            self.syncing_lock.acquire()

            self.full_syncing = True
            local_deletes = {}
            now = time.time()

            self.notify_observers(
                'progress:sync_full',
                utils.KeyValueObject(msg='Starting full sync.'))
            # 1. Synchronize notes when it has locally changed.
            #    In this phase, synchronized all notes from client to server.
            for ni, lk in enumerate(self.notes.keys()):
                n = self.notes[lk]
                if Note(n).need_sync_to_server:
                    result = self.update_note_to_server(n)

                    if result.error_object is None:
                        # replace n with result.note.
                        # if this was a new note, our local key is not valid anymore
                        del self.notes[lk]
                        # in either case (new or existing note), save note at assigned key
                        k = result.note.get('key')
                        # we merge the note we got back (content could be empty!)
                        n.update(result.note)
                        # and put it at the new key slot
                        self.notes[k] = n

                        # record that we just synced
                        n['syncdate'] = now

                        # whatever the case may be, k is now updated
                        self.helper_save_note(k, self.notes[k])
                        if lk != k:
                            # if lk was a different (purely local) key, should be deleted
                            local_deletes[lk] = True

                        self.notify_observers(
                            'progress:sync_full',
                            utils.KeyValueObject(
                                msg='Synced modified note %d to server.' %
                                (ni, )))

                    else:
                        key = n.get('key') or lk
                        raise SyncError(
                            "Sync step 1 error - Could not update note {0} to server: {1}"
                            .format(key, str(result.error_object)))

            # 2. Retrieves full note list from server.
            #    In phase 2 to 5, synchronized all notes from server to client.
            self.notify_observers(
                'progress:sync_full',
                utils.KeyValueObject(
                    msg=
                    'Retrieving full note list from server, could take a while.'
                ))
            self.waiting_for_simplenote = True
            nl = self.simplenote.get_note_list()
            self.waiting_for_simplenote = False
            if nl[1] == 0:
                nl = nl[0]
                self.notify_observers(
                    'progress:sync_full',
                    utils.KeyValueObject(
                        msg='Retrieved full note list from server.'))

            else:
                raise SyncError('Could not get note list from server.')

            # 3. Delete local notes not included in full note list.
            server_keys = {}
            for n in nl:
                k = n.get('key')
                server_keys[k] = True

            for lk in list(self.notes.keys()):
                if lk not in server_keys:
                    if self.notes[lk]['syncdate'] == 0:
                        # This note MUST NOT delete because it was created during phase 1 or phase 2.
                        continue

                    if self.config.notes_as_txt:
                        tfn = os.path.join(
                            self.config.txt_path,
                            utils.get_note_title_file(self.notes[lk]))
                        if os.path.isfile(tfn):
                            os.unlink(tfn)
                    del self.notes[lk]
                    local_deletes[lk] = True

            self.notify_observers(
                'progress:sync_full',
                utils.KeyValueObject(msg='Deleted note %d.' %
                                     (len(local_deletes))))

            # 4. Update local notes.
            lennl = len(nl)
            sync_from_server_errors = 0
            for ni, n in enumerate(nl):
                k = n.get('key')
                if k in self.notes:
                    # n is already exists in local.
                    if Note(n).is_newer_than(self.notes[k]):
                        # We must update local note with remote note.
                        err = 0
                        if 'content' not in n:
                            # The content field is missing.  Get all data from server.
                            self.waiting_for_simplenote = True
                            n, err = self.simplenote.get_note(k)
                            self.waiting_for_simplenote = False

                        if err == 0:
                            self.notes[k].update(n)
                            self.notes[k]['syncdate'] = now
                            self.helper_save_note(k, self.notes[k])
                            self.notify_observers(
                                'progress:sync_full',
                                utils.KeyValueObject(
                                    msg='Synced newer note %d (%d) from server.'
                                    % (ni, lennl)))

                        else:
                            logging.error(
                                'Error syncing newer note %s from server: %s' %
                                (k, err))
                            sync_from_server_errors += 1

                else:
                    # n is new note.
                    # We must save it in local.
                    err = 0
                    if 'content' not in n:
                        # The content field is missing.  Get all data from server.
                        self.waiting_for_simplenote = True
                        n, err = self.simplenote.get_note(k)
                        self.waiting_for_simplenote = False

                    if err == 0:
                        self.notes[k] = n
                        self.notes[k][
                            'savedate'] = 0  # never been written to disc
                        self.notes[k]['syncdate'] = now
                        self.helper_save_note(k, self.notes[k])
                        self.notify_observers(
                            'progress:sync_full',
                            utils.KeyValueObject(
                                msg='Synced new note %d (%d) from server.' %
                                (ni, lennl)))

                    else:
                        logging.error(
                            'Error syncing new note %s from server: %s' %
                            (k, err))
                        sync_from_server_errors += 1

            # 5. Clean up local notes.
            for dk in local_deletes.keys():
                fn = self.helper_key_to_fname(dk)
                if os.path.exists(fn):
                    os.unlink(fn)

            self.notify_observers(
                'progress:sync_full',
                utils.KeyValueObject(msg='Full sync complete.'))

            self.full_syncing = False
            return sync_from_server_errors

        finally:
            self.full_syncing = False
            self.syncing_lock.release()
Example #8
0
    def __init__(self, config):
        utils.SubjectMixin.__init__(self)

        self.config = config

        # create db dir if it does not exist
        if not os.path.exists(config.db_path):
            os.mkdir(config.db_path)

        self.db_path = config.db_path

        # create txt Notes dir if it does not exist
        if self.config.notes_as_txt and not os.path.exists(config.txt_path):
            os.mkdir(config.txt_path)

        now = time.time()
        # now read all .json files from disk
        fnlist = glob.glob(self.helper_key_to_fname('*'))
        txtlist = []

        for ext in config.read_txt_extensions.split(','):
            txtlist += glob.glob(
                unicode(self.config.txt_path + '/*.' + ext, 'utf-8'))

        # removing json files and force full full sync if using text files
        # and none exists and json files are there
        if self.config.notes_as_txt and not txtlist and fnlist:
            logging.debug('Forcing resync: using text notes, first usage')
            for fn in fnlist:
                os.unlink(fn)
            fnlist = []

        self.notes = {}
        if self.config.notes_as_txt:
            self.titlelist = {}

        for fn in fnlist:
            try:
                n = json.load(open(fn, 'rb'))
                if self.config.notes_as_txt:
                    nt = utils.get_note_title_file(n)
                    tfn = os.path.join(self.config.txt_path, nt)
                    if os.path.isfile(tfn):
                        self.titlelist[n.get('key')] = nt
                        txtlist.remove(tfn)
                        if os.path.getmtime(tfn) > os.path.getmtime(fn):
                            logging.debug('Text note was changed: %s' % (fn, ))
                            with codecs.open(tfn, mode='rb',
                                             encoding='utf-8') as f:
                                c = f.read()

                            n['content'] = c
                            n['modifydate'] = os.path.getmtime(tfn)
                    else:
                        logging.debug('Deleting note : %s' % (fn, ))
                        if not self.config.simplenote_sync:
                            os.unlink(fn)
                            continue
                        else:
                            n['deleted'] = 1
                            n['modifydate'] = now

            except IOError as e:
                logging.error('NotesDB_init: Error opening %s: %s' %
                              (fn, str(e)))
                raise ReadError('Error opening note file')

            except ValueError as e:
                logging.error('NotesDB_init: Error reading %s: %s' %
                              (fn, str(e)))
                raise ReadError('Error reading note file')

            else:
                # we always have a localkey, also when we don't have a note['key'] yet (no sync)
                localkey = os.path.splitext(os.path.basename(fn))[0]
                self.notes[localkey] = n
                # we maintain in memory a timestamp of the last save
                # these notes have just been read, so at this moment
                # they're in sync with the disc.
                n['savedate'] = now

        if self.config.notes_as_txt:
            for fn in txtlist:
                logging.debug('New text note found : %s' % (fn), )
                tfn = os.path.join(self.config.txt_path, fn)
                try:
                    with codecs.open(tfn, mode='rb', encoding='utf-8') as f:
                        c = f.read()

                except IOError as e:
                    logging.error('NotesDB_init: Error opening %s: %s' %
                                  (fn, str(e)))
                    raise ReadError('Error opening note file')

                except ValueError as e:
                    logging.error('NotesDB_init: Error reading %s: %s' %
                                  (fn, str(e)))
                    raise ReadError('Error reading note file')

                else:
                    nk = self.create_note(c)
                    nn = os.path.splitext(os.path.basename(fn))[0]
                    if nn != utils.get_note_title(self.notes[nk]):
                        self.notes[nk]['content'] = nn + "\n\n" + c

                    os.unlink(tfn)

        # save and sync queue
        self.q_save = Queue()
        self.q_save_res = Queue()

        thread_save = Thread(target=wrap_buggy_function(self.worker_save))
        thread_save.setDaemon(True)
        thread_save.start()

        self.full_syncing = False

        # initialise the simplenote instance we're going to use
        # this does not yet need network access
        if self.config.simplenote_sync:
            self.simplenote = Simplenote(config.sn_username,
                                         config.sn_password)

            # we'll use this to store which notes are currently being synced by
            # the background thread, so we don't add them anew if they're still
            # in progress. This variable is only used by the background thread.
            self.threaded_syncing_keys = {}

            # reading a variable or setting this variable is atomic
            # so sync thread will write to it, main thread will only
            # check it sometimes.
            self.waiting_for_simplenote = False

            self.syncing_lock = Lock()

            self.q_sync = Queue()
            self.q_sync_res = Queue()

            thread_sync = Thread(target=wrap_buggy_function(self.worker_sync))
            thread_sync.setDaemon(True)
            thread_sync.start()