Moved Database class to own file with enhancements.
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 29 Apr 2010 14:37:32 +0000 (16:37 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 29 Apr 2010 14:37:51 +0000 (16:37 +0200)
cappie/__init__.py
cappie/database.py [new file with mode: 0644]

index 1cf1e8d..5e5a10a 100644 (file)
@@ -194,33 +194,3 @@ class Interface(Thread):
        def filter(self):
                return "arp or rarp"
 
-
-class Database(object):
-       def __init__(self, interface):
-               self.interface = interface
-               self.dev = self.interface.dev
-               self.log = self.interface.log
-
-               self.__data = {}
-
-       def open(self):
-               self.log.debug("Opened database for %s" % self.dev)
-
-       def close(self):
-               self.log.debug("Closing database for %s" % self.dev)
-               print self.__data
-
-       def get(self, mac):
-               if self.has(mac):
-                       return self.__data[mac]
-
-       def has(self, mac):
-               return self.__data.has_key(mac)
-
-       def put(self, mac, key, val):
-               if not self.has(mac):
-                       self.__data[mac] = {}
-
-               # TODO Check key for sanity
-
-               self.__data[mac][key] = val
diff --git a/cappie/database.py b/cappie/database.py
new file mode 100644 (file)
index 0000000..df766cb
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+###############################################################################
+#                                                                             #
+# Cappie                                                                      #
+# Copyright (C) 2010 Michael Tremer                                           #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import itertools
+import sqlite3
+
+class Database(object):
+       KEYS = ("EVENTS", "ADDRESSES")
+       _CREATE = ["CREATE TABLE IF NOT EXISTS addresses(mac, address, lastseen);",
+               "CREATE TABLE IF NOT EXISTS changes(address, lastchange);"]
+
+       counter = 0
+
+       def __init__(self, log):
+               self.log = log
+
+               self.__connection = None
+
+       def __del__(self):
+               self.close()
+
+       def open(self):
+               self.log.debug("Opening database")
+               if self.__connection:
+                       self.close()
+               self.__connection = sqlite3.connect("test.db")
+               for statement in self._CREATE:
+                       self.execute(statement)
+
+       def close(self):
+               self.log.debug("Closing database")
+               self.commit()
+               self.__connection.close()
+               self.__connection = None
+
+       def commit(self):
+               self.log.debug("Committing data to database")
+               self.__connection.commit()
+
+       def query(self, query, *parameters):
+               """Returns a row list for the given query and parameters."""
+               cursor = self._cursor()
+               self._execute(cursor, query, parameters)
+               column_names = [d[0] for d in cursor.description]
+               return [Row(itertools.izip(column_names, row)) for row in cursor]
+
+       def get(self, query, *parameters):
+               """Returns the first row returned for the given query."""
+               rows = self.query(query, *parameters)
+               if not rows:
+                       return None
+               elif len(rows) > 1:
+                       raise Exception("Multiple rows returned for Database.get() query")
+               else:
+                       return rows[0]
+
+       def _cursor(self):
+               if not self.__connection:
+                       self.open()
+               return self.__connection.cursor()
+
+       def execute(self, query, *parameters):
+               """Executes the given query, returning the lastrowid from the query."""
+               cursor = self._cursor()
+               self._execute(cursor, query, parameters)
+               return cursor.lastrowid
+
+       def _execute(self, cursor, query, parameters):
+               try:
+                       return cursor.execute(query, parameters)
+               except sqlite3.OperationalError:
+                       self.log.error("Error connecting to database")
+                       self.close()
+                       raise
+
+
+class Row(dict):
+       """A dict that allows for object-like property access syntax."""
+       def __getattr__(self, name):
+               try:
+                       return self[name]
+               except KeyError:
+                       raise AttributeError(name)