app/shell/shell.py
author Daniel Hans <Daniel.M.Hans@gmail.com>
Sat, 14 Nov 2009 23:58:20 +0100
changeset 3092 beeb5d111318
parent 2344 621252e2cc18
permissions -rw-r--r--
Changes in tags are saved to the data store. Also, when a task is created, its arbit tags are stored. Issue 696 fixed.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2335
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     1
#!/usr/bin/python
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     2
#
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     3
# Copyright 2007 Google Inc.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     4
#
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     5
# Licensed under the Apache License, Version 2.0 (the "License");
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     6
# you may not use this file except in compliance with the License.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     7
# You may obtain a copy of the License at
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     8
#
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
     9
#      http://www.apache.org/licenses/LICENSE-2.0
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    10
#
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    11
# Unless required by applicable law or agreed to in writing, software
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    12
# distributed under the License is distributed on an "AS IS" BASIS,
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    14
# See the License for the specific language governing permissions and
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    15
# limitations under the License.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    16
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    17
"""
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    18
An interactive, stateful AJAX shell that runs Python code on the server.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    19
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    20
Part of http://code.google.com/p/google-app-engine-samples/.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    21
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    22
May be run as a standalone app or in an existing app as an admin-only handler.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    23
Can be used for system administration tasks, as an interactive way to try out
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    24
APIs, or as a debugging aid during development.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    25
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    26
The logging, os, sys, db, and users modules are imported automatically.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    27
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    28
Interpreter state is stored in the datastore so that variables, function
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    29
definitions, and other values in the global and local namespaces can be used
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    30
across commands.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    31
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    32
To use the shell in your app, copy shell.py, static/*, and templates/* into
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    33
your app's source directory. Then, copy the URL handlers from app.yaml into
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    34
your app.yaml.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    35
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    36
TODO: unit tests!
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    37
"""
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    38
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    39
import logging
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    40
import new
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    41
import os
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    42
import pickle
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    43
import sys
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    44
import traceback
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    45
import types
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    46
import wsgiref.handlers
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    47
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    48
from django.template import loader
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    49
from google.appengine.api import users
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    50
from google.appengine.ext import db
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    51
from google.appengine.ext import webapp
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    52
from google.appengine.ext.webapp import template
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    53
2344
621252e2cc18 Add missing django.template import to shell.py.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents: 2335
diff changeset
    54
