Fix https://code.google.com/p/soc/issues/detail?id=2264

Add links to T-Shirt sizing charts.
Merge commit '9e64720'
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6676011
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,41 @@
+# Copyright 2014 the Melange authors.
+#
+# 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.
+
+# setup target sets up the basics of the development environment
+setup:
+	virtualenv venv
+	venv/bin/pip install -U lxml setuptools
+	venv/bin/python bootstrap.py
+	bin/buildout
+	bin/gen-app-yaml local-devel
+	bin/paver build --skip-pylint
+
+# run all the tests
+test:
+	bin/run-tests
+
+# run only the lint tests
+pylint:
+	bin/run-tests -t pylint
+
+lint: pylint
+
+# start a local instance. defaults to port 8080 for the app and 8000
+# for the appengine console
+localserver:
+	thirdparty/google_appengine/dev_appserver.py build
+
+# return to a pristine git checkout.  *DELETES EVERYTHING WITHOUT PROMPTING*
+gitclean:
+	git clean -xdf
diff --git a/app/app.yaml.template b/app/app.yaml.template
index 0de1f2a..db96f86 100644
--- a/app/app.yaml.template
+++ b/app/app.yaml.template
@@ -15,7 +15,7 @@
 # TODO(proto): uncomment and supply a Google App Engine application instance
 # application: FIXME
 # TODO(release): see the instructions in README about the "version:" field
-version: 2-1-20140626
+version: 2-1-20140702
 runtime: python27
 api_version: 1
 threadsafe: false
diff --git a/app/soc/modules/gci/views/org_home.py b/app/soc/modules/gci/views/org_home.py
index f0c33a4..1f36b08 100644
--- a/app/soc/modules/gci/views/org_home.py
+++ b/app/soc/modules/gci/views/org_home.py
@@ -16,6 +16,8 @@
 
 from django.utils.translation import ugettext
 
+from google.appengine.ext import ndb
+
 from melange.request import access
 from melange.request import exception
 from melange.request import links
@@ -125,9 +127,14 @@
 
     list_config = lists.ListConfiguration()
 
+    def _getStudent(entity, *args):
+      """Helper function to get value for student column."""
+      student_key = ndb.Key.from_old_key(
+          GCITask.student.get_value_for_datastore(entity))
+      return student_key.get().public_name
+
     list_config.addSimpleColumn('title', 'Title')
-    list_config.addPlainTextColumn('student', 'Student',
-        lambda entity, *args: entity.student.name())
+    list_config.addPlainTextColumn('student', 'Student', _getStudent)
     list_config.addPlainTextColumn('types', 'Type',
         lambda entity, *args: ", ".join(entity.types))
 
diff --git a/app/soc/modules/gsoc/logic/grading_record.py b/app/soc/modules/gsoc/logic/grading_record.py
index 628112f..f7c8a7c 100644
--- a/app/soc/modules/gsoc/logic/grading_record.py
+++ b/app/soc/modules/gsoc/logic/grading_record.py
@@ -141,8 +141,7 @@
   for record in records:
     project = ndb.Key.from_old_key(record.parent_key()).get()
 
-    if project.status in [
-        project_model.Status.WITHDRAWN, project_model.Status.FAILED]:
+    if project.status == project_model.Status.WITHDRAWN:
       # skip this project
       continue
 
@@ -175,12 +174,12 @@
 
     # update the necessary fields and store it before updating
     project.passed_evaluations = passed_evals
-    project.failed_evaluations = failed_eval
+    project.failed_evaluation = failed_eval
     project.status = new_status
 
     profile = project.key.parent().get()
-    profile.student_data.passed_evaluations = len(passed_evals)
-    profile.student_data.failed_evaluations = 1 if failed_eval else 0
+    profile.student_data.number_of_passed_evaluations = len(passed_evals)
+    profile.student_data.number_of_failed_evaluations = 1 if failed_eval else 0
     profile.put()
 
     projects_to_update.append(project)
diff --git a/app/soc/modules/gsoc/tasks/grading_survey_group.py b/app/soc/modules/gsoc/tasks/grading_survey_group.py
index f505ded..3d877c7 100644
--- a/app/soc/modules/gsoc/tasks/grading_survey_group.py
+++ b/app/soc/modules/gsoc/tasks/grading_survey_group.py
@@ -32,7 +32,6 @@
 from soc.modules.gsoc.logic import profile as profile_logic
 from soc.modules.gsoc.models.grading_record import GSoCGradingRecord
 from soc.modules.gsoc.models.grading_survey_group import GSoCGradingSurveyGroup
-from soc.modules.gsoc.models.project import GSoCProject
 
 from summerofcode.logic import project as project_logic
 
diff --git a/app/soc/modules/gsoc/views/grading_record_details.py b/app/soc/modules/gsoc/views/grading_record_details.py
index 51d4333..a4219ef 100644
--- a/app/soc/modules/gsoc/views/grading_record_details.py
+++ b/app/soc/modules/gsoc/views/grading_record_details.py
@@ -34,7 +34,6 @@
 from soc.modules.gsoc.logic import survey
 from soc.modules.gsoc.models.grading_record import GSoCGradingRecord
 from soc.modules.gsoc.models.grading_survey_group import GSoCGradingSurveyGroup
