Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/search/searchpipeline.py b/search/searchpipeline.py
new file mode 100644
index 0000000..422a619
--- /dev/null
+++ b/search/searchpipeline.py
@@ -0,0 +1,90 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+"""Helper functions and classes used in issue search and sorting."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import logging
+import re
+
+from features import savedqueries_helpers
+from search import query2ast
+from services import tracker_fulltext
+from services import fulltext_helpers
+from tracker import tracker_helpers
+
+
+# Users can use "is:starred" in queries to limit
+# search results to issues starred by that user.
+IS_STARRED_RE = re.compile(r'\b(?![-@.:])is:starred\b(?![-@.:])', re.I)
+
+# Users can use "me" in other fields to refer to the logged in user name.
+KEYWORD_ME_RE = re.compile(r'\b[-_a-z0-9]+[=:]me\b(?![-@.:=])', re.I)
+ME_RE = re.compile(r'(?<=[=:])me\b(?![-@.:=])', re.I)
+
+
+def _AccumulateIssueProjectsAndConfigs(
+ cnxn, project_dict, config_dict, services, issues):
+ """Fetch any projects and configs that we need but haven't already loaded.
+
+ Args:
+ cnxn: connection to SQL database.
+ project_dict: dict {project_id: project} of projects that we have
+ already retrieved.
+ config_dict: dict {project_id: project} of configs that we have
+ already retrieved.
+ services: connections to backends.
+ issues: list of issues, which may be parts of different projects.
+
+ Returns:
+ Nothing, but projects_dict will be updated to include all the projects that
+ contain the given issues, and config_dicts will be updated to incude all
+ the corresponding configs.
+ """
+ new_ids = {issue.project_id for issue in issues}
+ new_ids.difference_update(iter(project_dict.keys()))
+ new_projects_dict = services.project.GetProjects(cnxn, new_ids)
+ project_dict.update(new_projects_dict)
+ new_configs_dict = services.config.GetProjectConfigs(cnxn, new_ids)
+ config_dict.update(new_configs_dict)
+
+
+def ReplaceKeywordsWithUserIDs(me_user_ids, query):
+ """Substitutes User ID in terms such as is:starred and me.
+
+ This is done on the query string before it is parsed because the query string
+ is used as a key for cached search results in memcache. A search for by one
+ user for owner:me should not retrieve results stored for some other user.
+
+ Args:
+ me_user_ids: [] when no user is logged in, or user ID of the logged in
+ user when doing an interactive search, or the viewed user ID when
+ viewing someone else's dashboard, or the subscribing user's ID when
+ evaluating subscriptions. Also contains linked account IDs.
+ query: The query string.
+
+ Returns:
+ A pair (query, warnings) where query is a string with "me" and "is:starred"
+ removed or replaced by new terms that use the numeric user ID provided,
+ and warnings is a list of warning strings to display to the user.
+ """
+ warnings = []
+ if me_user_ids:
+ me_user_ids_str = ','.join(str(uid) for uid in me_user_ids)
+ star_term = 'starredby:%s' % me_user_ids_str
+ query = IS_STARRED_RE.sub(star_term, query)
+ if KEYWORD_ME_RE.search(query):
+ query = ME_RE.sub(me_user_ids_str, query)
+ else:
+ if IS_STARRED_RE.search(query):
+ warnings.append('"is:starred" ignored because you are not signed in.')
+ query = IS_STARRED_RE.sub('', query)
+ if KEYWORD_ME_RE.search(query):
+ warnings.append('"me" keyword ignored because you are not signed in.')
+ query = KEYWORD_ME_RE.sub('', query)
+
+ return query, warnings