summaryrefslogtreecommitdiffstats
path: root/appengine_django/db
diff options
context:
space:
mode:
Diffstat (limited to 'appengine_django/db')
-rwxr-xr-xappengine_django/db/__init__.py20
-rw-r--r--appengine_django/db/__init__.pycbin0 -> 183 bytes
-rwxr-xr-xappengine_django/db/base.py150
-rw-r--r--appengine_django/db/base.pycbin0 -> 6210 bytes
-rwxr-xr-xappengine_django/db/creation.py37
-rw-r--r--appengine_django/db/creation.pycbin0 -> 1288 bytes
6 files changed, 207 insertions, 0 deletions
diff --git a/appengine_django/db/__init__.py b/appengine_django/db/__init__.py
new file mode 100755
index 0000000..619bc78
--- /dev/null
+++ b/appengine_django/db/__init__.py
@@ -0,0 +1,20 @@
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Explicitly set the name of this package to "appengine".
+#
+# The rationale for this is so that Django can refer to the database as
+# "appengine" even though at a filesystem level it appears as the "db" package
+# within the appengine_django package.
+__name__ = "appengine"
diff --git a/appengine_django/db/__init__.pyc b/appengine_django/db/__init__.pyc
new file mode 100644
index 0000000..879eeaa
--- /dev/null
+++ b/appengine_django/db/__init__.pyc
Binary files differ
diff --git a/appengine_django/db/base.py b/appengine_django/db/base.py
new file mode 100755
index 0000000..8a90182
--- /dev/null
+++ b/appengine_django/db/base.py
@@ -0,0 +1,150 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This module looks after initialising the appengine api stubs."""
+
+import logging
+import os
+
+from appengine_django import appid
+from appengine_django import have_appserver
+from appengine_django.db.creation import DatabaseCreation
+
+
+from django.db.backends import BaseDatabaseWrapper
+from django.db.backends import BaseDatabaseFeatures
+from django.db.backends import BaseDatabaseOperations
+
+
+def get_datastore_paths():
+ """Returns a tuple with the path to the datastore and history file.
+
+ The datastore is stored in the same location as dev_appserver uses by
+ default, but the name is altered to be unique to this project so multiple
+ Django projects can be developed on the same machine in parallel.
+
+ Returns:
+ (datastore_path, history_path)
+ """
+ from google.appengine.tools import dev_appserver_main
+ datastore_path = dev_appserver_main.DEFAULT_ARGS['datastore_path']
+ history_path = dev_appserver_main.DEFAULT_ARGS['history_path']
+ datastore_path = datastore_path.replace("dev_appserver", "django_%s" % appid)
+ history_path = history_path.replace("dev_appserver", "django_%s" % appid)
+ return datastore_path, history_path
+
+
+def get_test_datastore_paths(inmemory=True):
+ """Returns a tuple with the path to the test datastore and history file.
+
+ If inmemory is true, (None, None) is returned to request an in-memory
+ datastore. If inmemory is false the path returned will be similar to the path
+ returned by get_datastore_paths but with a different name.
+
+ Returns:
+ (datastore_path, history_path)
+ """
+ if inmemory:
+ return None, None
+ datastore_path, history_path = get_datastore_paths()
+ datastore_path = datastore_path.replace("datastore", "testdatastore")
+ history_path = history_path.replace("datastore", "testdatastore")
+ return datastore_path, history_path
+
+
+def destroy_datastore(datastore_path, history_path):
+ """Destroys the appengine datastore at the specified paths."""
+ for path in [datastore_path, history_path]:
+ if not path: continue
+ try:
+ os.remove(path)
+ except OSError, e:
+ if e.errno != 2:
+ logging.error("Failed to clear datastore: %s" % e)
+
+
+class DatabaseError(Exception):
+ """Stub class for database errors. Required by Django"""
+ pass
+
+
+class IntegrityError(Exception):
+ """Stub class for database integrity errors. Required by Django"""
+ pass
+
+
+class DatabaseFeatures(BaseDatabaseFeatures):
+ """Stub class to provide the feaures member expected by Django"""
+ pass
+
+
+class DatabaseOperations(BaseDatabaseOperations):
+ """Stub class to provide the options member expected by Django"""
+ pass
+
+
+class DatabaseWrapper(BaseDatabaseWrapper):
+ """App Engine database definition for Django.
+
+ This "database" backend does not support any of the standard backend
+ operations. The only task that it performs is to setup the api stubs required
+ by the appengine libraries if they have not already been initialised by an
+ appserver.
+ """
+
+ def __init__(self, *args, **kwargs):
+ super(DatabaseWrapper, self).__init__(*args, **kwargs)
+ self.features = DatabaseFeatures()
+ self.ops = DatabaseOperations()
+ self.creation = DatabaseCreation(self)
+ self.use_test_datastore = kwargs.get("use_test_datastore", False)
+ self.test_datastore_inmemory = kwargs.get("test_datastore_inmemory", True)
+ if have_appserver:
+ return
+ self._setup_stubs()
+
+ def _get_paths(self):
+ if self.use_test_datastore:
+ return get_test_datastore_paths(self.test_datastore_inmemory)
+ else:
+ return get_datastore_paths()
+
+ def _setup_stubs(self):
+ # If this code is being run without an appserver (eg. via a django
+ # commandline flag) then setup a default stub environment.
+ from google.appengine.tools import dev_appserver_main
+ args = dev_appserver_main.DEFAULT_ARGS.copy()
+ args['datastore_path'], args['history_path'] = self._get_paths()
+ from google.appengine.tools import dev_appserver
+ dev_appserver.SetupStubs(appid, **args)
+ if self.use_test_datastore:
+ logging.debug("Configured API stubs for the test datastore")
+ else:
+ logging.debug("Configured API stubs for the development datastore")
+
+ def flush(self):
+ """Helper function to remove the current datastore and re-open the stubs"""
+ destroy_datastore(*self._get_paths())
+ self._setup_stubs()
+
+ def close(self):
+ pass
+
+ def _commit(self):
+ pass
+
+ def cursor(self, *args):
+ pass
diff --git a/appengine_django/db/base.pyc b/appengine_django/db/base.pyc
new file mode 100644
index 0000000..8699add
--- /dev/null
+++ b/appengine_django/db/base.pyc
Binary files differ
diff --git a/appengine_django/db/creation.py b/appengine_django/db/creation.py
new file mode 100755
index 0000000..74e3048
--- /dev/null
+++ b/appengine_django/db/creation.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+from django.db.backends.creation import BaseDatabaseCreation
+
+
+class DatabaseCreation(BaseDatabaseCreation):
+
+ def create_test_db(self, *args, **kw):
+ """Destroys the test datastore. A new store will be recreated on demand"""
+ self.destroy_test_db()
+ self.connection.use_test_datastore = True
+ self.connection.flush()
+
+
+ def destroy_test_db(self, *args, **kw):
+ """Destroys the test datastore files."""
+ from appengine_django.db.base import destroy_datastore
+ from appengine_django.db.base import get_test_datastore_paths
+ destroy_datastore(*get_test_datastore_paths())
+ logging.debug("Destroyed test datastore")
diff --git a/appengine_django/db/creation.pyc b/appengine_django/db/creation.pyc
new file mode 100644
index 0000000..2055fb6
--- /dev/null
+++ b/appengine_django/db/creation.pyc
Binary files differ