app/shell/shell.py
author Mario Ferraro <fadinlight@gmail.com>
Sun, 15 Nov 2009 22:12:20 +0100
changeset 3093 d1be59b6b627
parent 2344 621252e2cc18
permissions -rw-r--r--
GMaps related JS changed to use new google namespace. Google is going to change permanently in the future the way to load its services, so better stay safe. Also this commit shows uses of the new melange.js module. Fixes Issue 634.
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()