# HG changeset patch # User amit@thunder # Date 1274115839 -19800 # Node ID 0b061d58aea3c9d6550bf492d893f5415ec80a30 First commit to Fossee of testapp has the basic Pykata framework on django with some specific changes to Problems model and some views to suit an exam like system diff -r 000000000000 -r 0b061d58aea3 testappproj/.database.sqlite3 Binary file testappproj/.database.sqlite3 has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/__init__.py diff -r 000000000000 -r 0b061d58aea3 testappproj/__init__.pyc Binary file testappproj/__init__.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/error_file diff -r 000000000000 -r 0b061d58aea3 testappproj/manage.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/manage.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff -r 000000000000 -r 0b061d58aea3 testappproj/settings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/settings.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,95 @@ +import os +import sys +# Django settings for testappproj project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +ROOT = os.path.dirname(sys.modules[__name__].__file__) + +DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. +DATABASE_NAME = '.database.sqlite3' # Or path to database file if using sqlite3. +DATABASE_USER = '' # Not used with sqlite3. +DATABASE_PASSWORD = '' # Not used with sqlite3. +DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. +DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 's2er59!c4*5-bi5tz)j-#=ngw^p&z8&w-#ft&+sv!_^0m#88pd' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +) + + +# Our own Auth Profile Module so that we can change django registration +AUTH_PROFILE_MODULE="testapp.Test_User" + +#SETTINGS related to registration +ACCOUNT_ACTIVATION_DAYS=1 + + +ROOT_URLCONF = 'testappproj.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join(ROOT, 'templates') +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.admin', + 'testappproj.testapp', + 'registration', +) diff -r 000000000000 -r 0b061d58aea3 testappproj/settings.py.pykata --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/settings.py.pykata Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,43 @@ +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Minimal Django settings.""" + +import os + + +DEBUG=True + +#APPEND_SLASH = False +# DEBUG = os.environ['SERVER_SOFTWARE'].startswith('Dev') +INSTALLED_APPS = ( + 'testapp', + ) +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.middleware.http.ConditionalGetMiddleware', +) +ROOT_URLCONF = 'urls' +TEMPLATE_CONTEXT_PROCESSORS = () +TEMPLATE_DEBUG = DEBUG +TEMPLATE_DIRS = ( + os.path.join(os.path.dirname(__file__), 'templates'), + ) +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + ) +FILE_UPLOAD_HANDLERS = ( + 'django.core.files.uploadhandler.MemoryFileUploadHandler', +) +FILE_UPLOAD_MAX_MEMORY_SIZE = 1048576 # 1 MB diff -r 000000000000 -r 0b061d58aea3 testappproj/settings.pyc Binary file testappproj/settings.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/settings.py~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/settings.py~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,85 @@ +import os +import sys +# Django settings for testappproj project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +ROOT = os.path.dirname(sys.modules[__name__].__file__) + +DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. +DATABASE_NAME = '' # Or path to database file if using sqlite3. +DATABASE_USER = '' # Not used with sqlite3. +DATABASE_PASSWORD = '' # Not used with sqlite3. +DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. +DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 's2er59!c4*5-bi5tz)j-#=ngw^p&z8&w-#ft&+sv!_^0m#88pd' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +) + +ROOT_URLCONF = 'testappproj.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join(ROOT, 'templates') +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'testapp', +) diff -r 000000000000 -r 0b061d58aea3 testappproj/static/appjs.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/static/appjs.js Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,10 @@ + + +function loadcode(id) { + +$("#solve_" + id).load(location.protocol + "//" + location.host + + "/code/" + id + "/",function() { + alert("something happened here") + }); + +} \ No newline at end of file diff -r 000000000000 -r 0b061d58aea3 testappproj/static/appjs.js~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/static/appjs.js~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,15 @@ +$(document).ready(function(){ +$("a").click(function(event){ + alert("As you can see, the link no longer took you to jquery.com"); + event.preventDefault(); + }); + }); + + + +function loadcode(id) { + +$("#solve_" + id).load(location.protocol + "//" + location.host + + "/code/" + id + "/"); + +} \ No newline at end of file diff -r 000000000000 -r 0b061d58aea3 testappproj/static/jquery.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/static/jquery.js Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,2992 @@ +(function(){ +/* + * jQuery 1.2.1 - New Wave Javascript + * + * Copyright (c) 2007 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2007-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $ + * $Rev: 3353 $ + */ + +// Map over jQuery in case of overwrite +if ( typeof jQuery != "undefined" ) + var _jQuery = jQuery; + +var jQuery = window.jQuery = function(selector, context) { + // If the context is a namespace object, return a new object + return this instanceof jQuery ? + this.init(selector, context) : + new jQuery(selector, context); +}; + +// Map over the $ in case of overwrite +if ( typeof $ != "undefined" ) + var _$ = $; + +// Map the jQuery namespace to the '$' one +window.$ = jQuery; + +var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; + +jQuery.fn = jQuery.prototype = { + init: function(selector, context) { + // Make sure that a selection was provided + selector = selector || document; + + // Handle HTML strings + if ( typeof selector == "string" ) { + var m = quickExpr.exec(selector); + if ( m && (m[1] || !context) ) { + // HANDLE: $(html) -> $(array) + if ( m[1] ) + selector = jQuery.clean( [ m[1] ], context ); + + // HANDLE: $("#id") + else { + var tmp = document.getElementById( m[3] ); + if ( tmp ) + // Handle the case where IE and Opera return items + // by name instead of ID + if ( tmp.id != m[3] ) + return jQuery().find( selector ); + else { + this[0] = tmp; + this.length = 1; + return this; + } + else + selector = []; + } + + // HANDLE: $(expr) + } else + return new jQuery( context ).find( selector ); + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction(selector) ) + return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( selector ); + + return this.setArray( + // HANDLE: $(array) + selector.constructor == Array && selector || + + // HANDLE: $(arraylike) + // Watch for when an array-like object is passed as the selector + (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) || + + // HANDLE: $(*) + [ selector ] ); + }, + + jquery: "1.2.1", + + size: function() { + return this.length; + }, + + length: 0, + + get: function( num ) { + return num == undefined ? + + // Return a 'clean' array + jQuery.makeArray( this ) : + + // Return just the object + this[num]; + }, + + pushStack: function( a ) { + var ret = jQuery(a); + ret.prevObject = this; + return ret; + }, + + setArray: function( a ) { + this.length = 0; + Array.prototype.push.apply( this, a ); + return this; + }, + + each: function( fn, args ) { + return jQuery.each( this, fn, args ); + }, + + index: function( obj ) { + var pos = -1; + this.each(function(i){ + if ( this == obj ) pos = i; + }); + return pos; + }, + + attr: function( key, value, type ) { + var obj = key; + + // Look for the case where we're accessing a style value + if ( key.constructor == String ) + if ( value == undefined ) + return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined; + else { + obj = {}; + obj[ key ] = value; + } + + // Check to see if we're setting style values + return this.each(function(index){ + // Set all the styles + for ( var prop in obj ) + jQuery.attr( + type ? this.style : this, + prop, jQuery.prop(this, obj[prop], type, index, prop) + ); + }); + }, + + css: function( key, value ) { + return this.attr( key, value, "curCSS" ); + }, + + text: function(e) { + if ( typeof e != "object" && e != null ) + return this.empty().append( document.createTextNode( e ) ); + + var t = ""; + jQuery.each( e || this, function(){ + jQuery.each( this.childNodes, function(){ + if ( this.nodeType != 8 ) + t += this.nodeType != 1 ? + this.nodeValue : jQuery.fn.text([ this ]); + }); + }); + return t; + }, + + wrapAll: function(html) { + if ( this[0] ) + // The elements to wrap the target around + jQuery(html, this[0].ownerDocument) + .clone() + .insertBefore(this[0]) + .map(function(){ + var elem = this; + while ( elem.firstChild ) + elem = elem.firstChild; + return elem; + }) + .append(this); + + return this; + }, + + wrapInner: function(html) { + return this.each(function(){ + jQuery(this).contents().wrapAll(html); + }); + }, + + wrap: function(html) { + return this.each(function(){ + jQuery(this).wrapAll(html); + }); + }, + + append: function() { + return this.domManip(arguments, true, 1, function(a){ + this.appendChild( a ); + }); + }, + + prepend: function() { + return this.domManip(arguments, true, -1, function(a){ + this.insertBefore( a, this.firstChild ); + }); + }, + + before: function() { + return this.domManip(arguments, false, 1, function(a){ + this.parentNode.insertBefore( a, this ); + }); + }, + + after: function() { + return this.domManip(arguments, false, -1, function(a){ + this.parentNode.insertBefore( a, this.nextSibling ); + }); + }, + + end: function() { + return this.prevObject || jQuery([]); + }, + + find: function(t) { + var data = jQuery.map(this, function(a){ return jQuery.find(t,a); }); + return this.pushStack( /[^+>] [^+>]/.test( t ) || t.indexOf("..") > -1 ? + jQuery.unique( data ) : data ); + }, + + clone: function(events) { + // Do the clone + var ret = this.map(function(){ + return this.outerHTML ? jQuery(this.outerHTML)[0] : this.cloneNode(true); + }); + + // Need to set the expando to null on the cloned set if it exists + // removeData doesn't work here, IE removes it from the original as well + // this is primarily for IE but the data expando shouldn't be copied over in any browser + var clone = ret.find("*").andSelf().each(function(){ + if ( this[ expando ] != undefined ) + this[ expando ] = null; + }); + + // Copy the events from the original to the clone + if (events === true) + this.find("*").andSelf().each(function(i) { + var events = jQuery.data(this, "events"); + for ( var type in events ) + for ( var handler in events[type] ) + jQuery.event.add(clone[i], type, events[type][handler], events[type][handler].data); + }); + + // Return the cloned set + return ret; + }, + + filter: function(t) { + return this.pushStack( + jQuery.isFunction( t ) && + jQuery.grep(this, function(el, index){ + return t.apply(el, [index]); + }) || + + jQuery.multiFilter(t,this) ); + }, + + not: function(t) { + return this.pushStack( + t.constructor == String && + jQuery.multiFilter(t, this, true) || + + jQuery.grep(this, function(a) { + return ( t.constructor == Array || t.jquery ) + ? jQuery.inArray( a, t ) < 0 + : a != t; + }) + ); + }, + + add: function(t) { + return this.pushStack( jQuery.merge( + this.get(), + t.constructor == String ? + jQuery(t).get() : + t.length != undefined && (!t.nodeName || jQuery.nodeName(t, "form")) ? + t : [t] ) + ); + }, + + is: function(expr) { + return expr ? jQuery.multiFilter(expr,this).length > 0 : false; + }, + + hasClass: function(expr) { + return this.is("." + expr); + }, + + val: function( val ) { + if ( val == undefined ) { + if ( this.length ) { + var elem = this[0]; + + // We need to handle select boxes special + if ( jQuery.nodeName(elem, "select") ) { + var index = elem.selectedIndex, + a = [], + options = elem.options, + one = elem.type == "select-one"; + + // Nothing was selected + if ( index < 0 ) + return null; + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[i]; + if ( option.selected ) { + // Get the specifc value for the option + var val = jQuery.browser.msie && !option.attributes["value"].specified ? option.text : option.value; + + // We don't need an array for one selects + if ( one ) + return val; + + // Multi-Selects return an array + a.push(val); + } + } + + return a; + + // Everything else, we just grab the value + } else + return this[0].value.replace(/\r/g, ""); + } + } else + return this.each(function(){ + if ( val.constructor == Array && /radio|checkbox/.test(this.type) ) + this.checked = (jQuery.inArray(this.value, val) >= 0 || + jQuery.inArray(this.name, val) >= 0); + else if ( jQuery.nodeName(this, "select") ) { + var tmp = val.constructor == Array ? val : [val]; + + jQuery("option", this).each(function(){ + this.selected = (jQuery.inArray(this.value, tmp) >= 0 || + jQuery.inArray(this.text, tmp) >= 0); + }); + + if ( !tmp.length ) + this.selectedIndex = -1; + } else + this.value = val; + }); + }, + + html: function( val ) { + return val == undefined ? + ( this.length ? this[0].innerHTML : null ) : + this.empty().append( val ); + }, + + replaceWith: function( val ) { + return this.after( val ).remove(); + }, + + eq: function(i){ + return this.slice(i, i+1); + }, + + slice: function() { + return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); + }, + + map: function(fn) { + return this.pushStack(jQuery.map( this, function(elem,i){ + return fn.call( elem, i, elem ); + })); + }, + + andSelf: function() { + return this.add( this.prevObject ); + }, + + domManip: function(args, table, dir, fn) { + var clone = this.length > 1, a; + + return this.each(function(){ + if ( !a ) { + a = jQuery.clean(args, this.ownerDocument); + if ( dir < 0 ) + a.reverse(); + } + + var obj = this; + + if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") ) + obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody")); + + jQuery.each( a, function(){ + var elem = clone ? this.cloneNode(true) : this; + if ( !evalScript(0, elem) ) + fn.call( obj, elem ); + }); + }); + } +}; + +function evalScript(i, elem){ + var script = jQuery.nodeName(elem, "script"); + + if ( script ) { + if ( elem.src ) + jQuery.ajax({ url: elem.src, async: false, dataType: "script" }); + else + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + + if ( elem.parentNode ) + elem.parentNode.removeChild(elem); + + } else if ( elem.nodeType == 1 ) + jQuery("script", elem).each(evalScript); + + return script; +} + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, a = 1, al = arguments.length, deep = false; + + // Handle a deep copy situation + if ( target.constructor == Boolean ) { + deep = target; + target = arguments[1] || {}; + } + + // extend jQuery itself if only one argument is passed + if ( al == 1 ) { + target = this; + a = 0; + } + + var prop; + + for ( ; a < al; a++ ) + // Only deal with non-null/undefined values + if ( (prop = arguments[a]) != null ) + // Extend the base object + for ( var i in prop ) { + // Prevent never-ending loop + if ( target == prop[i] ) + continue; + + // Recurse if we're merging object values + if ( deep && typeof prop[i] == 'object' && target[i] ) + jQuery.extend( target[i], prop[i] ); + + // Don't bring in undefined values + else if ( prop[i] != undefined ) + target[i] = prop[i]; + } + + // Return the modified object + return target; +}; + +var expando = "jQuery" + (new Date()).getTime(), uuid = 0, win = {}; + +jQuery.extend({ + noConflict: function(deep) { + window.$ = _$; + if ( deep ) + window.jQuery = _jQuery; + return jQuery; + }, + + // This may seem like some crazy code, but trust me when I say that this + // is the only cross-browser way to do this. --John + isFunction: function( fn ) { + return !!fn && typeof fn != "string" && !fn.nodeName && + fn.constructor != Array && /function/i.test( fn + "" ); + }, + + // check if an element is in a XML document + isXMLDoc: function(elem) { + return elem.documentElement && !elem.body || + elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; + }, + + // Evalulates a script in a global context + // Evaluates Async. in Safari 2 :-( + globalEval: function( data ) { + data = jQuery.trim( data ); + if ( data ) { + if ( window.execScript ) + window.execScript( data ); + else if ( jQuery.browser.safari ) + // safari doesn't provide a synchronous global eval + window.setTimeout( data, 0 ); + else + eval.call( window, data ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); + }, + + cache: {}, + + data: function( elem, name, data ) { + elem = elem == window ? win : elem; + + var id = elem[ expando ]; + + // Compute a unique ID for the element + if ( !id ) + id = elem[ expando ] = ++uuid; + + // Only generate the data cache if we're + // trying to access or manipulate it + if ( name && !jQuery.cache[ id ] ) + jQuery.cache[ id ] = {}; + + // Prevent overriding the named cache with undefined values + if ( data != undefined ) + jQuery.cache[ id ][ name ] = data; + + // Return the named cache data, or the ID for the element + return name ? jQuery.cache[ id ][ name ] : id; + }, + + removeData: function( elem, name ) { + elem = elem == window ? win : elem; + + var id = elem[ expando ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( jQuery.cache[ id ] ) { + // Remove the section of cache data + delete jQuery.cache[ id ][ name ]; + + // If we've removed all the data, remove the element's cache + name = ""; + for ( name in jQuery.cache[ id ] ) break; + if ( !name ) + jQuery.removeData( elem ); + } + + // Otherwise, we want to remove all of the element's data + } else { + // Clean up the element expando + try { + delete elem[ expando ]; + } catch(e){ + // IE has trouble directly removing the expando + // but it's ok with using removeAttribute + if ( elem.removeAttribute ) + elem.removeAttribute( expando ); + } + + // Completely remove the data cache + delete jQuery.cache[ id ]; + } + }, + + // args is for internal usage only + each: function( obj, fn, args ) { + if ( args ) { + if ( obj.length == undefined ) + for ( var i in obj ) + fn.apply( obj[i], args ); + else + for ( var i = 0, ol = obj.length; i < ol; i++ ) + if ( fn.apply( obj[i], args ) === false ) break; + + // A special, fast, case for the most common use of each + } else { + if ( obj.length == undefined ) + for ( var i in obj ) + fn.call( obj[i], i, obj[i] ); + else + for ( var i = 0, ol = obj.length, val = obj[0]; + i < ol && fn.call(val,i,val) !== false; val = obj[++i] ){} + } + + return obj; + }, + + prop: function(elem, value, type, index, prop){ + // Handle executable functions + if ( jQuery.isFunction( value ) ) + value = value.call( elem, [index] ); + + // exclude the following css properties to add px + var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; + + // Handle passing in a number to a CSS property + return value && value.constructor == Number && type == "curCSS" && !exclude.test(prop) ? + value + "px" : + value; + }, + + className: { + // internal only, use addClass("class") + add: function( elem, c ){ + jQuery.each( (c || "").split(/\s+/), function(i, cur){ + if ( !jQuery.className.has( elem.className, cur ) ) + elem.className += ( elem.className ? " " : "" ) + cur; + }); + }, + + // internal only, use removeClass("class") + remove: function( elem, c ){ + elem.className = c != undefined ? + jQuery.grep( elem.className.split(/\s+/), function(cur){ + return !jQuery.className.has( c, cur ); + }).join(" ") : ""; + }, + + // internal only, use is(".class") + has: function( t, c ) { + return jQuery.inArray( c, (t.className || t).toString().split(/\s+/) ) > -1; + } + }, + + swap: function(e,o,f) { + for ( var i in o ) { + e.style["old"+i] = e.style[i]; + e.style[i] = o[i]; + } + f.apply( e, [] ); + for ( var i in o ) + e.style[i] = e.style["old"+i]; + }, + + css: function(e,p) { + if ( p == "height" || p == "width" ) { + var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"]; + + jQuery.each( d, function(){ + old["padding" + this] = 0; + old["border" + this + "Width"] = 0; + }); + + jQuery.swap( e, old, function() { + if ( jQuery(e).is(':visible') ) { + oHeight = e.offsetHeight; + oWidth = e.offsetWidth; + } else { + e = jQuery(e.cloneNode(true)) + .find(":radio").removeAttr("checked").end() + .css({ + visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0" + }).appendTo(e.parentNode)[0]; + + var parPos = jQuery.css(e.parentNode,"position") || "static"; + if ( parPos == "static" ) + e.parentNode.style.position = "relative"; + + oHeight = e.clientHeight; + oWidth = e.clientWidth; + + if ( parPos == "static" ) + e.parentNode.style.position = "static"; + + e.parentNode.removeChild(e); + } + }); + + return p == "height" ? oHeight : oWidth; + } + + return jQuery.curCSS( e, p ); + }, + + curCSS: function(elem, prop, force) { + var ret, stack = [], swap = []; + + // A helper method for determining if an element's values are broken + function color(a){ + if ( !jQuery.browser.safari ) + return false; + + var ret = document.defaultView.getComputedStyle(a,null); + return !ret || ret.getPropertyValue("color") == ""; + } + + if (prop == "opacity" && jQuery.browser.msie) { + ret = jQuery.attr(elem.style, "opacity"); + return ret == "" ? "1" : ret; + } + + if (prop.match(/float/i)) + prop = styleFloat; + + if (!force && elem.style[prop]) + ret = elem.style[prop]; + + else if (document.defaultView && document.defaultView.getComputedStyle) { + + if (prop.match(/float/i)) + prop = "float"; + + prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase(); + var cur = document.defaultView.getComputedStyle(elem, null); + + if ( cur && !color(elem) ) + ret = cur.getPropertyValue(prop); + + // If the element isn't reporting its values properly in Safari + // then some display: none elements are involved + else { + // Locate all of the parent display: none elements + for ( var a = elem; a && color(a); a = a.parentNode ) + stack.unshift(a); + + // Go through and make them visible, but in reverse + // (It would be better if we knew the exact display type that they had) + for ( a = 0; a < stack.length; a++ ) + if ( color(stack[a]) ) { + swap[a] = stack[a].style.display; + stack[a].style.display = "block"; + } + + // Since we flip the display style, we have to handle that + // one special, otherwise get the value + ret = prop == "display" && swap[stack.length-1] != null ? + "none" : + document.defaultView.getComputedStyle(elem,null).getPropertyValue(prop) || ""; + + // Finally, revert the display styles back + for ( a = 0; a < swap.length; a++ ) + if ( swap[a] != null ) + stack[a].style.display = swap[a]; + } + + if ( prop == "opacity" && ret == "" ) + ret = "1"; + + } else if (elem.currentStyle) { + var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}); + ret = elem.currentStyle[prop] || elem.currentStyle[newProp]; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test(ret) && /^\d/.test(ret) ) { + var style = elem.style.left; + var runtimeStyle = elem.runtimeStyle.left; + elem.runtimeStyle.left = elem.currentStyle.left; + elem.style.left = ret || 0; + ret = elem.style.pixelLeft + "px"; + elem.style.left = style; + elem.runtimeStyle.left = runtimeStyle; + } + } + + return ret; + }, + + clean: function(a, doc) { + var r = []; + doc = doc || document; + + jQuery.each( a, function(i,arg){ + if ( !arg ) return; + + if ( arg.constructor == Number ) + arg = arg.toString(); + + // Convert html string into DOM nodes + if ( typeof arg == "string" ) { + // Fix "XHTML"-style tags in all browsers + arg = arg.replace(/(<(\w+)[^>]*?)\/>/g, function(m, all, tag){ + return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i)? m : all+">"; + }); + + // Trim whitespace, otherwise indexOf won't work as expected + var s = jQuery.trim(arg).toLowerCase(), div = doc.createElement("div"), tb = []; + + var wrap = + // option or optgroup + !s.indexOf("", ""] || + + !s.indexOf("", ""] || + + s.match(/^<(thead|tbody|tfoot|colg|cap)/) && + [1, "", "
"] || + + !s.indexOf("", ""] || + + // matched above + (!s.indexOf("", ""] || + + !s.indexOf("", ""] || + + // IE can't serialize and + + Fossee Test + + + +
+ +
+ {% block body %} + {% endblock %} +
+ +
+ + {% block scripts %} + {% endblock %} + + + + + diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/base.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/base.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,47 @@ + + + + Fossee Test + + + +
+ +
+ {% block body %} + {% endblock %} +
+ +
+ + {% block scripts %} + {% endblock %} + + + + + diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/code.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/code.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,42 @@ +{# {%extends "base.html"%} #} +{%block body%} +

{{ problem.name }}

+ + +{% comment %} +{% load pykata_extras %} +{% autoescape off %} +

+{{problem.description|force_escape|spacify_code|linebreaksbr}} +

+{% endautoescape %} +{% endcomment %} + +

Examples

+
+{{ problem.examples }}
+
+ +
+

Enter your solution here:

+

+ +

+
+ + + +{%endblock%} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/code.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/code.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,42 @@ +{%extends "base.html"%} +{%block body%} +

{{ problem.name }}

+ + +{% comment %} +{% load pykata_extras %} +{% autoescape off %} +

+{{problem.description|force_escape|spacify_code|linebreaksbr}} +

+{% endautoescape %} +{% endcomment %} + +

Examples

+
+{{ problem.examples }}
+
+ +
+

Enter your solution here:

+

+ +

+
+ + + +{%endblock%} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/index.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,7 @@ +{%extends "base.html"%} +{%block body%} + +

Welcome to testapp

+ +{%endblock%} + diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/index.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/index.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,46 @@ +{%extends "base.html"%} +{%block body%} + +

Welcome to PyKata ... the website for Python practice. Learning Python is a skill. +It takes practice, not just an understanding of the theory. In fact, you can learn +basic Python without any theory. Just read the help pages if you get stuck. Start +with the easy problems first. Some of these have hints, or even a complete solution. +   vision statement +       teacher statements +       manifesto

+ +

About Python ... Python is a modern mainstream computer language, much like Java +and C++, but simpler. It's the closest thing we could find to pseudocode, the language used +by scientists when they want to express an idea involving computation.

+ +

You don't have to take an entire course in programming to learn Python. Every high-school +graduate, certainly anyone considering a career in technology, should know how to write a +simple program. Python makes that possible. PyKata is the best way to learn Python.

+ +

Problem Categories

+ + +

News

+
    +
  1. You can now save your work-in-progress. When solving an exercise, hitting Run automatically saves your work.
  2. +
  3. Progress indicators: We now show which problems you have solved.
  4. +
+ +

This site is still under development. Coming Soon:

+
    +
  • Teacher report to view a student's progress +    Mockup
  • +
  • More content!!
  • +
+ +{%endblock%} + diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/new_edit_problem.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/new_edit_problem.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,22 @@ +{%block body%} + +{% if creating %} +

Upload Problems

+
+ + {{ upload_form.as_table }} +
+ +
+
+{% endif %} + +

{% if creating %}Add{% else %}Edit{% endif %} Problem

+
+ + {{ form.as_table }} +
+ +
+ +{%endblock%} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/new_edit_problem.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/new_edit_problem.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,22 @@ +{%block body%} + +{% if creating %} +

Upload Problems

+
+ + {{ upload_form.as_table }} +
+ +
+
+{% endif %} + +

{% if creating %}Add{% else %}Edit{% endif %} Problem

+
+ + {{ form.as_table }} +
+ +
+ +{%endblock%} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/problems.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/problems.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,30 @@ +{%extends "base.html"%} +{% block body %} +

All Problems

+ + + + +{# {% if user %}{% endif %} #} + + +{% for entry in entries %} + + + + + +{% endfor %} + +
DescriptionSolvedEdit
+ {{ entry.problem|escape }} + {{ entry.session|escape }} +
+ solve +
+ +

+{% if user %}Create new problem{% endif %} +

+ +{%endblock%} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/problems.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/problems.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,27 @@ +{%extends "base.html"%} +{% block body %} +

All Problems

+ + + + +{# {% if user %}{% endif %} #} + + +{% for entry in entries %} + + + + +{% endfor %} + +
DescriptionSolvedEdit
+ {{ entry.problem|escape }} + solve +
+ +

+{% if user %}Create new problem{% endif %} +

+ +{%endblock%} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/activate.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/activate.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,4 @@ +{% extends 'base.html' %} +{% block content %} +Your account has been successfully activated. +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/activation_email.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/activation_email.txt Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,9 @@ +Welcome to PyTasks: + +Click on the following link +http://{{site}}/accounts/activate/{{activation_key}} +and activate your account. +Note that the account has to activated within {{expiration_days}} days + +Regards, +PyTasks Team diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/activation_email_subject.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/activation_email_subject.txt Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,1 @@ +Welcome to PyTasks! diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/cases.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/cases.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,62 @@ +""" +This is the "example" module. + +The example module supplies one function, factorial(). For example, + +>>> factorial(5) +120 +""" + +def factorial(n): + """Return the factorial of n, an exact integer >= 0. + + If the result is small enough to fit in an int, return an int. + Else return a long. + + >>> [factorial(n) for n in range(6)] + [1, 1, 2, 6, 24, 120] + >>> [factorial(long(n)) for n in range(6)] + [1, 1, 2, 6, 24, 120] + >>> factorial(30) + 265252859812191058636308480000000L + >>> factorial(30L) + 265252859812191058636308480000000L + >>> factorial(-1) + Traceback (most recent call last): + ... + ValueError: n must be >= 0 + + Factorials of floats are OK, but the float must be an exact integer: + >>> factorial(30.1) + Traceback (most recent call last): + ... + ValueError: n must be exact integer + >>> factorial(30.0) + 265252859812191058636308480000000L + + It must also not be ridiculously large: + >>> factorial(1e100) + Traceback (most recent call last): + ... + OverflowError: n too large + """ + + import math + if not n >= 0: + raise ValueError("n must be >= 0") + if math.floor(n) != n: + raise ValueError("n must be exact integer") + if n+1 == n: # catch a value like 1e300 + raise OverflowError("n too large") + result = 1 + factor = 2 + while factor <= n: + result *= factor + factor += 1 + return result + + +if __name__ == "__main__": + import doctest + doctest.testmod() + diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/logged_out.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/logged_out.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,12 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block breadcrumbs %}{% endblock %} + +{% block content %} + +

{% trans "Thanks for spending some quality time with the Web site today." %}

+ +

{% trans 'Log in again' %}

+ +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/login.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/login.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,7 @@ +{% block content %} +
+{{ form.as_p }} + +
+Forgot password? +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/login.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/login.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,7 @@ +{% block content %} +
+{{ form.as_p }} + +
+Forgot password? +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/logout.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/logout.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,6 @@ +{% extends 'base.html' %} +{% block content %} +You have successfully logged out of PyTasks. +

+Click here to go back to PyTask Homepage +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/password_change_done.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/password_change_done.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% load i18n %} +{% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}{% trans 'Documentation' %} / {% endif %}{% trans 'Change password' %} / {% trans 'Log out' %}{% endblock %} +{% block breadcrumbs %}{% endblock %} + +{% block title %}{% trans 'Password change successful' %}{% endblock %} + +{% block content %} + +

{% trans 'Password change successful' %}

+ +

{% trans 'Your password was changed.' %}

+ +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/password_change_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/password_change_form.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,26 @@ +{% extends "base.html" %} +{% load i18n %} +{% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}{% trans 'Documentation' %} / {% endif %} {% trans 'Change password' %} / {% trans 'Log out' %}{% endblock %} +{% block breadcrumbs %}{% endblock %} + +{% block title %}{% trans 'Password change' %}{% endblock %} + +{% block content %} + +

{% trans 'Password change' %}

+ +

{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}

+ +
+ +{{ form.old_password.errors }} +

{{ form.old_password }}

+{{ form.new_password1.errors }} +

{{ form.new_password1 }}

+{{ form.new_password2.errors }} +

{{ form.new_password2 }}

+ +

+
+ +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/password_reset_complete.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/password_reset_complete.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,16 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block breadcrumbs %}{% endblock %} + +{% block title %}{% trans 'Password reset complete' %}{% endblock %} + +{% block content %} + +

{% trans 'Password reset complete' %}

+ +

{% trans "Your password has been set. You may go ahead and log in now." %}

+ +

{% trans 'Log in' %}

+ +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/password_reset_confirm.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/password_reset_confirm.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,32 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block breadcrumbs %}{% endblock %} + +{% block title %}{% trans 'Password reset' %}{% endblock %} + +{% block content %} + +{% if validlink %} + +

