Merge branch 'main' into avm99963-monorail

Merged commit cd4b3b336f1f14afa02990fdc2eec5d9467a827e

GitOrigin-RevId: e67bbf185d5538e1472bb42e0abb2a141f88bac1
diff --git a/project/peopledetail.py b/project/peopledetail.py
index 3c4846b..af9cd49 100644
--- a/project/peopledetail.py
+++ b/project/peopledetail.py
@@ -14,10 +14,10 @@
 import ezt
 
 from framework import exceptions
+from framework import flaskservlet
 from framework import framework_bizobj
 from framework import framework_helpers
 from framework import framework_views
-from framework import jsonfeed
 from framework import permissions
 from framework import servlet
 from framework import template_helpers
@@ -39,7 +39,6 @@
     permissions.DELETE_OWN,
     permissions.DELETE_ANY,
     permissions.EDIT_ANY_MEMBER_NOTES,
-    permissions.MODERATE_SPAM,
     ]
 
 
@@ -47,7 +46,7 @@
   """People detail page documents one partipant's involvement in a project."""
 
   _PAGE_TEMPLATE = 'project/people-detail-page.ezt'
-  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PEOPLE
+  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_PEOPLE
 
   def AssertBasePermission(self, mr):
     """Check that the user is allowed to access this servlet."""
@@ -234,6 +233,8 @@
 
     role = post_data.get('role', '').lower()
     extra_perms = []
+    # TODO(crbug.com/monorail/10936): getall in Flask is getlist
+    # for ep in post_data.getlist('extra_perms'):
     for ep in post_data.getall('extra_perms'):
       perm = framework_bizobj.CanonicalizeLabel(ep)
       # Perms with leading underscores are reserved.
@@ -269,3 +270,9 @@
 
     self.services.project.UpdateProjectRoles(
         cnxn, project.project_id, owner_ids, committer_ids, contributor_ids)
+
+  # def GetPeopleDetailPage(self, **kwargs):
+  #   return self.handler(**kwargs)
+
+  # def PostPeopleDetailPage(self, **kwargs):
+  #   return self.handler(**kwargs)
diff --git a/project/peoplelist.py b/project/peoplelist.py
index 0db5ee6..f2aff1a 100644
--- a/project/peoplelist.py
+++ b/project/peoplelist.py
@@ -19,6 +19,7 @@
 import ezt
 
 from businesslogic import work_env
+from framework import flaskservlet
 from framework import framework_bizobj
 from framework import framework_constants
 from framework import framework_helpers
@@ -37,7 +38,7 @@
   """People list page shows a paginatied list of project members."""
 
   _PAGE_TEMPLATE = 'project/people-list-page.ezt'
-  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PEOPLE
+  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_PEOPLE
 
   def AssertBasePermission(self, mr):
     super(PeopleList, self).AssertBasePermission(mr)
@@ -217,6 +218,8 @@
     """
     # 1. Parse and validate user input.
     remove_strs = post_data.getall('remove')
+    # TODO(crbug.com/monorail/10936): getall in Flask is getlist
+    # remove_strs = post_data.getlist('remove')
     logging.info('remove_strs = %r', remove_strs)
     remove_ids = set(
         self.services.user.LookupUserIDs(mr.cnxn, remove_strs).values())
@@ -232,3 +235,9 @@
     # 3. Determine the next page in the UI flow.
     return framework_helpers.FormatAbsoluteURL(
         mr, urls.PEOPLE_LIST, saved=1, ts=int(time.time()))
+
+  # def GetPeopleListPage(self, **kwargs):
+  #   return self.handler(**kwargs)
+
+  # def PostPeopleListPage(self, **kwargs):
+  #   return self.handler(**kwargs)
diff --git a/project/projectadmin.py b/project/projectadmin.py
index 887d3fc..a6e0d3e 100644
--- a/project/projectadmin.py
+++ b/project/projectadmin.py
@@ -8,17 +8,15 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import logging
 import time
 
+from google.cloud import exceptions
 from six import string_types
-from third_party import cloudstorage
 import ezt
 
 from businesslogic import work_env
 from framework import emailfmt
-from framework import framework_bizobj
-from framework import framework_constants
+from framework import flaskservlet
 from framework import framework_helpers
 from framework import gcs_helpers
 from framework import permissions
@@ -39,7 +37,7 @@
   """A page with project configuration options for the Project Owner(s)."""
 
   _PAGE_TEMPLATE = 'project/project-admin-page.ezt'
-  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_ADMIN
+  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_ADMIN
 
   def AssertBasePermission(self, mr):
     super(ProjectAdmin, self).AssertBasePermission(mr)
@@ -138,7 +136,7 @@
       if post_data.get('delete_logo'):
         try:
           gcs_helpers.DeleteObjectFromGCS(logo_gcs_id)
-        except cloudstorage.NotFoundError:
+        except exceptions.NotFound:
           pass
         # Reset the GCS ID and file name.
         logo_gcs_id = ''
@@ -190,3 +188,9 @@
         errors.description = _MSG_DESCRIPTION_MISSING
 
     return summary, description
+
+  # def GetProjectAdminPage(self, **kwargs):
+  #   return self.handler(**kwargs)
+
+  # def PostProjectAdminPage(self, **kwargs):
+  #   return self.handler(**kwargs)
diff --git a/project/projectadminadvanced.py b/project/projectadminadvanced.py
index 9c5fc1b..eafe912 100644
--- a/project/projectadminadvanced.py
+++ b/project/projectadminadvanced.py
@@ -17,12 +17,12 @@
 from __future__ import print_function
 from __future__ import absolute_import
 
-import logging
 import time
 
 import ezt
 
 from businesslogic import work_env
+from framework import flaskservlet
 from framework import framework_constants
 from framework import framework_helpers
 from framework import permissions
@@ -37,7 +37,7 @@
   """A page with project state options for the Project Owner(s)."""
 
   _PAGE_TEMPLATE = 'project/project-admin-advanced-page.ezt'
-  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_ADMIN
+  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_ADMIN
 
   def AssertBasePermission(self, mr):
     """Make sure that the logged in user has permission to view this page.
