Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it work with django 1.7 #91

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions djangoappengine/boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ def find_project_dir():
env_ext['DJANGO_SETTINGS_MODULE'] = 'settings'


def setup_env():
def setup_env(dev_appserver_version=1):
"""Configures GAE environment for command-line apps."""

if dev_appserver_version not in (1, 2):
raise Exception('Invalid dev_appserver_version setting, expected 1 or 2, got %s' % dev_appserver_version)

# Try to import the appengine code from the system path.
try:
from google.appengine.api import apiproxy_stub_map
Expand Down Expand Up @@ -74,10 +77,16 @@ def setup_env():
from dev_appserver import fix_sys_path
except ImportError:
from old_dev_appserver import fix_sys_path

if dev_appserver_version == 2:
# emulate dev_appserver._run_file in devappserver2
from dev_appserver import _PATHS
sys.path = _PATHS._script_to_paths['dev_appserver.py'] + sys.path
fix_sys_path()

setup_project()
from .utils import have_appserver
setup_project(dev_appserver_version)

from djangoappengine.utils import have_appserver
if have_appserver:
# App Engine's threading.local is broken.
setup_threading()
Expand Down Expand Up @@ -125,7 +134,7 @@ def setup_logging():

# Enable logging.
level = logging.DEBUG
from .utils import have_appserver
from djangoappengine.utils import have_appserver
if have_appserver:
# We can't import settings at this point when running a normal
# manage.py command because this module gets imported from
Expand All @@ -135,21 +144,20 @@ def setup_logging():
level = logging.INFO
logging.getLogger().setLevel(level)


def setup_project():
from .utils import have_appserver, on_production_server
def setup_project(dev_appserver_version):
from djangoappengine.utils import have_appserver, on_production_server
if have_appserver:
# This fixes a pwd import bug for os.path.expanduser().
env_ext['HOME'] = PROJECT_DIR

# The dev_appserver creates a sandbox which restricts access to
# certain modules and builtins in order to emulate the production
# environment. Here we get the subprocess module back into the
# dev_appserver sandbox.This module is just too important for
# dev_appserver sandbox. This module is just too important for
# development. Also we add the compiler/parser module back and
# enable https connections (seem to be broken on Windows because
# the _ssl module is disallowed).
if not have_appserver:
if not have_appserver and dev_appserver_version == 1:
try:
from google.appengine.tools import dev_appserver
except ImportError:
Expand Down Expand Up @@ -178,7 +186,7 @@ def setup_project():
logging.warn("Could not patch modules whitelist. the compiler "
"and parser modules will not work and SSL support "
"is disabled.")
elif not on_production_server:
elif not on_production_server and dev_appserver_version == 1:
try:
try:
from google.appengine.tools import dev_appserver
Expand Down
4 changes: 2 additions & 2 deletions djangoappengine/db/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def _value_for_db(self, value, field, field_kind, db_type, lookup):
value = key_from_path(field.model._meta.db_table, value)
except (BadArgumentError, BadValueError,):
raise DatabaseError("Only strings and positive integers "
"may be used as keys on GAE.")
"may be used as keys on GAE. Received %r." % value)

# Store all strings as unicode, use db.Text for longer content.
elif db_type == 'string' or db_type == 'text':
Expand Down Expand Up @@ -342,7 +342,7 @@ def flush(self):
stub_manager.activate_test_stubs(self)
else:
destroy_datastore(get_datastore_paths(self.settings_dict))
stub_manager.setup_local_stubs(self)
stub_manager.reset_stubs(self)


def delete_all_entities():
Expand Down
2 changes: 1 addition & 1 deletion djangoappengine/db/db_settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.conf import settings
from django.utils.importlib import import_module
from importlib import import_module

# TODO: Add autodiscover() and make API more like dbindexer's
# register_index.
Expand Down
48 changes: 36 additions & 12 deletions djangoappengine/db/stubs.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,53 @@ def setup_stubs(self, connection):
if self.active_stubs is not None:
return
if not have_appserver:
self.activate_stubs(connection)

def activate_stubs(self, connection):
try:
from google.appengine.tools import dev_appserver_main
self.setup_local_stubs(connection)
except ImportError:
self.activate_test_stubs(connection)

def reset_stubs(self, connection, datastore_path=None):
if self.active_stubs == 'test':
self.deactivate_test_stubs()
self.activate_test_stubs(connection, datastore_path)

elif self.active_stubs == 'local':
self.setup_local_stubs(connection)

def activate_test_stubs(self, connection):
elif self.active_stubs == 'remote':
self.setup_remote_stubs(connection)

def activate_test_stubs(self, connection, datastore_path=None):
if self.active_stubs == 'test':
return

if self.testbed is None:
from google.appengine.ext.testbed import Testbed
self.testbed = Testbed()

self.testbed.activate()
self.pre_test_stubs = self.active_stubs
self.active_stubs = 'test'

os.environ['APPLICATION_ID'] = 'dev~' + appid
os.environ['HTTP_HOST'] = "%s.appspot.com" % appid

appserver_opts = connection.settings_dict.get('DEV_APPSERVER_OPTIONS', {})
high_replication = appserver_opts.get('high_replication', False)
require_indexes = appserver_opts.get('require_indexes', False)
use_sqlite = appserver_opts.get('use_sqlite', False)