{% trans 'Enter new password' %}

+ +

{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}

+ +
+{{ form.new_password1.errors }} +

{{ form.new_password1 }}

+{{ form.new_password2.errors }} +

{{ form.new_password2 }}

+

+
+ +{% else %} + +

{% trans 'Password reset unsuccessful' %}

+ +

{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}

+ +{% endif %} + +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/password_reset_done.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/password_reset_done.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block breadcrumbs %}{% endblock %} + +{% block title %}{% trans 'Password reset successful' %}{% endblock %} + +{% block content %} + +

{% trans 'Password reset successful' %}

+ +

{% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}

+ +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/password_reset_email.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/password_reset_email.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,15 @@ +{% load i18n %}{% autoescape off %} +{% trans "You're receiving this e-mail because you requested a password reset" %} +{% blocktrans %}for your user account at {{ site_name }}{% endblocktrans %}. + +{% trans "Please go to the following page and choose a new password:" %} +{% block reset_link %} +{{ protocol }}://{{ domain }}{% url django.contrib.auth.views.password_reset_confirm uidb36=uid, token=token %} +{% endblock %} +{% trans "Your username, in case you've forgotten:" %} {{ user.username }} + +{% trans "Thanks for using our site!" %} + +{% blocktrans %}The {{ site_name }} team{% endblocktrans %} + +{% endautoescape %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/password_reset_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/password_reset_form.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,19 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block breadcrumbs %}{% endblock %} + +{% block title %}{% trans "Password reset" %}{% endblock %} + +{% block content %} + +