@@ -211,3 +211,9 @@
               'This project is not live, no user can move it')
         moved_to = post_data.get('moved_to', '')
         we.UpdateProject(mr.project.project_id, moved_to=moved_to)
+
+  # def GetProjectAdminAdvancedPage(self, **kwargs):
+  #   return self.handler(**kwargs)
+
+  # def PostProjectAdminAdvancedPage(self, **kwargs):
+  #   return self.handler(**kwargs)
\ No newline at end of file
diff --git a/project/projectexport.py b/project/projectexport.py
index e315442..177eea4 100644
--- a/project/projectexport.py
+++ b/project/projectexport.py
@@ -14,6 +14,7 @@
 
 import ezt
 
+from framework import flaskservlet
 from framework import permissions
 from framework import jsonfeed
 from framework import servlet
@@ -25,7 +26,7 @@
   """Only site admins can export a project"""
 
   _PAGE_TEMPLATE = 'project/project-export-page.ezt'
-  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_ADMIN
+  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_ADMIN
 
   def AssertBasePermission(self, mr):
     """Make sure that the logged in user has permission to view this page."""
@@ -42,7 +43,11 @@
         'page_perms': self.MakePagePerms(mr, None, permissions.CREATE_ISSUE),
     }
 
+  # def GetProjectExportPage(self, **kwargs):
+  #   return self.handler(**kwargs)
 
+
+# TODO(https://crbug.com/monorail/10936): Use FlaskJsonFeed
 class ProjectExportJSON(jsonfeed.JsonFeed):
   """ProjectExportJSON shows all configuration for a Project in JSON form."""
 
@@ -201,3 +206,9 @@
       'ccs': [email_dict.get(user) for user in component.cc_ids],
     }
     return component_json
+
+  # def GetProjectExportJSONPage(self, **kwargs):
+  #   return self.handler(**kwargs)
+
+  # def PostProjectExportJSONPage(self, **kwargs):
+  #   return self.handler(**kwargs)
\ No newline at end of file
diff --git a/project/projectsummary.py b/project/projectsummary.py
index 018aaf3..c0cad5a 100644
--- a/project/projectsummary.py
+++ b/project/projectsummary.py
@@ -8,9 +8,8 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import logging
-
 from businesslogic import work_env
+from framework import flaskservlet
 from framework import permissions
 from framework import servlet
 from project import project_helpers
@@ -21,7 +20,7 @@
   """Page to show brief project description and process documentation."""
 
   _PAGE_TEMPLATE = 'project/project-summary-page.ezt'
-  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PROCESS
+  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_PROCESS
 
   def GatherPageData(self, mr):
     """Build up a dictionary of data values to use when rendering the page."""
@@ -70,3 +69,6 @@
         help_data['cue'] = 'document_team_duties'
 
     return help_data
+
+  # def GetProjectSummaryPage(self, **kwargs):
+  #   return self.handler(**kwargs)
\ No newline at end of file
diff --git a/project/projectupdates.py b/project/projectupdates.py
index bd1e316..304b435 100644
--- a/project/projectupdates.py
+++ b/project/projectupdates.py
@@ -13,6 +13,7 @@
 import ezt
 
 from features import activities
+from framework import flaskservlet
 from framework import servlet
 from framework import urls
 
@@ -21,7 +22,7 @@
   """ProjectUpdates page shows a list of past activities."""
 
   _PAGE_TEMPLATE = 'project/project-updates-page.ezt'
-  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_UPDATES
+  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_UPDATES
 
   def GatherPageData(self, mr):
     """Build up a dictionary of data values to use when rendering the page."""
@@ -40,3 +41,6 @@
         self.services, mr, project_ids=[mr.project_id],
         ending='by_user', updates_page_url=url,
         autolink=self.services.autolink)
