# Python imports
import doctest
import logging
import os
import traceback
import random
import StringIO
import sys
# # AppEngine imports
from django.contrib.auth.models import User
from testappproj.testapp.models import *
from django.http import HttpResponse
# 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
from django.contrib.auth.decorators import login_required
from models import Score
import time
# def handle_uploaded_file(f):
# print f
# destination = open('some/file/name.txt', 'wb+')
# for chunk in f.chunks():
# destination.write(chunk)
# destination.close()
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_plotting_test_cases(user_code , solution_image,problem_id , username):
print user_code
print "solution"+solution_image
image_name = username+'_'+str(problem_id)+'_'+time.time()
code="""from pylab import *
%s
show()"""%user_code
solved=False
# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()
# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr
exec code
# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
s = codeOut.getvalue()
s=unicode(s)
print s.strip()
print solution.strip()
if solution.strip() == s.strip():
solved =True
errors=codeErr.getvalue()
codeOut.close()
codeErr.close()
return solved,errors
def execute_test_cases(code , solution):
print code
print "solution"+solution
solved=False
# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()
# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr
exec code
# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
s = codeOut.getvalue()
s=unicode(s)
print s.strip()
print solution.strip()
if solution.strip() == s.strip():
solved =True
errors=codeErr.getvalue()
codeOut.close()
codeErr.close()
return solved,errors
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
@login_required(function=None, redirect_field_name='next')
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 } )
@login_required(function=None, redirect_field_name='next')
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
print problem.id
return respond(request, request.user ,'code' ,{'problem' : problem } )
def run(request):
user = request.user
print request.POST
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)
solved,errors = execute_test_cases(user_code,problem.solution)
# 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()
if solved==True:
#user is answering his first question
try:
# print user.id
score_for_user= Score.objects.get(user=user)
score_for_user.total_credits+=problem.credit
score_for_user.save()
# user has answered questions previously
except Score.DoesNotExist:
# print user.id
score_new_user=user.id
score_total_credits=problem.credit
score=Score(user_id=user.id,total_credits=score_total_credits)
score.save()
else:
print "oops"
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
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
if request.method == 'POST':
form = ProblemForm(request.POST, request.FILES)
else:
form = ProblemForm()
if not request.POST:
return respond(request, user, 'new_edit_problem', {'form':form, 'problem':None, 'creating':creating_new })
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']
credit=form.cleaned_data['Credit']
# solution_image=form.cleaned_data['Solution_Image']
solution_image=request.FILES['Solution_Image']
author = user.username
created = date.today()
modified=date.today()
# print request.FILES
# print "this is solution"+solution
# print "this is solution_image"+solution_image
problem=Problem(description=description,problem_type=problem_type,solution_image=solution_image,session=session,author=author,created=created,modified=modified,credit=credit)
problem.save()
print "saved"
else:
print "form is valid"
print form.errors
# print form.errors
# except ValueError, err:
# errors['__all__'] = unicode(err)
if form.errors:
print "new world"
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, '<string>', 'single')
except:
return HttpResponse(traceback.format_exc(),mimetype="text/plain")
# pass
return HttpResponse("",mimetype="text/plain")
else:
return respond(request, user, 'shell')