commit 655be0cd0d5c140f80e9ca209988882c9937e308
Author: dsorber <david.sorber@gmail.com>
Date:   Sat Jul 12 23:10:40 2014 -0400

    Added selection and debugged updating of bookmark records. Also added suggest_title and is_reachable methods.

diff --git a/software/bookmark_library/lib/bookmark.py b/software/bookmark_library/lib/bookmark.py
index b7faaa9..9dfb26f 100644
--- a/software/bookmark_library/lib/bookmark.py
+++ b/software/bookmark_library/lib/bookmark.py
@@ -1,11 +1,26 @@
+import re
+from urllib.request import urlopen
+
 import sqlite3
 
 
 DB_PATH = 'bookmarks.db'
 
+SQL_SELECT_BOOKMARK = "SELECT * FROM bookmarks WHERE id=?"
 SQL_INSERT_BOOKMARK = "INSERT INTO bookmarks VALUES (?,?,?,?,?,?,?,?)"
 SQL_UPDATE_BOOKMARK = "UPDATE bookmarks SET {:s} WHERE id=?"
 
+HTTP_OKAY = 200
+
+class BookmarkNotFoundError(Exception):
+    
+    def __init__(self, value):
+        self.value = value
+        
+    def __str__(self, value):
+        return repr(self.value)
+        
+
 class DBConnectionError(Exception):
     
     def __init__(self, value):
@@ -26,6 +41,7 @@ class Bookmark(object):
         
         # Setup internal parameters
         self._db_conn = db_conn
+        self._content = None
         
         # Setup defaut object data attributes
         self.id = id
@@ -37,7 +53,29 @@ class Bookmark(object):
         self.last_reachable = 0
         self.deleted = False
         
-        # This dict MUST appear after the data attributes, it is used to 
+        # Retrieve an existing bookmark
+        if self.id:
+            db = self._db_conn.cursor()
+            db.execute(SQL_SELECT_BOOKMARK, (self.id,))
+            row = db.fetchone()
+            
+            # Check to see if a record was found
+            if not row:
+                raise BookmarkNotFoundError(self.id)
+            
+            # Assign data attributes
+            self.url = row[1]
+            self.title = row[2]
+            self.description = row[3]
+            self.times_visited = int(row[4])
+            self.last_visited = row[5]
+            self.last_reachable = row[6]
+            if int(row[7]) == 0:
+                self.deleted = False
+            else:
+                self.deleted = True
+        
+        # This dict MUST appear *after* the data attributes, it is used to 
         # record which data attributes are dirty
         self._dirty = {'url': False,
                        'title': False,
@@ -48,14 +86,20 @@ class Bookmark(object):
                        'deleted': False}        
     
     def __del__(self):
-        """ Save any changes to a record before the object is destroyed. """
+        """ Automatically save any changes to a record before the object is 
+        destroyed. 
+        """
+        self.save()
+    
+    def save(self):
+        """ Save any changes to a bookmark record if it is dirty. """
         # Check if the record is dirty
         if self.record_dirty:
             if self.id:
-                # Update existing record
-                pass
+                # Update existing bookmark record
+                self._db_update()
             else:
-                # Insert new record
+                # Insert new bookmark record
                 self._db_insert()
     
     def __setattr__(self, name, value):
@@ -74,7 +118,7 @@ class Bookmark(object):
         super(Bookmark, self).__setattr__(name, value)
         
     def _db_insert(self):
-        """ Insert a new bookmark into the database. """
+        """ Insert a new bookmark record into the database. """
         db = self._db_conn.cursor()
         values = (0, self.url, self.title, self.description, 
                   self.times_visited, self.last_visited, self.last_reachable,
@@ -87,17 +131,17 @@ class Bookmark(object):
             self._dirty[key] = False
             
     def _db_update(self):
-        """ Update an exisitng bookmark row in the database. """
+        """ Update an exisitng bookmark record in the database. """
         values = []
         sets = []
         
         # Find dirty data attributes for updating
         for key in self._dirty.keys():
-            if self._dirty[key] == False:
+            if self._dirty[key] == True:
                 sets.append('{:s}=?'.format(key))
                 values.append(getattr(self, key))
-                
-        if not value or not sets:
+        
+        if not values or not sets:
             return
         
         # Add the record id as the last value
@@ -106,11 +150,9 @@ class Bookmark(object):
         # Build full SQL statement then execute it
         sql = SQL_UPDATE_BOOKMARK.format(','.join(sets))
         db = self._db_conn.cursor()
-        db.execute(SQL_INSERT_BOOKMARK, values)
+        db.execute(sql, values)
         self._db_conn.commit()
         
-        print('Updated record')
-        
         # Reset dirty flags
         for key in self._dirty.keys():
             self._dirty[key] = False
@@ -121,3 +163,32 @@ class Bookmark(object):
         is dirty.
         """
         return any([val for key, val in self._dirty.items()])
+        
+    def _get_content(self):
+        """ Read the page and get its raw page HTML content. """
+        if self.url:
+            response = urlopen(self.url)
+            if response.getcode() == HTTP_OKAY:
+                self._content = response.read().decode('utf-8')
+        
+    def suggest_title(self):
+        """ Return the contents of the page's <title> tag as a title suggestion
+        """
+        if self.url and not self._content:
+            self._get_content()
+        
+        try:
+            title = re.search('<title>(.+)</title>', self._content).group(1)
+        except IndexError:
+            title = None
+        return title
+        
+    def is_reachable(self):
+        """ Check if the page is reachable. """
+        if self.url:
+            response = urlopen(self.url)
+            if response.getcode() == HTTP_OKAY:
+                return True
+        return False
+        
+            
diff --git a/software/bookmark_library/lib/bookmarks.db b/software/bookmark_library/lib/bookmarks.db
index 608e918..71cb32f 100644
Binary files a/software/bookmark_library/lib/bookmarks.db and b/software/bookmark_library/lib/bookmarks.db differ