import django.template
2335
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    55
import gae_django
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    56
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    57
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    58
# Set to True if stack traces should be shown in the browser, etc.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    59
_DEBUG = True
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    60
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    61
# The entity kind for shell sessions. Feel free to rename to suit your app.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    62
_SESSION_KIND = '_Shell_Session'
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    63
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    64
# Types that can't be pickled.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    65
UNPICKLABLE_TYPES = (
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    66
  types.ModuleType,
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    67
  types.TypeType,
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    68
  types.ClassType,
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    69
  types.FunctionType,
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    70
  )
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    71
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    72
# Unpicklable statements to seed new sessions with.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    73
INITIAL_UNPICKLABLES = [
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    74
  'import logging',
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    75
  'import os',
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    76
  'import sys',
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    77
  'from google.appengine.ext import db',
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    78
  'from google.appengine.api import users',
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    79
  ]
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    80
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    81
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    82
class ShellSession(db.Model):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    83
  """A shell session. Stores the session's globals.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    84
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    85
  Each session globals is stored in one of two places:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    86
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    87
  If the global is picklable, it's stored in the parallel globals and
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    88
  global_names list properties. (They're parallel lists to work around the
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    89
  unfortunate fact that the datastore can't store dictionaries natively.)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    90
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    91
  If the global is not picklable (e.g. modules, classes, and functions), or if
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    92
  it was created by the same statement that created an unpicklable global,
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    93
  it's not stored directly. Instead, the statement is stored in the
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    94
  unpicklables list property. On each request, before executing the current
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    95
  statement, the unpicklable statements are evaluated to recreate the
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    96
  unpicklable globals.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    97
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    98
  The unpicklable_names property stores all of the names of globals that were
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
    99
  added by unpicklable statements. When we pickle and store the globals after
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   100
  executing a statement, we skip the ones in unpicklable_names.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   101
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   102
  Using Text instead of string is an optimization. We don't query on any of
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   103
  these properties, so they don't need to be indexed.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   104
  """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   105
  global_names = db.ListProperty(db.Text)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   106
  globals = db.ListProperty(db.Blob)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   107
  unpicklable_names = db.ListProperty(db.Text)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   108
  unpicklables = db.ListProperty(db.Text)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   109
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   110
  def set_global(self, name, value):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   111
    """Adds a global, or updates it if it already exists.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   112
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   113
    Also removes the global from the list of unpicklable names.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   114
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   115
    Args:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   116
      name: the name of the global to remove
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   117
      value: any picklable value
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   118
    """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   119
    blob = db.Blob(pickle.dumps(value))
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   120
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   121
    if name in self.global_names:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   122
      index = self.global_names.index(name)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   123
      self.globals[index] = blob
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   124
    else:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   125
      self.global_names.append(db.Text(name))
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   126
      self.globals.append(blob)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   127
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   128
    self.remove_unpicklable_name(name)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   129
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   130
  def remove_global(self, name):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   131
    """Removes a global, if it exists.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   132
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   133
    Args:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   134
      name: string, the name of the global to remove
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   135
    """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   136
    if name in self.global_names:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   137
      index = self.global_names.index(name)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   138
      del self.global_names[index]
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   139
      del self.globals[index]
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   140
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   141
  def globals_dict(self):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   142
    """Returns a dictionary view of the globals.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   143
    """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   144
    return dict((name, pickle.loads(val))
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   145
                for name, val in zip(self.global_names, self.globals))
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   146
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   147
  def add_unpicklable(self, statement, names):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   148
    """Adds a statement and list of names to the unpicklables.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   149
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   150
    Also removes the names from the globals.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   151
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   152
    Args:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   153
      statement: string, the statement that created new unpicklable global(s).
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   154
      names: list of strings; the names of the globals created by the statement.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   155
    """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   156
    self.unpicklables.append(db.Text(statement))
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   157
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   158
    for name in names:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   159
      self.remove_global(name)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   160
      if name not in self.unpicklable_names:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   161
        self.unpicklable_names.append(db.Text(name))
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   162
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   163
  def remove_unpicklable_name(self, name):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   164
    """Removes a name from the list of unpicklable names, if it exists.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   165
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   166
    Args:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   167
      name: string, the name of the unpicklable global to remove
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   168
    """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   169
    if name in self.unpicklable_names:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   170
      self.unpicklable_names.remove(name)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   171
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   172
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   173
class FrontPageHandler(webapp.RequestHandler):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   174
  """Creates a new session and renders the shell.html template.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   175
  """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   176
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   177
  def get(self):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   178
    # set up the session. TODO: garbage collect old shell sessions
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   179
    session_key = self.request.get('session')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   180
    if session_key:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   181
      session = ShellSession.get(session_key)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   182
    else:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   183
      # create a new session
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   184
      session = ShellSession()
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   185
      session.unpicklables = [db.Text(line) for line in INITIAL_UNPICKLABLES]
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   186
      session_key = session.put()
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   187
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   188
    template_file = os.path.join(os.path.dirname(__file__), 'templates',
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   189
                                 'shell.html')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   190
    session_url = '/?session=%s' % session_key
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   191
    vars = { 'server_software': os.environ['SERVER_SOFTWARE'],
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   192
             'python_version': sys.version,
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   193
             'session': str(session_key),
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   194
             'user': users.get_current_user(),
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   195
             'login_url': users.create_login_url(session_url),
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   196
             'logout_url': users.create_logout_url(session_url),
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   197
             }
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   198
    
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   199
    rendered = loader.render_to_string('shell.html', dictionary=vars)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   200
    # rendered = webapp.template.render(template_file, vars, debug=_DEBUG)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   201
    self.response.out.write(rendered)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   202
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   203
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   204
class StatementHandler(webapp.RequestHandler):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   205
  """Evaluates a python statement in a given session and returns the result.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   206
  """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   207
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   208
  def get(self):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   209
    self.response.headers['Content-Type'] = 'text/plain'
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   210
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   211
    # extract the statement to be run
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   212
    statement = self.request.get('statement')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   213
    if not statement:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   214
      return
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   215
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   216
    # the python compiler doesn't like network line endings
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   217
    statement = statement.replace('\r\n', '\n')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   218
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   219
    # add a couple newlines at the end of the statement. this makes
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   220
    # single-line expressions such as 'class Foo: pass' evaluate happily.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   221
    statement += '\n\n'
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   222
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   223
    # log and compile the statement up front
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   224
    try:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   225
      logging.info('Compiling and evaluating:\n%s' % statement)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   226
      compiled = compile(statement, '<string>', 'single')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   227
    except:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   228
      self.response.out.write(traceback.format_exc())
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   229
      return
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   230
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   231
    # create a dedicated module to be used as this statement's __main__
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   232
    statement_module = new.module('__main__')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   233
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   234
    # use this request's __builtin__, since it changes on each request.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   235
    # this is needed for import statements, among other things.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   236
    import __builtin__
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   237
    statement_module.__builtins__ = __builtin__
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   238
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   239
    # load the session from the datastore
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   240
    session = ShellSession.get(self.request.get('session'))
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   241
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   242
    # swap in our custom module for __main__. then unpickle the session
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   243
    # globals, run the statement, and re-pickle the session globals, all
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   244
    # inside it.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   245
    old_main = sys.modules.get('__main__')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   246
    try:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   247
      sys.modules['__main__'] = statement_module
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   248
      statement_module.__name__ = '__main__'
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   249
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   250
      # re-evaluate the unpicklables
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   251
      for code in session.unpicklables:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   252
        exec code in statement_module.__dict__
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   253
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   254
      # re-initialize the globals
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   255
      for name, val in session.globals_dict().items():
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   256
        try:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   257
          statement_module.__dict__[name] = val
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   258
        except:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   259
          msg = 'Dropping %s since it could not be unpickled.\n' % name
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   260
          self.response.out.write(msg)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   261
          logging.warning(msg + traceback.format_exc())
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   262
          session.remove_global(name)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   263
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   264
      # run!
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   265
      old_globals = dict(statement_module.__dict__)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   266
      try:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   267
        old_stdout = sys.stdout
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   268
        old_stderr = sys.stderr
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   269
        try:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   270
          sys.stdout = self.response.out
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   271
          sys.stderr = self.response.out
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   272
          exec compiled in statement_module.__dict__
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   273
        finally:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   274
          sys.stdout = old_stdout
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   275
          sys.stderr = old_stderr
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   276
      except:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   277
        self.response.out.write(traceback.format_exc())
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   278
        return
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   279
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   280
      # extract the new globals that this statement added
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   281
      new_globals = {}
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   282
      for name, val in statement_module.__dict__.items():
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   283
        if name not in old_globals or val != old_globals[name]:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   284
          new_globals[name] = val
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   285
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   286
      if True in [isinstance(val, UNPICKLABLE_TYPES)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   287
                  for val in new_globals.values()]:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   288
        # this statement added an unpicklable global. store the statement and
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   289
        # the names of all of the globals it added in the unpicklables.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   290
        session.add_unpicklable(statement, new_globals.keys())
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   291
        logging.debug('Storing this statement as an unpicklable.')
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   292
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   293
      else:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   294
        # this statement didn't add any unpicklables. pickle and store the
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   295
        # new globals back into the datastore.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   296
        for name, val in new_globals.items():
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   297
          if not name.startswith('__'):
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   298
            session.set_global(name, val)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   299
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   300
    finally:
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   301
      sys.modules['__main__'] = old_main
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   302
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   303
    session.put()
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   304
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   305
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   306
def main():
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   307
  """Main program.
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   308
  """
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   309
  
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   310
  application = webapp.WSGIApplication(
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   311
    [('/admin/shell', FrontPageHandler),
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   312
     ('/admin/shell/shell.do', StatementHandler)], debug=_DEBUG)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   313
  wsgiref.handlers.CGIHandler().run(application)
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   314
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   315
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   316
if __name__ == '__main__':
366e64ecba91 Add web based python shell to Melange.
Pawel Solyga <Pawel.Solyga@gmail.com>
parents:
diff changeset
   317
  main()