commit aa15db9e5ab8f78bf22228fb060fbc5ed1e0d8a2
Author: dsorber <david.sorber@gmail.com>
Date:   Sat Jul 12 18:36:00 2014 -0400

    First commit for the bookmark library project! Hopefully many more to come. Starting the bookmark class.

diff --git a/software/bookmark_library/lib/bookmark.py b/software/bookmark_library/lib/bookmark.py
new file mode 100644
index 0000000..b7faaa9
--- /dev/null
+++ b/software/bookmark_library/lib/bookmark.py
@@ -0,0 +1,123 @@
+import sqlite3
+
+
+DB_PATH = 'bookmarks.db'
+
+SQL_INSERT_BOOKMARK = "INSERT INTO bookmarks VALUES (?,?,?,?,?,?,?,?)"
+SQL_UPDATE_BOOKMARK = "UPDATE bookmarks SET {:s} WHERE id=?"
+
+class DBConnectionError(Exception):
+    
+    def __init__(self, value):
+        self.value = value
+        
+    def __str__(self, value):
+        return repr(self.value)
+        
+
+class Bookmark(object):
+    
+    def __init__(self, db_conn, id=None, url=None):
+        
+        # Make sure the DB connection is valid before doing anything 
+        # else
+        if not db_conn:
+            raise DBConnectionError('Invalid database connection object!')
+        
+        # Setup internal parameters
+        self._db_conn = db_conn
+        
+        # Setup defaut object data attributes
+        self.id = id
+        self.url = url
+        self.title = ''
+        self.description = ''
+        self.times_visited = 0
+        self.last_visited = 0
+        self.last_reachable = 0
+        self.deleted = False
+        
+        # This dict MUST appear after the data attributes, it is used to 
+        # record which data attributes are dirty
+        self._dirty = {'url': False,
+                       'title': False,
+                       'description': False,
+                       'times_visited': False,
+                       'last_visited': False,
+                       'last_reachable': False,
+                       'deleted': False}        
+    
+    def __del__(self):
+        """ Save any changes to a record before the object is destroyed. """
+        # Check if the record is dirty
+        if self.record_dirty:
+            if self.id:
+                # Update existing record
+                pass
+            else:
+                # Insert new record
+                self._db_insert()
+    
+    def __setattr__(self, name, value):
+        """ Customize setting data attributes so we can tell which ones
+        are dirty.
+        """
+        
+        # Check if the attr is a data attribute then check if the value has 
+        # changed. If so, mark the attribute as dirty
+        if hasattr(self, '_dirty'):
+            if name in self._dirty and getattr(self, name) != value:
+                self._dirty[name] = True
+                
+        # Set the attribute value using the super class's __setattr__ to avoid
+        # infinite recursion (recursion joke here)
+        super(Bookmark, self).__setattr__(name, value)
+        
+    def _db_insert(self):
+        """ Insert a new bookmark 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,
+                  self.deleted and '1' or '0')
+        db.execute(SQL_INSERT_BOOKMARK, values)
+        self._db_conn.commit()
+        
+        # Reset dirty flags
+        for key in self._dirty.keys():
+            self._dirty[key] = False
+            
+    def _db_update(self):
+        """ Update an exisitng bookmark row in the database. """
+        values = []
+        sets = []
+        
+        # Find dirty data attributes for updating
+        for key in self._dirty.keys():
+            if self._dirty[key] == False:
+                sets.append('{:s}=?'.format(key))
+                values.append(getattr(self, key))
+                
+        if not value or not sets:
+            return
+        
+        # Add the record id as the last value
+        values.append(self.id)
+        
+        # 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)
+        self._db_conn.commit()
+        
+        print('Updated record')
+        
+        # Reset dirty flags
+        for key in self._dirty.keys():
+            self._dirty[key] = False
+    
+    @property
+    def record_dirty(self):
+        """ Check if any data attributes are dirty, which indicates the record 
+        is dirty.
+        """
+        return any([val for key, val in self._dirty.items()])
diff --git a/software/bookmark_library/lib/bookmarks.db b/software/bookmark_library/lib/bookmarks.db
new file mode 100644
index 0000000..608e918
Binary files /dev/null and b/software/bookmark_library/lib/bookmarks.db differ
diff --git a/software/bookmark_library/lib/tag.py b/software/bookmark_library/lib/tag.py
new file mode 100644
index 0000000..e69de29
diff --git a/software/bookmark_library/tests/script b/software/bookmark_library/tests/script
new file mode 100644
index 0000000..26d8c69
--- /dev/null
+++ b/software/bookmark_library/tests/script
@@ -0,0 +1,7 @@
+import sqlite3
+conn = sqlite3.connect('bookmarks.db')
+from bookmark import Bookmark
+d = Bookmark(conn)
+d.url = 'http://www.google.com'
+d.title = 'Google'
+d.record_dirty