{% trans "Password reset" %}

+ +

{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}

+ +
+{{ form.email.errors }} +

{{ form.email }}

+
+ +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/registration_complete.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/registration_complete.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,4 @@ +{% extends 'base.html' %} +{% block content %} +Please check your email for instructions on activating your account. +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/registration_form.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/registration_form.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,7 @@ +{# {% extends 'base.html' %} #} +{% block content %} +
+{{ form.as_p }} + +
+{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/registration/registration_form.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/registration/registration_form.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,7 @@ +{% extends 'base.html' %} +{% block content %} +
+{{ form.as_p }} + +
+{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/run.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/run.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,22 @@ +{%extends "base.html"%} +{%block body%} + {{ results }} + +{%endblock%} + +{% block scripts %} + + +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/run.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/run.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,22 @@ +{%extends "base.html"%} +{%block body%} + {{ result }} + +{%endblock%} + +{% block scripts %} + + +{% endblock %} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/shell.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/shell.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,108 @@ + + + + + Interactive Shell + + + + + + + + + + +
+ + + + + + +
+ +

+ +

use ctrl-up for history

+ + + + + + diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/shell.html~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/shell.html~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,106 @@ + + + + + Interactive Shell + + + + + + + + + + +
+ + + + + + +
+ +

+ + + + + + diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/traceback.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/traceback.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,6 @@ +{%extends "base.html"%} +{%block body%} +
+{{ errors }}
+
+{%endblock%} diff -r 000000000000 -r 0b061d58aea3 testappproj/templates/upload.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/templates/upload.html Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,16 @@ +{%extends "base.html"%} +{%block body%} + +

Your upload was processed!

+

Report -

+{% for item in report %} +

+ {{item.name}} gave {{item.status}} + {% ifequal item.status "error" %} + {{ item.upload_response }} + {% endifequal %} +

+{% endfor %} + +{%endblock%} + diff -r 000000000000 -r 0b061d58aea3 testappproj/test.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/test.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,1 @@ +print "hello world" diff -r 000000000000 -r 0b061d58aea3 testappproj/test.pyc Binary file testappproj/test.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/test.py~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/test.py~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,1 @@ +print "hello world" diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/#forms.py# --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/#forms.py# Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,54 @@ +from django import forms +from registration.forms import RegistrationForm +from django.utils.translation import ugettext_lazy as _ +from testapp.models import Test_User +from registration.models import RegistrationProfile +#from google.appengine.ext.db import djangoforms +import models + + +attrs_dict = { 'class': 'required' } + +PROBLEM_CHOICES=( + ('P', 'Plotting'), + ('S', 'Scripting'), +) + + + +class ProblemForm(forms.Form): + Description = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),required=True,help_text="To be used as the question") + Problem_type = forms.ChoiceField(choices=PROBLEM_CHOICES,required=True) + Solution = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),help_text="comma seperated in case of multiple solutions") + Solution_Image = forms.ImageField() + Session = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}), required=True) + + + class Meta: + model = models.Problem + exclude = ('author', 'created', 'modified') + + + +class Test_UserForm(RegistrationForm): + + fullname = forms.CharField(widget=forms.TextInput(attrs=attrs_dict)) + class Meta: + exclude = ('special_user',) + + + def save(self, profile_callback=None): + new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'], + password=self.cleaned_data['password1'], + email=self.cleaned_data['email']) + new_profile = Test_User(user=new_user, fullname=self.cleaned_data[fullname]) + new_profile.save() + return new_user + + + +class UploadForm(forms.Form): + file = forms.FileField() + + class Meta: + model = None diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/#views (copy).py# --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/#views (copy).py# Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,460 @@ +# Python imports +import doctest +import logging +import os +import traceback + +# # AppEngine imports + +from django.contrib.auth.models import User + +from testappproj.testapp.models import * +from django.http import HttpResponse + +# from google.appengine.api import users +# from google.appengine.ext.webapp import template + +# from google.appengine.ext import db +# from google.appengine.ext.db import djangoforms + + +# Django imports +#from django.conf import settings +#settings._target = None +#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' +#import django +from django import http +from django import shortcuts +from django.template import Context ,RequestContext +from django.template.loader import get_template + +# Local imports +from forms import * +import models +from helpers import bulkuploader as pykataupload +from datetime import date + + +def respond(request, user,template, params=None): + """Helper to render a response, passing standard stuff to the response. + + Args: + request: The request object. + user: The User object representing the current user; or None if nobody + is logged in. + template: The template name; '.html' is appended automatically. + params: A dict giving the template parameters; modified in-place. + + Returns: + Whatever render_to_response(template, params) returns. + + Raises: + Whatever render_to_response(template, params) raises. + """ + if params is None: + params = {} + if user: + params['user'] = user + params['sign_out'] = 1 + # params['is_admin'] = (users.is_current_user_admin()) + else: + params['sign_in'] = 1 + # if not template.endswith('.html'): + template += '.html' + return shortcuts.render_to_response(template, params) + +def execute_test_cases(request, test_cases, g): + li = [] + + solved = True + for e in test_cases: + if not e.want: + exec e.source in g + continue + call = e.source.strip() + got = eval(e.source.strip(), g) + expected = eval(e.want, g) + + if got == expected: + status = 'pass' + else: + status = 'fail' + solved = False + li.append([call, expected, "%r" % got, status]) + + return li, solved + + + + +def index(request): + """ need to change user in the django.contrib way""" + + user = request.user + + return respond(request , user, 'index') + +# def contribution(request): +# # user = users.get_current_user() +# return respond(request, user, 'contribution') + +# def help(request): +# # user = users.get_current_user() +# return respond(request, user, 'help') + +# def about(request): +# # user = users.get_current_user() +# return respond(request, user, 'about') + +# def vision(request): +# # user = users.get_current_user() +# return respond(request, user, 'vision') + +# def statements(request): +# # user = users.get_current_user() +# return respond(request, user, 'statements') + + +def get_pu(problem): + ''' + returns: + - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor + - "PU_NOT_FOUND": for signed in users when no solution has been attempted. + - ProblemUser: for signed in users when a solution has been attempted + + ''' +# user = users.get_current_user() +# if not user: +# return "USER_NOT_SIGNED_IN" + pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user()) + pu_results = pu_query.fetch(1) + if pu_results: + return pu_results[0] + return "PU_NOT_FOUND" + +def is_solved(problem): + pu = get_pu(problem) + if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False + return pu.solved + +def problems(request, category=None): + user = request.user + + # if category is None: + # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC') + # else: + # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category) + + + + + # entries = [] + # for problem in problems: + # e = dict(problem=problem, + # username=problem.author.nickname().partition('@')[0], + # solved=is_solved(problem)) + # entries.append(e) + # problems = entries + entries=[] + problems=Problem.objects.all() + for problem in problems: + e = dict(problem=problem.name, + username=user.username, + problem_id=problem.id + ) + entries.append(e) + +# print entries + + + + return respond(request, user, 'problems',{'entries' : entries } ) + +def code(request, problem_id): + + print problem_id + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + +# pu = get_pu(problem) +# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time +# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False) +# pu.put() +# pu = None + + return respond(request, request.user ,'code' , ) + +def run(request): + user = request.user + problem_id = request.POST.get('problem_id') + if problem_id: + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + + user_code = request.POST.get('user_code') + + if not user_code: + return http.HttpResponse('bad request') + + # pu = get_pu(problem) + # # update ProblemUser object for this user + # if (pu.__class__ == models.ProblemUser): + # pu.solution = user_code + # pu.put() + + user_code = user_code.replace('\r\n', '\n') + user_code += '\n\n' + + errors = '' + + + try: + print user_code + compiled = compile(user_code, 'error_file', 'exec') + g = {} + exec compiled in g + +# s = problem.tests.replace('\r\n', '\n') +# s += '\n\n' + # test_cases = doctest.DocTestParser().get_examples(s) + # results, solved = execute_test_cases(request, test_cases, g) + # if solved: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = True + # pu.put() + # else: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = False + # pu.put() + except: + errors = traceback.format_exc() + return respond(request, user, 'traceback', {'errors': errors}) + results="solved" + return respond(request, request.user, 'run', {'results': results}) + +def new_edit(request, problem_id=None, internal=False): + # internal indicates that it is being called internally by uploader + # + user = request.user + print user.username + if user.is_anonymous() : + return http.HttpResponseForbidden('You must be an signed in to create edit a problem.') + + if problem_id is None: + creating_new = True + else: + creating_new = False + + problem = None + # if problem_id: + # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id))) + # if problem.author != user and not users.is_current_user_admin(): + # return http.HttpResponseForbidden('You can only edit your own problems.') + # if problem is None: + # return http.HttpResponseNotFound('No such problem.') + + form = ProblemForm(data=request.POST or None, instance=problem) + upload_form = UploadForm(data=request.POST) + + if not request.POST: + return respond(request, user, 'new_edit_problem', {'form':form, 'problem':problem, 'creating':creating_new , 'upload_form' : upload_form }) + + + errors = form.errors + if not errors: + try: + problem = form.save(commit=False) + except ValueError, err: + errors['__all__'] = unicode(err) + + + if errors: + print "new world" + if internal: + return ('error',errors) + return respond(request, user, 'new_edit_problem', + {'form': form, 'problem':problem, 'creating':creating_new}) + + if creating_new: + # if internal: + # if len(request.POST['user_id'])>0: + # logging.info(request.POST) + # problem.author = users.User(request.POST['user_id']) + # else: + # problem.author = user + # else: + + + + + problem.author = user.username + problem.created = date.today() + problem. modified=date.today() + + problem.save() +# l = [] + # for x in problem.categories: + # l.extend(x.split()) + # problem.categories = l + # problem.put() + + if internal: + return ('success','success') + + + return http.HttpResponseRedirect('/problems') + +def upload(request): + """ upload handler, validates the form and calls handle_uploaded_file + for processing further + """ + user = request.user + if user is None: + return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.') + + if request.method == 'POST': + form = UploadForm(request.POST, request.FILES) + if form.is_valid(): + submission_report = handle_uploaded_file(request) + print "testing" + print submission_report + + return respond(request, user, 'upload', {'report':submission_report}) + else: + return http.HttpResponseForbidden('Oops something went wrong with the upload') + +def handle_uploaded_file(request): + """ Handles uploaded data, pushes it to existing problem creating code + TODO: 1. make efficient by putting actual database code Here + 2. Add more security and validation + """ + submission_data = request.FILES['file'].read() + if '#---' in submission_data: + all_submissions = submission_data.split('#---')[1:-1] + # ^^ ignoring the first null and last __main__ code + all_submissions = [ pykataupload.Submission(x) for x in all_submissions ] + report = [] + + for key,each_submission in enumerate(all_submissions): + # TODO: handle these later by TaskQueues to avoid timeouts on big uploads + # a good way would be to have ajax based status coming back to this page + # about each problem in the uploaded file, their status, progress etc. + each_submission.parse() + request.POST.clear() + request.POST.update (each_submission.data_dict) + upload_status, upload_response = new_edit(request, internal=True) + + report.append ({'status':upload_status, 'name':each_submission['name'], + 'upload_response':upload_response}) + + # Yay this hack works :D + return report + else: + return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.') + +def shell(request): + """ need to change user in the django.contrib way""" + + user = request.user + statement=request.GET.get('statement','') + if statement is not '': + + # the python compiler doesn't like network line endings + statement = statement.replace('\r\n', '\n') + + # add a couple newlines at the end of the statement. this makes + # single-line expressions such as 'class Foo: pass' evaluate happily. + statement += '\n\n' + print "statement"+statement + # log and compile the statement up front + try: + logging.info('Compiling and evaluating:\n%s' % statement) + compiled = compile(statement, '', 'single') + except: + return HttpResponse(traceback.format_exc(),mimetype="text/plain") +# pass + return HttpResponse("",mimetype="text/plain") + else: + return respond(request, user, 'shell') + # create a dedicated module to be used as this statement's __main__ + statement_module = new.module('__main__') + + # use this request's __builtin__, since it changes on each request. + # this is needed for import statements, among other things. + import __builtin__ + statement_module.__builtins__ = __builtin__ + + # load the session from the datastore + session = Session.get(self.request.get('session')) + + # swap in our custom module for __main__. then unpickle the session + # globals, run the statement, and re-pickle the session globals, all + # inside it. + old_main = sys.modules.get('__main__') + try: + sys.modules['__main__'] = statement_module + statement_module.__name__ = '__main__' + + # re-evaluate the unpicklables + for code in session.unpicklables: + exec code in statement_module.__dict__ + + # re-initialize the globals + for name, val in session.globals_dict().items(): + try: + statement_module.__dict__[name] = val + except: + msg = 'Dropping %s since it could not be unpickled.\n' % name + self.response.out.write(msg) + logging.warning(msg + traceback.format_exc()) + session.remove_global(name) + + # run! + old_globals = dict(statement_module.__dict__) + try: + old_stdout = sys.stdout + old_stderr = sys.stderr + try: + sys.stdout = self.response.out + sys.stderr = self.response.out + exec compiled in statement_module.__dict__ + finally: + sys.stdout = old_stdout + sys.stderr = old_stderr + except: + self.response.out.write(traceback.format_exc()) + return + + # extract the new globals that this statement added + new_globals = {} + for name, val in statement_module.__dict__.items(): + if name not in old_globals or val != old_globals[name]: + new_globals[name] = val + + if True in [isinstance(val, UNPICKLABLE_TYPES) + for val in new_globals.values()]: + # this statement added an unpicklable global. store the statement and + # the names of all of the globals it added in the unpicklables. + session.add_unpicklable(statement, new_globals.keys()) + logging.debug('Storing this statement as an unpicklable.') + + else: + # this statement didn't add any unpicklables. pickle and store the + # new globals back into the datastore. + for name, val in new_globals.items(): + if not name.startswith('__'): + session.set_global(name, val) + + finally: + sys.modules['__main__'] = old_main + + session.put() + + + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/__init__.py diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/__init__.pyc Binary file testappproj/testapp/__init__.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/forms.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,64 @@ +from django import forms +from registration.forms import RegistrationForm +from django.utils.translation import ugettext_lazy as _ +from testapp.models import Test_User +from registration.models import RegistrationProfile +#from google.appengine.ext.db import djangoforms +import models + + +attrs_dict = { 'class': 'required' } + +PROBLEM_CHOICES=( + ('P', 'Plotting'), + ('S', 'Scripting'), +) + +SESSION_CHOICES=( + ('A','DAY 1 SESSION 1'), + ('B','DAY 1 SESSION 2'), + ('C','DAY 1 SESSION 3'), + ('D','DAY 1 SESSION 4'), + ('E','DAY 2 SESSION 1'), + ('F','DAY 2 SESSION 2'), + ('G','DAY 2 SESSION 3'), + ('H','DAY 2 SESSION 4'), + ) + + +class ProblemForm(forms.Form): + Description = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),required=True,help_text="To be used as the question") + Problem_type = forms.ChoiceField(choices=PROBLEM_CHOICES,required=True) + Solution = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}),help_text="comma seperated in case of multiple solutions") + Solution_Image = forms.ImageField(required=False) + Session = forms.ChoiceField(choices=SESSION_CHOICES, required=True) + + + class Meta: + model = models.Problem + exclude = ('author', 'created', 'modified') + + + +class Test_UserForm(RegistrationForm): + + fullname = forms.CharField(widget=forms.TextInput(attrs=attrs_dict)) + class Meta: + exclude = ('special_user',) + + + def save(self, profile_callback=None): + new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'], + password=self.cleaned_data['password1'], + email=self.cleaned_data['email']) + new_profile = Test_User(user=new_user, fullname=self.cleaned_data[fullname]) + new_profile.save() + return new_user + + + +class UploadForm(forms.Form): + file = forms.FileField() + + class Meta: + model = None diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/forms.pyc Binary file testappproj/testapp/forms.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/forms.py~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/forms.py~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,25 @@ +from django import forms +#from google.appengine.ext.db import djangoforms +import models + + +class ProblemForm(forms.ModelForm): + name = forms.CharField(widget=forms.TextInput(attrs={'size': '80'})) + categories = forms.CharField(widget=forms.TextInput(attrs={'size': '80'})) + description = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'})) + examples = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'})) + skeleton = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'})) + tests = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'})) + other_tests = forms.CharField(widget=forms.Textarea(attrs={'rows': '10', 'cols': '80'}), required=False) + solution = forms.CharField(widget=forms.Textarea(attrs={'rows': '20', 'cols': '80'}), required=False) + + class Meta: + model = models.Problem + exclude = ('author', 'created', 'modified') + + +# class UploadForm(forms.ModelForm): +# file = forms.FileField() + +# class Meta: + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/helpers/.svn/all-wcprops Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 37 +/svn/!svn/ver/36/trunk/pykata/helpers +END +bulkuploader.py +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/36/trunk/pykata/helpers/bulkuploader.py +END +__init__.py +K 25 +svn:wc:ra_dav:version-url +V 49 +/svn/!svn/ver/36/trunk/pykata/helpers/__init__.py +END diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/helpers/.svn/entries Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,96 @@ +10 + +dir +47 +http://pykata.googlecode.com/svn/trunk/pykata/helpers +http://pykata.googlecode.com/svn + + + +2010-04-05T01:11:22.924441Z +36 +ideamonk + + + + + + + + + + + + + + +2167b252-2954-11df-990d-a5851c616dea + +bulkuploader.py +file + + + + +2010-04-13T15:15:45.000000Z +217236b8c5663efd46105616501ee7fb +2010-04-05T01:11:22.924441Z +36 +ideamonk + + + + + + + + + + + + + + + + + + + + + +3102 + +__init__.py +file + + + + +2010-04-13T15:15:45.000000Z +d784fa8b6d98d27699781bd9a7cf19f0 +2010-04-05T01:11:22.924441Z +36 +ideamonk + + + + + + + + + + + + + + + + + + + + + +2 + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/.svn/text-base/__init__.py.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/helpers/.svn/text-base/__init__.py.svn-base Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,1 @@ + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/.svn/text-base/bulkuploader.py.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/helpers/.svn/text-base/bulkuploader.py.svn-base Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,94 @@ +# UploadFormat Parser -- test version +# -- ideamonk + +class Submission(): + """ + A helper class for bulk uploads. It parses the given chunk of bulk + upload and tries to submit them to PyKata + """ + def __init__(self, bulk_text): + # initialize everything as default/blank as some things might not be + # present in submission + self.data_dict = dict() + self.bulk_text = bulk_text + self.multiline_fields = ('description', 'examples') + self.data_dict['user_id'] = '' + + def __getitem__(self, key): + try: + return self.data_dict[key] + except : + return None + + def __setitem__(self, key, item): + # mapping to match form submission for code reuse + if key=='pubTests': + key = 'tests' + if key=='privTests': + key='other_tests' + if key=='userID': + key='user_id' + + self.data_dict[key] = item + + def __str__(self): + return str(self.bulk_text) + + def parse(self): + """ Parses a problem submission into data fillable in the submission + form + """ + chunks = self.bulk_text.split('#-') + for chunk in chunks[1:]: + # ^^ ignores the first comment line of the problem + chunk_key, chunk_data = chunk.split(':',1) + chunk_key = chunk_key.strip() + if chunk_key in self.multiline_fields: + # these are data surrounded in triple quotes, single or double + chunk_data = eval(chunk_data).strip('\r\n') + else: + chunk_data = chunk_data.strip().strip('\r\n') + self[chunk_key] = chunk_data + + def talk(self): + """ Just a testing function, a submission talks about itself to everyone + """ + print "Hi I am a submission problem on PyKata," + print "Let me tell you something about myself - " + print "I was created by -", self['userID'] + print "My name is -", self['name'] + print "I belong to these categories -", self['categories'] + print "Here, something more about myself --" + print self['description'] + print "---------------------------------------" + print "My solution --" + print self['solution'] + print "----------------------------------------" + print "My skeleton --" + print self['skeleton'] + print "----------------------------------------" + print "Public Tests --" + print self['pubTests'] + print "----------------------------------------" + print "Private Tests --" + print self['privTests'] + print "----------------------------------------" + print "\n So tell me something about you too?" + + +def test_submission_parse(): + import urllib2 + example_file = urllib2.urlopen('http://ideamonk.in/code/foo.py').read() + example_submissions = example_file.split('#---')[1:-1] + # ^^ ignore the first null string and last __main__ test code + example_submissions = [ Submission(x) for x in example_submissions ] + for key, a_submission in enumerate(example_submissions): + print "Problem #", key, "parsed as --" + print "*************************************************************" + a_submission.parse() + a_submission.talk() + +if __name__=='__main__': + # testing + test_submission_parse() + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/helpers/__init__.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,1 @@ + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/__init__.pyc Binary file testappproj/testapp/helpers/__init__.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/bulkuploader.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/helpers/bulkuploader.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,97 @@ +# UploadFormat Parser -- test version +# -- ideamonk + +class Submission(): + """ + A helper class for bulk uploads. It parses the given chunk of bulk + upload and tries to submit them to PyKata + """ + def __init__(self, bulk_text): + # initialize everything as default/blank as some things might not be + # present in submission + self.data_dict = dict() + self.bulk_text = bulk_text + self.multiline_fields = ('description', 'examples') + self.data_dict['user_id'] = '' + + def __getitem__(self, key): + try: + return self.data_dict[key] + except : + return None + + def __setitem__(self, key, item): + # mapping to match form submission for code reuse + if key=='pubTests': + key = 'tests' + if key=='privTests': + key='other_tests' + if key=='userID': + key='user_id' + + self.data_dict[key] = item + + def __str__(self): + return str(self.bulk_text) + + def parse(self): + """ Parses a problem submission into data fillable in the submission + form + """ + chunks = self.bulk_text.split('#-') + for chunk in chunks[1:]: + # ^^ ignores the first comment line of the problem + chunk_key, chunk_data = chunk.split(':',1) + chunk_key = chunk_key.strip() + if chunk_key in self.multiline_fields: + # these are data surrounded in triple quotes, single or double + chunk_data = eval(chunk_data).strip('\r\n') + else: + chunk_data = chunk_data.strip().strip('\r\n') + self[chunk_key] = chunk_data + + def talk(self): + """ Just a testing function, a submission talks about itself to everyone + """ + print "Hi I am a submission problem on PyKata," + print "Let me tell you something about myself - " + print "I was created by -", self['userID'] + print "My name is -", self['name'] + print "I belong to these categories -", self['categories'] + print "Here, something more about myself --" + print self['description'] + print "---------------------------------------" + print "My solution --" + print self['solution'] + print "----------------------------------------" + print "My skeleton --" + print self['skeleton'] + print "----------------------------------------" + print "Public Tests --" + print self['pubTests'] + print "----------------------------------------" + print "Private Tests --" + print self['privTests'] + print "----------------------------------------" + print "\n So tell me something about you too?" + + +def test_submission_parse(): + import urllib2 +# example_file = urllib2.urlopen('http://ideamonk.in/code/foo.py').read() + example_file = open('/home/amit/foo2.py').read() + example_submissions = example_file.split('#---')[1:-1] + # ^^ ignore the first null string and last __main__ test code + print example_submissions + example_submissions = [ Submission(x) for x in example_submissions ] + + for key, a_submission in enumerate(example_submissions): + print "Problem #", key, "parsed as --" + print "*************************************************************" + a_submission.parse() + a_submission.talk() + +if __name__=='__main__': + # testing + test_submission_parse() + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/bulkuploader.pyc Binary file testappproj/testapp/helpers/bulkuploader.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/helpers/bulkuploader.py~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/helpers/bulkuploader.py~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,97 @@ +# UploadFormat Parser -- test version +# -- ideamonk + +class Submission(): + """ + A helper class for bulk uploads. It parses the given chunk of bulk + upload and tries to submit them to PyKata + """ + def __init__(self, bulk_text): + # initialize everything as default/blank as some things might not be + # present in submission + self.data_dict = dict() + self.bulk_text = bulk_text + self.multiline_fields = ('description', 'examples') + self.data_dict['user_id'] = '' + + def __getitem__(self, key): + try: + return self.data_dict[key] + except : + return None + + def __setitem__(self, key, item): + # mapping to match form submission for code reuse + if key=='pubTests': + key = 'tests' + if key=='privTests': + key='other_tests' + if key=='userID': + key='user_id' + + self.data_dict[key] = item + + def __str__(self): + return str(self.bulk_text) + + def parse(self): + """ Parses a problem submission into data fillable in the submission + form + """ + chunks = self.bulk_text.split('#-') + for chunk in chunks[1:]: + # ^^ ignores the first comment line of the problem + chunk_key, chunk_data = chunk.split(':',1) + chunk_key = chunk_key.strip() + if chunk_key in self.multiline_fields: + # these are data surrounded in triple quotes, single or double + chunk_data = eval(chunk_data).strip('\r\n') + else: + chunk_data = chunk_data.strip().strip('\r\n') + self[chunk_key] = chunk_data + + def talk(self): + """ Just a testing function, a submission talks about itself to everyone + """ + print "Hi I am a submission problem on PyKata," + print "Let me tell you something about myself - " + print "I was created by -", self['userID'] + print "My name is -", self['name'] + print "I belong to these categories -", self['categories'] + print "Here, something more about myself --" + print self['description'] + print "---------------------------------------" + print "My solution --" + print self['solution'] + print "----------------------------------------" + print "My skeleton --" + print self['skeleton'] + print "----------------------------------------" + print "Public Tests --" + print self['pubTests'] + print "----------------------------------------" + print "Private Tests --" + print self['privTests'] + print "----------------------------------------" + print "\n So tell me something about you too?" + + +def test_submission_parse(): + import urllib2 +# example_file = urllib2.urlopen('http://ideamonk.in/code/foo.py').read() + example_file = open('/home/amit/Downloads/foo.py').read() + example_submissions = example_file.split('#---')[1:-1] + # ^^ ignore the first null string and last __main__ test code + print example_submissions + example_submissions = [ Submission(x) for x in example_submissions ] + + for key, a_submission in enumerate(example_submissions): + print "Problem #", key, "parsed as --" + print "*************************************************************" + a_submission.parse() + a_submission.talk() + +if __name__=='__main__': + # testing + test_submission_parse() + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/management/__init__.py diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/management/__init__.pyc Binary file testappproj/testapp/management/__init__.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/management/commands/__init__.py diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/management/commands/__init__.pyc Binary file testappproj/testapp/management/commands/__init__.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/management/commands/seed_db.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/management/commands/seed_db.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,45 @@ +import sys +from datetime import datetime +from random import randrange + +from django.core.management.base import NoArgsCommand +from django.contrib.auth.models import User + + + + + + +from testapp.models import Test_User + + +def seed_db(): + """ a method to seed the database with random data """ + +# defaultMentor = userEvents.createSuUser("admin", "admin@example.com", "123456", datetime.now(), "M") +# mentor_profile = defaultMentor.get_profile() +# userEvents.updateProfile(mentor_profile, {'rights':"AD"}) + + for i in range(1,21): + + username = 'user'+str(i) + email = username+'@example.com' + password = '123456' + fullname='user user' +# dob = datetime.now() +# gender = "M" +# user = userEvents.createUser(username,email,password,dob,gender) +# create_notification("NU", user) + user=User.objects.create_user(username=username,email=email,password=password) + user.is_active = True + user.save() + test_user=Test_User(user_id=user.id,fullname=fullname) + test_user.save() + + +class Command(NoArgsCommand): + + def handle_noargs(self, **options): + """ Just copied the code from seed_db.py """ + + seed_db() diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/management/commands/seed_db.pyc Binary file testappproj/testapp/management/commands/seed_db.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/management/commands/seed_db.py~ diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/models.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/models.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,70 @@ +from django.db import models +from django.contrib.auth.models import User +from django.contrib.auth.models import Group, Permission + + + +# class ProblemPermission(models.Model): +# """Abstract page permissions +# """ +# #who +# user = models.ForeignKey(User) +# #what +# can_change = models.BooleanField("can edit", default=False) +# can_add = models.BooleanField("can add", default=False) +# can_delete = models.BooleanField("can delete", default=False) + + +# class Meta: +# abstract = True +# app_label = 'testapp' + +PROBLEM_CHOICES=( + ('P', 'Plotting'), + ('S', 'Scripting'), +) + + +SESSION_CHOICES=( + ('A','DAY 1 SESSION 1'), + ('B','DAY 1 SESSION 2'), + ('C','DAY 1 SESSION 3'), + ('D','DAY 1 SESSION 4'), + ('E','DAY 2 SESSION 1'), + ('F','DAY 2 SESSION 2'), + ('G','DAY 2 SESSION 3'), + ('H','DAY 1 SESSION 4'), + ) + +class Problem(models.Model): + # name = models.CharField(blank=False,max_length=255) + description = models.CharField(blank=False , max_length=255) + problem_type=models.CharField(blank = False ,max_length=1, choices=PROBLEM_CHOICES) + solution = models.CharField(blank=True ,max_length=255) + solution_image = models.ImageField(blank = True ,upload_to='plots') + session = models.CharField(blank=False ,max_length=1,choices=SESSION_CHOICES) + author = models.CharField(max_length=255) + created = models.DateTimeField() + modified = models.DateTimeField() + + + + #if user.has_perm('testapp.add_bar') and user.has_perm('foo.change_bar') and user.has_perm('foo.delete_bar') + +class Test_User(models.Model): + #problem = models.ForeignKey('Problem') + user = models.ForeignKey(User, unique=True) + fullname=models.CharField(max_length=255) + + + + + + + + + + + + + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/models.pyc Binary file testappproj/testapp/models.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/models.py~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/models.py~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,25 @@ +from django.db import models + + +class Problem(models.Model): + name = models.CharField(blank=False,max_length=255) +# categories = models.() + description = models.CharField(max_length=255) + examples = models.CharField(max_length=255) + skeleton = models.CharField(max_length=255) + tests = models.CharField(max_length=255) + other_tests = models.CharField(max_length=255) + solution = models.CharField(max_length=255) + author = models.CharField(max_length=255) + created = models.DateTimeField() + modified = models.DateTimeField() + + +class ProblemUser(models.Model): + problem = models.ForeignKey('Problem') + # user = models.UserProperty() + solution = models.CharField(max_length=255) + solved = models.BooleanField() + def classname(self): + return "ProblemUser" + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/tests.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/tests.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/views (copy).py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/views (copy).py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,386 @@ +# Python imports +import doctest +import logging +import os +import traceback + +# # AppEngine imports + +from django.contrib.auth.models import User + +from testappproj.testapp.models import * +from django.http import HttpResponse + +# from google.appengine.api import users +# from google.appengine.ext.webapp import template + +# from google.appengine.ext import db +# from google.appengine.ext.db import djangoforms + + +# Django imports +#from django.conf import settings +#settings._target = None +#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' +#import django +from django import http +from django import shortcuts +from django.template import Context ,RequestContext +from django.template.loader import get_template + +# Local imports +from forms import * +import models +from helpers import bulkuploader as pykataupload +from datetime import date + + +def respond(request, user,template, params=None): + """Helper to render a response, passing standard stuff to the response. + + Args: + request: The request object. + user: The User object representing the current user; or None if nobody + is logged in. + template: The template name; '.html' is appended automatically. + params: A dict giving the template parameters; modified in-place. + + Returns: + Whatever render_to_response(template, params) returns. + + Raises: + Whatever render_to_response(template, params) raises. + """ + if params is None: + params = {} + if user: + params['user'] = user + params['sign_out'] = 1 + # params['is_admin'] = (users.is_current_user_admin()) + else: + params['sign_in'] = 1 + # if not template.endswith('.html'): + template += '.html' + return shortcuts.render_to_response(template, params) + +def execute_test_cases(request, test_cases, g): + li = [] + + solved = True + for e in test_cases: + if not e.want: + exec e.source in g + continue + call = e.source.strip() + got = eval(e.source.strip(), g) + expected = eval(e.want, g) + + if got == expected: + status = 'pass' + else: + status = 'fail' + solved = False + li.append([call, expected, "%r" % got, status]) + + return li, solved + + + + +def index(request): + """ need to change user in the django.contrib way""" + + user = request.user + + return respond(request , user, 'index') + +# def contribution(request): +# # user = users.get_current_user() +# return respond(request, user, 'contribution') + +# def help(request): +# # user = users.get_current_user() +# return respond(request, user, 'help') + +# def about(request): +# # user = users.get_current_user() +# return respond(request, user, 'about') + +# def vision(request): +# # user = users.get_current_user() +# return respond(request, user, 'vision') + +# def statements(request): +# # user = users.get_current_user() +# return respond(request, user, 'statements') + + +def get_pu(problem): + ''' + returns: + - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor + - "PU_NOT_FOUND": for signed in users when no solution has been attempted. + - ProblemUser: for signed in users when a solution has been attempted + + ''' +# user = users.get_current_user() +# if not user: +# return "USER_NOT_SIGNED_IN" + pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user()) + pu_results = pu_query.fetch(1) + if pu_results: + return pu_results[0] + return "PU_NOT_FOUND" + +def is_solved(problem): + pu = get_pu(problem) + if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False + return pu.solved + +def problems(request, category=None): + user = request.user + + # if category is None: + # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC') + # else: + # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category) + + + + + # entries = [] + # for problem in problems: + # e = dict(problem=problem, + # username=problem.author.nickname().partition('@')[0], + # solved=is_solved(problem)) + # entries.append(e) + # problems = entries + entries=[] + problems=Problem.objects.all() + for problem in problems: + e = dict(problem=problem.name, + username=user.username, + problem_id=problem.id + ) + entries.append(e) + +# print entries + + + + return respond(request, user, 'problems',{'entries' : entries } ) + +def code(request, problem_id): + + print problem_id + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + +# pu = get_pu(problem) +# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time +# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False) +# pu.put() +# pu = None + + return respond(request, request.user ,'code' , ) + +def run(request): + user = request.user + problem_id = request.POST.get('problem_id') + if problem_id: + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + + user_code = request.POST.get('user_code') + + if not user_code: + return http.HttpResponse('bad request') + + # pu = get_pu(problem) + # # update ProblemUser object for this user + # if (pu.__class__ == models.ProblemUser): + # pu.solution = user_code + # pu.put() + + user_code = user_code.replace('\r\n', '\n') + user_code += '\n\n' + + errors = '' + + + try: + print user_code + compiled = compile(user_code, 'error_file', 'exec') + g = {} + exec compiled in g + +# s = problem.tests.replace('\r\n', '\n') +# s += '\n\n' + # test_cases = doctest.DocTestParser().get_examples(s) + # results, solved = execute_test_cases(request, test_cases, g) + # if solved: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = True + # pu.put() + # else: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = False + # pu.put() + except: + errors = traceback.format_exc() + return respond(request, user, 'traceback', {'errors': errors}) + results="solved" + return respond(request, request.user, 'run', {'results': results}) + +def new_edit(request, problem_id=None, internal=False): + # internal indicates that it is being called internally by uploader + # + user = request.user + print user.username + if user.is_anonymous() : + return http.HttpResponseForbidden('You must be an signed in to create edit a problem.') + + if problem_id is None: + creating_new = True + else: + creating_new = False + + problem = None + # if problem_id: + # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id))) + # if problem.author != user and not users.is_current_user_admin(): + # return http.HttpResponseForbidden('You can only edit your own problems.') + # if problem is None: + # return http.HttpResponseNotFound('No such problem.') + + form = ProblemForm(data=request.POST or None, instance=problem) + upload_form = UploadForm(data=request.POST) + + if not request.POST: + return respond(request, user, 'new_edit_problem', {'form':form, 'problem':problem, 'creating':creating_new , 'upload_form' : upload_form }) + + + errors = form.errors + if not errors: + try: + problem = form.save(commit=False) + except ValueError, err: + errors['__all__'] = unicode(err) + + + if errors: + print "new world" + if internal: + return ('error',errors) + return respond(request, user, 'new_edit_problem', + {'form': form, 'problem':problem, 'creating':creating_new}) + + if creating_new: + # if internal: + # if len(request.POST['user_id'])>0: + # logging.info(request.POST) + # problem.author = users.User(request.POST['user_id']) + # else: + # problem.author = user + # else: + + + + + problem.author = user.username + problem.created = date.today() + problem. modified=date.today() + + problem.save() +# l = [] + # for x in problem.categories: + # l.extend(x.split()) + # problem.categories = l + # problem.put() + + if internal: + return ('success','success') + + + return http.HttpResponseRedirect('/problems') + +def upload(request): + """ upload handler, validates the form and calls handle_uploaded_file + for processing further + """ + user = request.user + if user is None: + return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.') + + if request.method == 'POST': + form = UploadForm(request.POST, request.FILES) + if form.is_valid(): + submission_report = handle_uploaded_file(request) + print "testing" + print submission_report + + return respond(request, user, 'upload', {'report':submission_report}) + else: + return http.HttpResponseForbidden('Oops something went wrong with the upload') + +def handle_uploaded_file(request): + """ Handles uploaded data, pushes it to existing problem creating code + TODO: 1. make efficient by putting actual database code Here + 2. Add more security and validation + """ + submission_data = request.FILES['file'].read() + if '#---' in submission_data: + all_submissions = submission_data.split('#---')[1:-1] + # ^^ ignoring the first null and last __main__ code + all_submissions = [ pykataupload.Submission(x) for x in all_submissions ] + report = [] + + for key,each_submission in enumerate(all_submissions): + # TODO: handle these later by TaskQueues to avoid timeouts on big uploads + # a good way would be to have ajax based status coming back to this page + # about each problem in the uploaded file, their status, progress etc. + each_submission.parse() + request.POST.clear() + request.POST.update (each_submission.data_dict) + upload_status, upload_response = new_edit(request, internal=True) + + report.append ({'status':upload_status, 'name':each_submission['name'], + 'upload_response':upload_response}) + + # Yay this hack works :D + return report + else: + return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.') + +def shell(request): + """ need to change user in the django.contrib way""" + + user = request.user + statement=request.GET.get('statement','') + if statement is not '': + + # the python compiler doesn't like network line endings + statement = statement.replace('\r\n', '\n') + + # add a couple newlines at the end of the statement. this makes + # single-line expressions such as 'class Foo: pass' evaluate happily. + statement += '\n\n' + print "statement"+statement + # log and compile the statement up front + try: + logging.info('Compiling and evaluating:\n%s' % statement) + compiled = compile(statement, '', 'single') + except: + return HttpResponse(traceback.format_exc(),mimetype="text/plain") +# pass + return HttpResponse("",mimetype="text/plain") + else: + return respond(request, user, 'shell') + + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/views.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,439 @@ +# Python imports +import doctest +import logging +import os +import traceback +import random + + +# # AppEngine imports + +from django.contrib.auth.models import User + +from testappproj.testapp.models import * +from django.http import HttpResponse + +# from google.appengine.api import users +# from google.appengine.ext.webapp import template + +# from google.appengine.ext import db +# from google.appengine.ext.db import djangoforms + + +# Django imports +#from django.conf import settings +#settings._target = None +#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' +#import django +from django import http +from django import shortcuts +from django.template import Context ,RequestContext +from django.template.loader import get_template + +# Local imports +from forms import * +import models +from helpers import bulkuploader as pykataupload +from datetime import date +from django.contrib.auth.decorators import permission_required +from models import Problem + + +def respond(request, user,template, params=None): + """Helper to render a response, passing standard stuff to the response. + + Args: + request: The request object. + user: The User object representing the current user; or None if nobody + is logged in. + template: The template name; '.html' is appended automatically. + params: A dict giving the template parameters; modified in-place. + + Returns: + Whatever render_to_response(template, params) returns. + + Raises: + Whatever render_to_response(template, params) raises. + """ + if params is None: + params = {} + if user: + params['user'] = user + params['sign_out'] = 1 + # params['is_admin'] = (users.is_current_user_admin()) + else: + params['sign_in'] = 1 + # if not template.endswith('.html'): + template += '.html' + return shortcuts.render_to_response(template, params) + +def execute_test_cases(request, test_cases, g): + li = [] + + solved = True + for e in test_cases: + if not e.want: + exec e.source in g + continue + call = e.source.strip() + got = eval(e.source.strip(), g) + expected = eval(e.want, g) + + if got == expected: + status = 'pass' + else: + status = 'fail' + solved = False + li.append([call, expected, "%r" % got, status]) + + return li, solved + + + + +def index(request): + """ need to change user in the django.contrib way""" + + user = request.user + + return respond(request , user, 'index') + +# def contribution(request): +# # user = users.get_current_user() +# return respond(request, user, 'contribution') + +# def help(request): +# # user = users.get_current_user() +# return respond(request, user, 'help') + +# def about(request): +# # user = users.get_current_user() +# return respond(request, user, 'about') + +# def vision(request): +# # user = users.get_current_user() +# return respond(request, user, 'vision') + +# def statements(request): +# # user = users.get_current_user() +# return respond(request, user, 'statements') + + +def get_pu(problem): + ''' + returns: + - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor + - "PU_NOT_FOUND": for signed in users when no solution has been attempted. + - ProblemUser: for signed in users when a solution has been attempted + + ''' +# user = users.get_current_user() +# if not user: +# return "USER_NOT_SIGNED_IN" + pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user()) + pu_results = pu_query.fetch(1) + if pu_results: + return pu_results[0] + return "PU_NOT_FOUND" + +# def is_solved(problem): +# pu = get_pu(problem) +# if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False +# return pu.solved + +def problems(request, category=None): + user = request.user + + # if category is None: + # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC') + # else: + # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category) + + + + + # entries = [] + # for problem in problems: + # e = dict(problem=problem, + # username=problem.author.nickname().partition('@')[0], + # solved=is_solved(problem)) + # entries.append(e) + # problems = entries + entries=[] + all_sessions=set([element.session for element in Problem.objects.all()]) + print all_sessions + + # for problem in problems: + # e = dict(problem=problem.description, + # username=user.username, + # problem_id=problem.id + + # ) + # entries.append(e) + +# print entries + + + #get problems to solve from each session. + for session in all_sessions: + get_problem=random.Random().choice(Problem.objects.filter(session=session)) + e = dict(problem=get_problem.description, + username=user.username, + problem_id=get_problem.id, + session =get_problem.session + ) + entries.append(e) + + + return respond(request, user, 'problems',{'entries' : entries } ) + +def code(request, problem_id): + + print problem_id + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + +# pu = get_pu(problem) +# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time +# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False) +# pu.put() +# pu = None + + return respond(request, request.user ,'code' , ) + +def run(request): + user = request.user + problem_id = request.POST.get('problem_id') + if problem_id: + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + + user_code = request.POST.get('user_code') + + if not user_code: + return http.HttpResponse('bad request') + + # pu = get_pu(problem) + # # update ProblemUser object for this user + # if (pu.__class__ == models.ProblemUser): + # pu.solution = user_code + # pu.put() + + user_code = user_code.replace('\r\n', '\n') + user_code += '\n\n' + + errors = '' + + + try: + print user_code + compiled = compile(user_code, 'error_file', 'exec') + g = {} + exec compiled in g + +# s = problem.tests.replace('\r\n', '\n') +# s += '\n\n' + # test_cases = doctest.DocTestParser().get_examples(s) + # results, solved = execute_test_cases(request, test_cases, g) + # if solved: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = True + # pu.put() + # else: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = False + # pu.put() + except: + errors = traceback.format_exc() + return respond(request, user, 'traceback', {'errors': errors}) + results="solved" + return respond(request, request.user, 'run', {'results': results}) + + +@permission_required('testapp.add_problem' , login_url="/code/1234") +def new_edit(request, problem_id=None, internal=False): + + + + # internal indicates that it is being called internally by uploader + # + user = request.user +# print user.get_all_permissions() + print user.username + if user.is_anonymous() : + return http.HttpResponseForbidden('You must be an signed in to create edit a problem.') + + if problem_id is None: + creating_new = True + else: + creating_new = False + +# problem = None + # if problem_id: + # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id))) + # if problem.author != user and not users.is_current_user_admin(): + # return http.HttpResponseForbidden('You can only edit your own problems.') + # if problem is None: + # return http.HttpResponseNotFound('No such problem.') + +# formset = ProblemForm(data=request.POST) +# instance=formset.save() +# # upload_form = UploadForm(data=request.POST) + + if request.method == 'POST': + form = ProblemForm(request.POST) + else: + form = ProblemForm() + + + + if not request.POST: + return respond(request, user, 'new_edit_problem', {'form':form, 'problem':None, 'creating':creating_new }) + +# print form + #errors = form.errors + #print str(errors)+"errors" + + + #if not errors: + # try: + + if form.is_valid(): + + description = form.cleaned_data['Description'] + problem_type=form.cleaned_data['Problem_type'] + solution=form.cleaned_data['Solution'] + session=form.cleaned_data['Session'] + + author = user.username + created = date.today() + modified=date.today() + + problem=Problem(description=description,problem_type=problem_type,solution=solution,session=session,author=author,created=created,modified=modified) + + problem.save() + print "saved" + else: + print "form is valid" + print form.errors + +# print form.errors + # except ValueError, err: + # errors['__all__'] = unicode(err) + + + # if errors: + # print "new world" + # if internal: + + # print errors + # return ('error',errors) + # return respond(request, user, 'new_edit_problem', + # {'form': form, 'problem':problem, 'creating':creating_new,'error':errors}) + + # if creating_new: + # # if internal: + # # if len(request.POST['user_id'])>0: + # # logging.info(request.POST) + # # problem.author = users.User(request.POST['user_id']) + # # else: + # # problem.author = user + # # else: + + + + + + +# l = [] + # for x in problem.categories: + # l.extend(x.split()) + # problem.categories = l + # problem.put() + + if internal: + return ('success','success') + + + return http.HttpResponseRedirect('/problems') + +def upload(request): + """ upload handler, validates the form and calls handle_uploaded_file + for processing further + """ + user = request.user + if user is None: + return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.') + + if request.method == 'POST': + form = UploadForm(request.POST, request.FILES) + if form.is_valid(): + submission_report = handle_uploaded_file(request) + print "testing" + print submission_report + + return respond(request, user, 'upload', {'report':submission_report}) + else: + return http.HttpResponseForbidden('Oops something went wrong with the upload') + +def handle_uploaded_file(request): + """ Handles uploaded data, pushes it to existing problem creating code + TODO: 1. make efficient by putting actual database code Here + 2. Add more security and validation + """ + submission_data = request.FILES['file'].read() + if '#---' in submission_data: + all_submissions = submission_data.split('#---')[1:-1] + # ^^ ignoring the first null and last __main__ code + all_submissions = [ pykataupload.Submission(x) for x in all_submissions ] + report = [] + + for key,each_submission in enumerate(all_submissions): + # TODO: handle these later by TaskQueues to avoid timeouts on big uploads + # a good way would be to have ajax based status coming back to this page + # about each problem in the uploaded file, their status, progress etc. + each_submission.parse() + request.POST.clear() + request.POST.update (each_submission.data_dict) + upload_status, upload_response = new_edit(request, internal=True) + + report.append ({'status':upload_status, 'name':each_submission['name'], + 'upload_response':upload_response}) + + # Yay this hack works :D + return report + else: + return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.') + +def shell(request): + """ need to change user in the django.contrib way""" + + user = request.user + statement=request.GET.get('statement','') + if statement is not '': + + # the python compiler doesn't like network line endings + statement = statement.replace('\r\n', '\n') + + # add a couple newlines at the end of the statement. this makes + # single-line expressions such as 'class Foo: pass' evaluate happily. + statement += '\n\n' + print "statement"+statement + # log and compile the statement up front + try: + logging.info('Compiling and evaluating:\n%s' % statement) + compiled = compile(statement, '', 'single') + except: + return HttpResponse(traceback.format_exc(),mimetype="text/plain") +# pass + return HttpResponse("",mimetype="text/plain") + else: + return respond(request, user, 'shell') + + diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/views.pyc Binary file testappproj/testapp/views.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/testapp/views.py~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/testapp/views.py~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,368 @@ +# Python imports +import doctest +import logging +import os +import traceback + +# # AppEngine imports + +from django.contrib.auth.models import User + +from testappproj.testapp.models import * +from django.http import HttpResponse + +# from google.appengine.api import users +# from google.appengine.ext.webapp import template + +# from google.appengine.ext import db +# from google.appengine.ext.db import djangoforms + + +# Django imports +#from django.conf import settings +#settings._target = None +#os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' +#import django +from django import http +from django import shortcuts +from django.template import Context ,RequestContext +from django.template.loader import get_template + +# Local imports +from forms import * +import models +from helpers import bulkuploader as pykataupload +from datetime import date + + +def respond(request, user,template, params=None): + """Helper to render a response, passing standard stuff to the response. + + Args: + request: The request object. + user: The User object representing the current user; or None if nobody + is logged in. + template: The template name; '.html' is appended automatically. + params: A dict giving the template parameters; modified in-place. + + Returns: + Whatever render_to_response(template, params) returns. + + Raises: + Whatever render_to_response(template, params) raises. + """ + if params is None: + params = {} + if user: + params['user'] = user + params['sign_out'] = 1 + # params['is_admin'] = (users.is_current_user_admin()) + else: + params['sign_in'] = 1 + # if not template.endswith('.html'): + template += '.html' + return shortcuts.render_to_response(template, params) + +def execute_test_cases(request, test_cases, g): + li = [] + + solved = True + for e in test_cases: + if not e.want: + exec e.source in g + continue + call = e.source.strip() + got = eval(e.source.strip(), g) + expected = eval(e.want, g) + + if got == expected: + status = 'pass' + else: + status = 'fail' + solved = False + li.append([call, expected, "%r" % got, status]) + + return li, solved + + + + +def index(request): + """ need to change user in the django.contrib way""" + + user = request.user + + return respond(request , user, 'index') + +# def contribution(request): +# # user = users.get_current_user() +# return respond(request, user, 'contribution') + +# def help(request): +# # user = users.get_current_user() +# return respond(request, user, 'help') + +# def about(request): +# # user = users.get_current_user() +# return respond(request, user, 'about') + +# def vision(request): +# # user = users.get_current_user() +# return respond(request, user, 'vision') + +# def statements(request): +# # user = users.get_current_user() +# return respond(request, user, 'statements') + + +def get_pu(problem): + ''' + returns: + - "USER_NOT_SIGNED_IN": user not signed in. returning this to prevent saving anonymous user's potentially crappy solution and display it to every anonymous visitor + - "PU_NOT_FOUND": for signed in users when no solution has been attempted. + - ProblemUser: for signed in users when a solution has been attempted + + ''' +# user = users.get_current_user() +# if not user: +# return "USER_NOT_SIGNED_IN" + pu_query = models.ProblemUser.all().filter('problem = ', problem).filter('user =', users.get_current_user()) + pu_results = pu_query.fetch(1) + if pu_results: + return pu_results[0] + return "PU_NOT_FOUND" + +def is_solved(problem): + pu = get_pu(problem) + if pu == "PU_NOT_FOUND" or pu == "USER_NOT_SIGNED_IN": return False + return pu.solved + +def problems(request, category=None): + user = request.user + + # if category is None: + # problems = db.GqlQuery('SELECT * FROM Problem ORDER BY created DESC') + # else: + # problems = db.GqlQuery('SELECT * FROM Problem WHERE categories = :1 ORDER BY created DESC', category) + + + + + # entries = [] + # for problem in problems: + # e = dict(problem=problem, + # username=problem.author.nickname().partition('@')[0], + # solved=is_solved(problem)) + # entries.append(e) + # problems = entries + entries=[] + problems=Problem.objects.all() + for problem in problems: + e = dict(problem=problem.name, + username=user.username, + problem_id=problem.id + ) + entries.append(e) + +# print entries + + + + return respond(request, user, 'problems',{'entries' : entries } ) + +def code(request, problem_id): + + print problem_id + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + +# pu = get_pu(problem) +# if pu == "PU_NOT_FOUND": # user is attempting problem for the first time +# pu = models.ProblemUser(problem=problem, user=users.get_current_user(), solution='', solved=False) +# pu.put() +# pu = None + + return respond(request, request.user ,'code' , ) + +def run(request): + user = request.user + problem_id = request.POST.get('problem_id') + if problem_id: + problem = Problem.objects.get(id=int(problem_id)) + + if problem is None: + return http.HttpResponseNotFound('No such problem.') + + user_code = request.POST.get('user_code') + + if not user_code: + return http.HttpResponse('bad request') + + # pu = get_pu(problem) + # # update ProblemUser object for this user + # if (pu.__class__ == models.ProblemUser): + # pu.solution = user_code + # pu.put() + + user_code = user_code.replace('\r\n', '\n') + user_code += '\n\n' + + errors = '' + + + try: + print user_code + compiled = compile(user_code, 'error_file', 'exec') + g = {} + exec compiled in g + +# s = problem.tests.replace('\r\n', '\n') +# s += '\n\n' + # test_cases = doctest.DocTestParser().get_examples(s) + # results, solved = execute_test_cases(request, test_cases, g) + # if solved: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = True + # pu.put() + # else: + # pu = get_pu(problem) + # if pu.__class__ == models.ProblemUser: + # pu.solved = False + # pu.put() + except: + errors = traceback.format_exc() + return respond(request, user, 'traceback', {'errors': errors}) + results="solved" + return respond(request, request.user, 'run', {'results': results}) + +def new_edit(request, problem_id=None, internal=False): + # internal indicates that it is being called internally by uploader + # + user = request.user + print user.username + if user.is_anonymous() : + return http.HttpResponseForbidden('You must be an signed in to create edit a problem.') + + if problem_id is None: + creating_new = True + else: + creating_new = False + + problem = None + # if problem_id: + # problem = models.Problem.get(db.Key.from_path(models.Problem.kind(), int(problem_id))) + # if problem.author != user and not users.is_current_user_admin(): + # return http.HttpResponseForbidden('You can only edit your own problems.') + # if problem is None: + # return http.HttpResponseNotFound('No such problem.') + + form = ProblemForm(data=request.POST or None, instance=problem) + upload_form = UploadForm(data=request.POST) + + if not request.POST: + return respond(request, user, 'new_edit_problem', {'form':form, 'problem':problem, 'creating':creating_new , 'upload_form' : upload_form }) + + + errors = form.errors + if not errors: + try: + problem = form.save(commit=False) + except ValueError, err: + errors['__all__'] = unicode(err) + + + if errors: + print "new world" + if internal: + return ('error',errors) + return respond(request, user, 'new_edit_problem', + {'form': form, 'problem':problem, 'creating':creating_new}) + + if creating_new: + # if internal: + # if len(request.POST['user_id'])>0: + # logging.info(request.POST) + # problem.author = users.User(request.POST['user_id']) + # else: + # problem.author = user + # else: + + + + + problem.author = user.username + problem.created = date.today() + problem. modified=date.today() + + problem.save() +# l = [] + # for x in problem.categories: + # l.extend(x.split()) + # problem.categories = l + # problem.put() + + if internal: + return ('success','success') + + + return http.HttpResponseRedirect('/problems') + +def upload(request): + """ upload handler, validates the form and calls handle_uploaded_file + for processing further + """ + user = request.user + if user is None: + return http.HttpResponseForbidden('You must be an signed in to create/edit a problem.') + + if request.method == 'POST': + form = UploadForm(request.POST, request.FILES) + if form.is_valid(): + submission_report = handle_uploaded_file(request) + print "testing" + print submission_report + + return respond(request, user, 'upload', {'report':submission_report}) + else: + return http.HttpResponseForbidden('Oops something went wrong with the upload') + +def handle_uploaded_file(request): + """ Handles uploaded data, pushes it to existing problem creating code + TODO: 1. make efficient by putting actual database code Here + 2. Add more security and validation + """ + submission_data = request.FILES['file'].read() + if '#---' in submission_data: + all_submissions = submission_data.split('#---')[1:-1] + # ^^ ignoring the first null and last __main__ code + all_submissions = [ pykataupload.Submission(x) for x in all_submissions ] + report = [] + + for key,each_submission in enumerate(all_submissions): + # TODO: handle these later by TaskQueues to avoid timeouts on big uploads + # a good way would be to have ajax based status coming back to this page + # about each problem in the uploaded file, their status, progress etc. + each_submission.parse() + request.POST.clear() + request.POST.update (each_submission.data_dict) + upload_status, upload_response = new_edit(request, internal=True) + + report.append ({'status':upload_status, 'name':each_submission['name'], + 'upload_response':upload_response}) + + # Yay this hack works :D + return report + else: + return http.HttpResponseForbidden('The file you uploaded is not in appropriate format.') + +def shell(request): + """ need to change user in the django.contrib way""" + + user = request.user + print request.GET.get('statement') + return respond(request , user, 'shell') + + diff -r 000000000000 -r 0b061d58aea3 testappproj/urls.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/urls.py Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,44 @@ +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Top-level URL mappings for Rietveld.""" + +# NOTE: Must import *, since Django looks for things here, e.g. handler500. +import os +import sys +from django.conf.urls.defaults import * +from registration.views import register +from testappproj.testapp.forms import Test_UserForm +from django.contrib import admin +admin.autodiscover() + + + +urlpatterns = patterns('', + (r'^$', 'testappproj.testapp.views.index'), + url(r'^accounts/register/$',register,{'form_class' : Test_UserForm},name='registration_register'), + (r'^accounts/', include('registration.urls')), + (r'^code/(\d+)/$', 'testappproj.testapp.views.code'), + (r'^admin/(.*)', admin.site.root), + (r'^new/$', 'testappproj.testapp.views.new_edit'), + (r'^problems/$', 'testappproj.testapp.views.problems'), + (r'^run/$', 'testappproj.testapp.views.run'), + (r'^upload/$', 'testappproj.testapp.views.upload'), + (r'^static/(?P.*)$', 'django.views.static.serve', + {'document_root': os.path.realpath(os.path.dirname( + sys.modules[__name__].__file__) + '/static/')}), + (r'^shell/$', 'testappproj.testapp.views.shell') + +) + diff -r 000000000000 -r 0b061d58aea3 testappproj/urls.pyc Binary file testappproj/urls.pyc has changed diff -r 000000000000 -r 0b061d58aea3 testappproj/urls.py~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testappproj/urls.py~ Mon May 17 22:33:59 2010 +0530 @@ -0,0 +1,44 @@ +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Top-level URL mappings for Rietveld.""" + +# NOTE: Must import *, since Django looks for things here, e.g. handler500. +import os +import sys +from django.conf.urls.defaults import * +from registration.views import register +from testappproj.testapp.forms import Tets_UserForm +from django.contrib import admin +admin.autodiscover() + + + +urlpatterns = patterns('', + (r'^$', 'testappproj.testapp.views.index'), + url(r'^accounts/register/$',register,{'form_class' : Test_UserForm},name='registration_register'), + (r'^accounts/', include('registration.urls')), + (r'^code/(\d+)/$', 'testappproj.testapp.views.code'), + (r'^admin/(.*)', admin.site.root), + (r'^new/$', 'testappproj.testapp.views.new_edit'), + (r'^problems/$', 'testappproj.testapp.views.problems'), + (r'^run/$', 'testappproj.testapp.views.run'), + (r'^upload/$', 'testappproj.testapp.views.upload'), + (r'^static/(?P.*)$', 'django.views.static.serve', + {'document_root': os.path.realpath(os.path.dirname( + sys.modules[__name__].__file__) + '/static/')}), + (r'^shell/$', 'testappproj.testapp.views.shell') + +) +