-from soc.modules.gsoc.models import project as project_model
 from soc.modules.gsoc.views import forms as gsoc_forms
 from soc.modules.gsoc.views import base
 from soc.modules.gsoc.views.helper import url_patterns as gsoc_url_patterns
diff --git a/app/soc/modules/gsoc/views/mentor_evaluation.py b/app/soc/modules/gsoc/views/mentor_evaluation.py
index a90c406..e46d89e 100644
--- a/app/soc/modules/gsoc/views/mentor_evaluation.py
+++ b/app/soc/modules/gsoc/views/mentor_evaluation.py
@@ -436,13 +436,13 @@
     assert isSet(data.mentor_evaluation_record)
 
     evaluation_record = data.mentor_evaluation_record
-    student = data.url_profile
+    student = data.url_ndb_profile
 
     context = {
-        'page_name': 'Student evaluation - %s' % (student.name()),
-        'student': student.name(),
-        'organization': data.url_project.org.name,
-        'project': data.url_project.title,
+        'page_name': 'Student evaluation - %s' % (student.public_name),
+        'student': student.public_name,
+        'organization': data.url_ndb_project.organization.get().name,
+        'project': data.url_ndb_project.title,
         'css_prefix': GSoCMentorEvaluationReadOnlyTemplate.Meta.css_prefix,
         }
 
diff --git a/tests/app/soc/modules/gci/views/test_org_home.py b/tests/app/soc/modules/gci/views/test_org_home.py
index 7209f57..d34be31 100644
--- a/tests/app/soc/modules/gci/views/test_org_home.py
+++ b/tests/app/soc/modules/gci/views/test_org_home.py
@@ -83,9 +83,13 @@
     self.assertEqual(len(list_data), 2)
 
   def testClosedTasksList(self):
-    """Tests if the list of open tasks is rendered.
-    """
-    task_prop = {'status': 'Closed', 'program': self.gci, 'org': self.org}
+    """Tests if the list of open tasks is rendered."""
+    task_prop = {
+        'status': 'Closed',
+        'program': self.program,
+        'org': self.org,
+        'student': profile_utils.seedNDBStudent(self.program).key.to_old_key(),
+        }
     seeder_logic.seed(GCITask, task_prop)
     seeder_logic.seed(GCITask, task_prop)
     response = self.get(self.url)
@@ -94,3 +98,4 @@
     idx = 1
     list_data = self.getListData(self.url, idx)
     self.assertEqual(len(list_data), 2)
+
diff --git a/tests/app/soc/modules/gsoc/logic/test_grading_record.py b/tests/app/soc/modules/gsoc/logic/test_grading_record.py
index c3d3256..55fdaa8 100644
--- a/tests/app/soc/modules/gsoc/logic/test_grading_record.py
+++ b/tests/app/soc/modules/gsoc/logic/test_grading_record.py
@@ -22,7 +22,6 @@
 from soc.modules.gsoc.models import grading_record as grading_record_model
 from soc.modules.gsoc.models import grading_survey_group \
     as grading_survey_group_model
-from soc.modules.gsoc.models import project as project_model
 from soc.modules.gsoc.models import project_survey_record \
     as project_survey_record_model
 from soc.modules.seeder.logic.seeder import logic as seeder_logic
diff --git a/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py b/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py
index 0dbcd36..5c25541 100644
--- a/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py
+++ b/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py
@@ -177,8 +177,7 @@
     self.assertEqual(record.grade_decision, 'pass')
 
   def testUpdateProject(self):
-    """Test updating a Project with a GradingRecord's result.
-    """
+    """Test updating a Project with a GradingRecord's result."""
     post_data = {
         'group_key': self.survey_group.key().id_or_name(),
         }
@@ -189,13 +188,13 @@
     self.assertTasksInQueue(n=1, url=self.UPDATE_PROJECTS_URL)
 
     project = project_model.Project.query().get()
-    self.assertFalse(project is None)
+    self.assertIsNotNone(project)
     self.assertEqual(
         project.passed_evaluations,
         [ndb.Key.from_old_key(self.grading_record.key())])
 
     student = self.student.key.get()
-    self.assertEqual(student.student_data.passed_evaluations, 1)
+    self.assertEqual(student.student_data.number_of_passed_evaluations, 1)
 
   def testUpdateProjectWithSendMail(self):
     """Test updating a Project with a GradingRecord's result and sending mail.
@@ -218,7 +217,7 @@
         [ndb.Key.from_old_key(self.grading_record.key())])
 
     student = self.student.key.get()
-    self.assertEqual(student.student_data.passed_evaluations, 1)
+    self.assertEqual(student.student_data.number_of_passed_evaluations, 1)
 
   def testSendMail(self):
     """Test sending mail about a GradingRecord's result."""