datastore_opts = {'require_indexes': require_indexes}
datastore_opts = {'require_indexes': require_indexes, 'use_sqlite': use_sqlite}

if high_replication:
from google.appengine.datastore import datastore_stub_util
datastore_opts['consistency_policy'] = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=1)

if self.testbed is None:
from google.appengine.ext.testbed import Testbed
self.testbed = Testbed()

self.testbed.activate()
self.pre_test_stubs = self.active_stubs
self.active_stubs = 'test'
self.testbed.init_datastore_v3_stub(root_path=PROJECT_DIR, **datastore_opts)
self.testbed.init_datastore_v3_stub(datastore_file=datastore_path, **datastore_opts)
self.testbed.init_memcache_stub()
self.testbed.init_taskqueue_stub(auto_task_running=True, root_path=PROJECT_DIR)
self.testbed.init_urlfetch_stub()
Expand All @@ -76,6 +97,7 @@ def deactivate_test_stubs(self):
def setup_local_stubs(self, connection):
if self.active_stubs == 'local':
return

from .base import get_datastore_paths
from google.appengine.tools import dev_appserver_main
args = dev_appserver_main.DEFAULT_ARGS.copy()
Expand All @@ -96,8 +118,10 @@ def setup_remote_stubs(self, connection):
if self.active_stubs == 'remote':
return
if not connection.remote_api_path:
from ..utils import appconfig
for handler in appconfig.handlers:
from djangoappengine.utils import appconfig
from google.appengine.api import appinfo
default_module = next(m for m in appconfig.modules if m.module_name == appinfo.DEFAULT_MODULE)
for handler in default_module.handlers:
if handler.script in REMOTE_API_SCRIPTS:
connection.remote_api_path = handler.url.split('(', 1)[0]
break
Expand Down
2 changes: 1 addition & 1 deletion djangoappengine/deferred/handler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Initialize Django.
from djangoappengine import main

from django.utils.importlib import import_module
from importlib import import_module
from django.conf import settings


Expand Down
6 changes: 4 additions & 2 deletions djangoappengine/mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ def _copy_message(self, message):
attachments = []
for attachment in message.attachments:
if isinstance(attachment, MIMEBase):
attachments.append((attachment.get_filename(),
attachment.get_payload(decode=True)))
attachments.append(aeemail.Attachment(
attachment.get_filename() or '',
attachment.get_payload(decode=True),
content_id = attachment.get('content-id')))
else:
attachments.append((attachment[0], attachment[1]))
gmsg.attachments = attachments
Expand Down
57 changes: 34 additions & 23 deletions djangoappengine/main/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@
sys.path.remove(project_dir)
sys.path.insert(0, project_dir)

for path in sys.path[:]:
if path != project_dir and os.path.isdir(os.path.join(path, 'django')):
sys.path.remove(path)
break

# Remove the standard version of Django.
if 'django' in sys.modules and sys.modules['django'].VERSION < (1, 2):
for k in [k for k in sys.modules
if k.startswith('django.') or k == 'django']:
del sys.modules[k]


from django.conf import settings
from django.core import signals
from django.core.wsgi import get_wsgi_application
from google.appengine.ext.webapp.util import run_wsgi_app

from djangoappengine.utils import on_production_server

from djangoappengine.boot import setup_env
setup_env()
setup_env(settings.DEV_APPSERVER_VERSION)


def validate_models():
Expand All @@ -34,45 +37,53 @@ def validate_models():
model valdidation here to ensure it is run every time the code
changes.
"""

import logging
from django.core.management.validation import get_validation_errors
logging.info("Validating models...")
error_text = None

try:
from cStringIO import StringIO
from django.core.management.validation import get_validation_errors
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

s = StringIO()
num_errors = get_validation_errors(s, None)

if num_errors:
s.seek(0)
error_text = s.read()

except ImportError:
from StringIO import StringIO
import django
from django.core.checks.model_checks import check_all_models

logging.info("Validating models...")
django.setup()
errors = check_all_models()

s = StringIO()
num_errors = get_validation_errors(s, None)
if errors:
error_text = "\n".join(errors)

if num_errors:
s.seek(0)
error_text = s.read()
if error_text:
logging.critical("One or more models did not validate:\n%s" %
error_text)
else:
logging.info("All models validated.")

from djangoappengine.utils import on_production_server
if not on_production_server:
validate_models()

from django.core.handlers.wsgi import WSGIHandler
from google.appengine.ext.webapp.util import run_wsgi_app
from django.conf import settings


def log_traceback(*args, **kwargs):
import logging
logging.exception("Exception in request:")

from django.core import signals
signals.got_request_exception.connect(log_traceback)


# Create a Django application for WSGI.
application = WSGIHandler()
application = get_wsgi_application()

# Add the staticfiles handler if necessary.
if settings.DEBUG and 'django.contrib.staticfiles' in settings.INSTALLED_APPS:
Expand Down
2 changes: 0 additions & 2 deletions djangoappengine/management/commands/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ def run_appcfg(argv):

new_args = argv[:]
new_args[1] = 'update'
if appconfig.runtime != 'python':
new_args.insert(1, '-R')
new_args.append(PROJECT_DIR)
syncdb = True
if '--nosyncdb' in new_args:
Expand Down
Loading