Merge branch 'main' into avm99963-monorail

Merged commit 3779da353b36d43cf778e7d4f468097714dd4540

GitOrigin-RevId: 6451a5c6b75afb0fd1f37b3f14521148d0722ea8
diff --git a/api/v3/api_constants.py b/api/v3/api_constants.py
index 9752242..e21270c 100644
--- a/api/v3/api_constants.py
+++ b/api/v3/api_constants.py
@@ -9,8 +9,8 @@
 # Max issues per page in the SearchIssues API.
 MAX_ISSUES_PER_PAGE = 100
 
-# Max issues tp fetch in the BatchGetIssues API.
-MAX_BATCH_ISSUES = 100
+# Max issues to fetch in the BatchGetIssues API.
+MAX_BATCH_ISSUES = 1000
 
 # Max issues to modify at once in the ModifyIssues API.
 MAX_MODIFY_ISSUES = 100
diff --git a/api/v3/monorail_servicer.py b/api/v3/monorail_servicer.py
index d54f425..fea6e45 100644
--- a/api/v3/monorail_servicer.py
+++ b/api/v3/monorail_servicer.py
@@ -9,6 +9,7 @@
 
 import cgi
 import functools
+import httplib
 import logging
 import time
 import sys
@@ -21,7 +22,6 @@
 from google.appengine.api import app_identity
 from google.protobuf import json_format
 from components.prpc import codes
-from components.prpc import server
 
 from framework import monitoring
 
@@ -51,10 +51,29 @@
 # Domain for service account emails.
 SERVICE_ACCOUNT_DOMAIN = 'gserviceaccount.com'
 
+# pylint: disable=pointless-string-statement
+
+# TODO(https://crbug.com/1346473)
+_PRPC_TO_HTTP_STATUS = {
+  codes.StatusCode.OK: httplib.OK,
+  codes.StatusCode.CANCELLED: httplib.NO_CONTENT,
+  codes.StatusCode.INVALID_ARGUMENT: httplib.BAD_REQUEST,
+  codes.StatusCode.DEADLINE_EXCEEDED: httplib.SERVICE_UNAVAILABLE,
+  codes.StatusCode.NOT_FOUND: httplib.NOT_FOUND,
+  codes.StatusCode.ALREADY_EXISTS: httplib.CONFLICT,
+  codes.StatusCode.PERMISSION_DENIED: httplib.FORBIDDEN,
+  codes.StatusCode.RESOURCE_EXHAUSTED: httplib.SERVICE_UNAVAILABLE,
+  codes.StatusCode.FAILED_PRECONDITION: httplib.PRECONDITION_FAILED,
+  codes.StatusCode.OUT_OF_RANGE: httplib.BAD_REQUEST,
+  codes.StatusCode.UNIMPLEMENTED: httplib.NOT_IMPLEMENTED,
+  codes.StatusCode.INTERNAL: httplib.INTERNAL_SERVER_ERROR,
+  codes.StatusCode.UNAVAILABLE: httplib.SERVICE_UNAVAILABLE,
+  codes.StatusCode.UNAUTHENTICATED: httplib.UNAUTHORIZED,
+}
 
 def ConvertPRPCStatusToHTTPStatus(context):
   """pRPC uses internal codes 0..16, but we want to report HTTP codes."""
-  return server._PRPC_TO_HTTP_STATUS.get(context._code, 500)
+  return _PRPC_TO_HTTP_STATUS.get(context._code, 500)
 
 
 def PRPCMethod(func):
diff --git a/api/v3/test/hotlists_servicer_test.py b/api/v3/test/hotlists_servicer_test.py
index e9808b5..170cf2e 100644
--- a/api/v3/test/hotlists_servicer_test.py
+++ b/api/v3/test/hotlists_servicer_test.py
@@ -23,6 +23,7 @@
 from framework import exceptions
 from framework import monorailcontext
 from framework import permissions
+from framework import sorting
 from features import features_constants
 from testing import fake
 from services import features_svc
@@ -38,6 +39,7 @@
         issue=fake.IssueService(),
         project=fake.ProjectService(),
         config=fake.ConfigService(),
+        cache_manager=fake.CacheManager(),
         user=fake.UserService(),
         usergroup=fake.UserGroupService())
     self.hotlists_svcr = hotlists_servicer.HotlistsServicer(
@@ -110,6 +112,7 @@
         is_private=True)
     self.hotlist_resource_name = rnc.ConvertHotlistName(
         self.hotlist_1.hotlist_id)
+    sorting.InitializeArtValues(self.services)
 
   def CallWrapped(self, wrapped_handler, mc, *args, **kwargs):
     self.converter = converters.Converter(mc, self.services)
diff --git a/api/v3/test/monorail_servicer_test.py b/api/v3/test/monorail_servicer_test.py
index 3569879..2abcaf9 100644
--- a/api/v3/test/monorail_servicer_test.py
+++ b/api/v3/test/monorail_servicer_test.py
@@ -11,9 +11,11 @@
 import time
 import unittest
 import mock
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 
-from components.prpc import server
 from components.prpc import codes
 from components.prpc import context
 from google.appengine.ext import testbed