+
+  # def GetProjectUpdatesPage(self, **kwargs):
+  #   return self.handler(**kwargs)
\ No newline at end of file
diff --git a/project/redirects.py b/project/redirects.py
index 7813a56..8c8b818 100644
--- a/project/redirects.py
+++ b/project/redirects.py
@@ -13,8 +13,9 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import httplib
+from six.moves import http_client
 
+from framework import flaskservlet
 from framework import framework_helpers
 from framework import servlet
 from framework import urls
@@ -26,14 +27,24 @@
   def get(self, **kwargs):
     """Construct a 302 pointing at project.docs_url, or at adminIntro."""
     if not self.mr.project:
-      self.response.status = httplib.NOT_FOUND
+      # TODO(crbug.com/monorail/10936): status in Flask is status_code
+      # self.response.status_code = http_client.NOT_FOUND
+      self.response.status = http_client.NOT_FOUND
       return
     docs_url = self.mr.project.docs_url
     if not docs_url:
       docs_url = framework_helpers.FormatAbsoluteURL(
           self.mr, urls.ADMIN_INTRO, include_project=True)
     self.response.location = docs_url
-    self.response.status = httplib.MOVED_PERMANENTLY
+    # TODO(crbug.com/monorail/10936): status in Flask is status_code
+    # self.response.status_code = http_client.MOVED_PERMANENTLY
+    self.response.status = http_client.MOVED_PERMANENTLY
+
+  # def GetWikiListRedirect(self, **kwargs):
+  #   return self.handler(**kwargs)
+
+  # def GetWikiRedirect(self, **kwargs):
+  #   return self.handler(**kwargs)
 
 
 class SourceRedirect(servlet.Servlet):
@@ -42,11 +53,18 @@
   def get(self, **kwargs):
     """Construct a 302 pointing at project.source_url, or at adminIntro."""
     if not self.mr.project:
-      self.response.status = httplib.NOT_FOUND
+      # TODO(crbug.com/monorail/10936): status in Flask is status_code
+      # self.response.status_code = http_client.NOT_FOUND
+      self.response.status = http_client.NOT_FOUND
       return
     source_url = self.mr.project.source_url
     if not source_url:
       source_url = framework_helpers.FormatAbsoluteURL(
           self.mr, urls.ADMIN_INTRO, include_project=True)
     self.response.location = source_url
-    self.response.status = httplib.MOVED_PERMANENTLY
+    # TODO(crbug.com/monorail/10936): status in Flask is status_code
+    # self.response.status_code = http_client.MOVED_PERMANENTLY
+    self.response.status = http_client.MOVED_PERMANENTLY
+
+  # def GetSourceRedirect(self, **kwargs):
+  #   return self.handler(**kwargs)
diff --git a/project/test/redirects_test.py b/project/test/redirects_test.py
index 2f51495..0091571 100644
--- a/project/test/redirects_test.py
+++ b/project/test/redirects_test.py
@@ -8,7 +8,7 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import httplib
+from six.moves import http_client
 import unittest
 
 import webapp2
@@ -35,14 +35,13 @@
     """Visiting a project that we don't host is 404."""
     self.servlet.mr.project = None
     self.servlet.get()
-    self.assertEqual(
-        httplib.NOT_FOUND, self.servlet.response.status_code)
+    self.assertEqual(http_client.NOT_FOUND, self.servlet.response.status_code)
 
   def testRedirect_NoDocsSpecified(self):
     """Visiting any old wiki URL goes to admin intro by default."""
     self.servlet.get()
     self.assertEqual(
-        httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+        http_client.MOVED_PERMANENTLY, self.servlet.response.status_code)
     self.assertTrue(
         self.servlet.response.location.endswith(urls.ADMIN_INTRO))
 
@@ -51,7 +50,7 @@
     self.project.docs_url = 'some_url'
     self.servlet.get()
     self.assertEqual(
-        httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+        http_client.MOVED_PERMANENTLY, self.servlet.response.status_code)
     self.assertEqual('some_url', self.servlet.response.location)
 
 
@@ -70,14 +69,13 @@
     """Visiting a project that we don't host is 404."""
     self.servlet.mr.project = None
     self.servlet.get()
-    self.assertEqual(
-        httplib.NOT_FOUND, self.servlet.response.status_code)
+    self.assertEqual(http_client.NOT_FOUND, self.servlet.response.status_code)
 
   def testRedirect_NoSrcSpecified(self):
     """Visiting any old source code URL goes to admin intro by default."""
     self.servlet.get()
     self.assertEqual(
-        httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+        http_client.MOVED_PERMANENTLY, self.servlet.response.status_code)
     self.assertTrue(
         self.servlet.response.location.endswith(urls.ADMIN_INTRO))
 
@@ -86,5 +84,5 @@
     self.project.source_url = 'some_url'
     self.servlet.get()
     self.assertEqual(
-        httplib.MOVED_PERMANENTLY, self.servlet.response.status_code)
+        http_client.MOVED_PERMANENTLY, self.servlet.response.status_code)
     self.assertEqual('some_url', self.servlet.response.location)