diff --git a/tests/app/soc/modules/gsoc/views/test_mentor_evaluation.py b/tests/app/soc/modules/gsoc/views/test_mentor_evaluation.py
index 52b1ca4..51dca67 100644
--- a/tests/app/soc/modules/gsoc/views/test_mentor_evaluation.py
+++ b/tests/app/soc/modules/gsoc/views/test_mentor_evaluation.py
@@ -128,3 +128,55 @@
     survey = record.GSoCGradingProjectSurveyRecord.all().get()
     self.assertFalse(survey.grade)
     self.assertEqual(survey.failure_reason, record.FAILURE_OPT_OTHER)
+
+
+def _getMentorEvaluationShowPageUrl(program, evaluation, project):
+  """Returns the URL to Mentor Evaluation Take page.
+
+  Args:
+    program: Program entity.
+    evaluation: Survey entity.
+    project: Project entity.
+
+  Returns:
+    A string containing the URL to Mentor Evaluation Take page.
+  """
+  return '/gsoc/eval/mentor/show/%s/%s/%s/%s' % (
+      program.key().name(), evaluation.link_id,
+      project.key.parent().parent().id(), project.key.id())
+
+
+class GSoCMentorEvaluationShowPageTest(test_utils.GSoCDjangoTestCase):
+  """Unit tests for GSoCMentorEvaluationShowPage class."""
+
+  def setUp(self):
+    """See unittest.TestCase.setUp for specification."""
+    self.init()
+    self.evaluation_helper = survey_utils.SurveyHelper(self.gsoc, self.dev_test)
+
+  def assertEvaluationShowTemplateUsed(self, response):
+    """Asserts that all the evaluation show templates were used."""
+    self.assertResponseOkAndGSoCTemplatesUsed(response)
+    self.assertTemplateUsed(response, 'modules/gsoc/_survey/show.html')
+
+  def testPageLoads(self):
+    """Tests that the page loads properly."""
+    evaluation = self.evaluation_helper.createMentorEvaluation()
+
+    user = profile_utils.seedNDBUser()
+    profile_utils.loginNDB(user)
+    org_admin = profile_utils.seedNDBProfile(
+        self.program.key(), user=user, admin_for=[self.org.key])
+
+    mentor = profile_utils.seedNDBProfile(
+        self.program.key(), mentor_for=[self.org.key])
+    student = profile_utils.seedSOCStudent(self.program)
+    project = project_utils.seedNDBProject(
+        student, self.program.key(), org_key=self.org.key,
+        mentor_key=mentor.key)
+
+    # test mentor evaluation show GET for a mentor of the project
+    response = self.get(
+        _getMentorEvaluationShowPageUrl(self.program, evaluation, project))
+    self.assertResponseOK(response)
+    self.assertEvaluationShowTemplateUsed(response)
diff --git a/tests/functional/melange_functional_actions.py b/tests/functional/melange_functional_actions.py
index b24fde3..9771afd 100644
--- a/tests/functional/melange_functional_actions.py
+++ b/tests/functional/melange_functional_actions.py
@@ -57,16 +57,18 @@
     # Select a random port to start a dev server.
     # Random ports and a seperate datastore file is for running of tests in multiple processes.
     self.port = random.randrange(50000, 60000, 2)
-    self.datastore_path = "tests/functional/datastore_files/"
-    if not os.path.isdir(self.datastore_path):
-      os.makedirs(self.datastore_path)
-    self.datastore_file = tempfile.NamedTemporaryFile(dir=self.datastore_path)
+    self.tempdir = tempfile.mkdtemp(prefix="melange-test-")
 
     # Start the dev server as a process running in background.
-    # TODO(nathaniel): Reflow these few lines.
-    self.server_process = subprocess.Popen(('nohup thirdparty/google_appengine/dev_appserver.py\
-               --clear_datastore --datastore_path=%s --port=%s build >/dev/null 2>&1&'
-               %(self.datastore_file.name, self.port)), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
+    cmd = ('nohup thirdparty/google_appengine/dev_appserver.py'
+           ' --clear_datastore --storage_path=%(tempdir)s --port=%(port)s '
+           ' --admin_port=0 --skip_sdk_update_check=True '
+           ' build >%(tempdir)s/STDOUT 2>%(tempdir)s/STDERR </dev/null &'
+           % {'tempdir': self.tempdir, 'port': self.port})
+    self.server_process = subprocess.Popen(
+        cmd,
+        stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True,
+        preexec_fn=os.setsid)
     if not self.server_process:
       self.fail("Server cannot be started: %s" % self.server_process)
     self.setupLocalRemote()
@@ -386,6 +388,7 @@
     """
     ex = None
     try:
+      time.sleep(1)
       self.takeScreenshot()
     except Exception as ex:
       logging.error(ex)
@@ -407,6 +410,11 @@
       subprocess.call('find . -name "*.pyc" -delete', shell=True)
     except Exception as ex:
       logging.error(ex)
+    try:
+      if not 'MELANGE_TEST_KEEP_LOGS' in os.environ:
+        shutil.rmtree(self.tempdir)
+    except Exception as ex:
+      logging.error(ex)
     if ex:
       raise ex  # pylint: disable=raising-bad-type