Commits

Vladimir Mihailenco committed 27c2bc1 Merge

Merge with master head

Comments (0)

Files changed (10)

appstats/__init__.py

Empty file added.
+# Initialize Django
+from djangoappengine.main import main
+
+from google.appengine.ext.appstats.ui import main
+
+if __name__ == '__main__':
+    main()
 import sys
 
 PROJECT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+DATA_ROOT = os.path.join(PROJECT_DIR, '.gaedata')
 
 # Overrides for os.environ
 env_ext = {'DJANGO_SETTINGS_MODULE': 'settings'}
     if have_appserver:
         # App Engine's threading.local is broken
         setup_threading()
+    elif not os.path.exists(DATA_ROOT):
+        os.mkdir(DATA_ROOT)
     setup_logging()
 
     if not have_appserver:
 from ..utils import appid, have_appserver, on_production_server
+from ..boot import DATA_ROOT
 from .creation import DatabaseCreation
 from django.db.backends.util import format_number
 from djangotoolbox.db.base import NonrelDatabaseFeatures, \
 
 def auth_func():
     import getpass
-    return raw_input('Login via Google Account: '), getpass.getpass('Password: ')
+    return raw_input('Login via Google Account (see note above if login fails): '), getpass.getpass('Password: ')
 
 def rpc_server_factory(*args, ** kwargs):
     from google.appengine.tools import appengine_rpc
     """
     from google.appengine.tools import dev_appserver_main
     datastore_path = options.get('datastore_path',
-                                 dev_appserver_main.DEFAULT_ARGS['datastore_path'].replace(
-                                 'dev_appserver', 'django_%s' % appid))
+                                 os.path.join(DATA_ROOT, 'datastore'))
     blobstore_path = options.get('blobstore_path',
-                                 dev_appserver_main.DEFAULT_ARGS['blobstore_path'].replace(
-                                 'dev_appserver', 'django_%s' % appid))
+                                 os.path.join(DATA_ROOT, 'blobstore'))
     history_path = options.get('history_path',
-                               dev_appserver_main.DEFAULT_ARGS['history_path'].replace(
-                               'dev_appserver', 'django_%s' % appid))
+                               os.path.join(DATA_ROOT, 'history'))
     return datastore_path, blobstore_path, history_path
 
 def get_test_datastore_paths(inmemory=True):
             from ..utils import appconfig
             for handler in appconfig.handlers:
                 if handler.script == REMOTE_API_SCRIPT:
-                    self.remote_api_path = handler.url
+                    self.remote_api_path = handler.url.split('(', 1)[0]
                     break
         self.remote = True
         remote_url = 'https://%s.appspot.com%s' % (self.remote_app_id,
         logging.info('Setting up remote_api for "%s" at %s' %
                      (self.remote_app_id, remote_url))
         if not have_appserver:
-            print 'Connecting to remote_api handler'
+            print('Connecting to remote_api handler.\n\n'
+                  'IMPORTANT: Check your login method settings in the '
+                  'App Engine Dashboard if you have problems logging in. '
+                  'Login is only supported for Google Accounts.\n')
         from google.appengine.ext.remote_api import remote_api_stub
         remote_api_stub.ConfigureRemoteApi(self.remote_app_id,
             self.remote_api_path, auth_func, secure=self.secure_remote_api,
                 raise URLError("%s\n"
                                "Couldn't reach remote_api handler at %s.\n"
                                "Make sure you've deployed your project and "
-                               "installed a remote_api handler in app.yaml."
+                               "installed a remote_api handler in app.yaml. "
+                               "Note that login is only supported for "
+                               "Google Accounts. Make sure you've configured "
+                               "the correct authentication method in the "
+                               "App Engine Dashboard."
                                % (e, remote_url))
         logging.info('Now using the remote datastore for "%s" at %s' %
                      (self.remote_app_id, remote_url))
 from google.appengine.datastore.datastore_query import Cursor
 
+class CursorQueryMixin(object):
+    def clone(self, *args, **kwargs):
+        kwargs['_gae_cursor'] = getattr(self, '_gae_cursor', None)
+        kwargs['_gae_start_cursor'] = getattr(self, '_gae_start_cursor', None)
+        kwargs['_gae_end_cursor'] = getattr(self, '_gae_end_cursor', None)
+        return super(CursorQueryMixin, self).clone(*args, **kwargs)
+
 def get_cursor(queryset):
     # Evaluate QuerySet
     len(queryset)
     return Cursor.to_websafe_string(cursor)
 
 def set_cursor(queryset, start=None, end=None):
+    queryset = queryset.all()
+    class CursorQuery(CursorQueryMixin, queryset.query.__class__):
+        pass
+    queryset.query = queryset.query.clone(klass=CursorQuery)
     if start is not None:
         start = Cursor.from_websafe_string(start)
-        queryset.query._gae_start_cursor = start
+    queryset.query._gae_start_cursor = start
     if end is not None:
         end = Cursor.from_websafe_string(end)
-        queryset.query._gae_end_cursor = end
+    queryset.query._gae_end_cursor = end
     # Evaluate QuerySet
-    len(queryset)
+    return queryset

deferred/handler.py

-import os, sys
+# Initialize Django
+from djangoappengine.main.main import make_profileable
 
-parent_dir = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
-if parent_dir not in sys.path:
-    sys.path.insert(0, parent_dir)
+from google.appengine.ext.deferred.handler import main
 
-# Initialize Django
-from djangoappengine.main import main as gaemain
+main = make_profileable(main)
 
-# Import and run the actual handler
-from google.appengine.ext.deferred.handler import main
 if __name__ == '__main__':
     main()
     # Run the WSGI CGI handler with that application.
     run_wsgi_app(application)
 
-def profile_main():
+def profile_main(func):
     import logging, cProfile, pstats, random, StringIO
     only_forced_profile = getattr(settings, 'ONLY_FORCED_PROFILE', False)
     profile_percentage = getattr(settings, 'PROFILE_PERCENTAGE', None)
                 'profile=forced' not in os.environ.get('QUERY_STRING')) or \
             (not only_forced_profile and profile_percentage and
                 float(profile_percentage) / 100.0 <= random.random()):
-        return real_main()
+        return func()
 
     prof = cProfile.Profile()
-    prof = prof.runctx('real_main()', globals(), locals())
+    prof = prof.runctx('func()', globals(), locals())
     stream = StringIO.StringIO()
     stats = pstats.Stats(prof, stream=stream)
     sort_by = getattr(settings, 'SORT_PROFILE_RESULTS_BY', 'time')
         stats.print_callers()
     logging.info('Profile data:\n%s', stream.getvalue())
 
-main = getattr(settings, 'ENABLE_PROFILER', False) and profile_main or real_main
+def make_profileable(func):
+    if getattr(settings, 'ENABLE_PROFILER', False):
+        return lambda: profile_main(func)
+    return func
+
+main = make_profileable(real_main)
 
 if __name__ == '__main__':
     main()

management/commands/deploy.py

 # CHANGED: show warning if profiler is enabled, so you don't mistakenly upload
 # with non-production settings. Also, added --nosyncdb switch.
 
+from ...boot import PROJECT_DIR
 from django.conf import settings
 from django.core.management import call_command
 from django.core.management.base import BaseCommand
 
     new_args = argv[:]
     new_args[1] = 'update'
-    new_args.append('.')
+    new_args.append(PROJECT_DIR)
     syncdb = True
     if '--nosyncdb' in new_args:
         syncdb = False

management/commands/runserver.py

 
 
 import logging
-import os
 import sys
 
 from django.db import connections
+from ...boot import PROJECT_DIR
 from ...db.base import DatabaseWrapper
 from django.core.management.base import BaseCommand
 from django.core.exceptions import ImproperlyConfigured
     logging.getLogger().setLevel(logging.INFO)
 
     # Append the current working directory to the arguments.
-    dev_appserver_main.main([progname] + args + [os.getcwdu()])
+    dev_appserver_main.main([progname] + args + [PROJECT_DIR])
 
 class Command(BaseCommand):
     """Overrides the default Django runserver command.
         for item in results:
             query = FieldsWithOptionsModel.objects.all()[:1]
             if cursor is not None:
-                set_cursor(query, cursor)
+                query = set_cursor(query, cursor)
             next = query[0]
             self.assertEqual(next.pk, item.pk)
             cursor = get_cursor(query)
-        query = FieldsWithOptionsModel.objects.all()[:1]
-        set_cursor(query, cursor)
-        self.assertEqual(list(query), [])
+        query = set_cursor(FieldsWithOptionsModel.objects.all(), cursor)
+        self.assertEqual(list(query[:1]), [])
 
     def test_Q_objects(self):
         self.assertEquals([entity.email for entity in