Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 1 | # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style |
| 3 | # license that can be found in the LICENSE file or at |
| 4 | # https://developers.google.com/open-source/licenses/bsd |
| 5 | |
| 6 | """Some constants used throughout Monorail.""" |
| 7 | from __future__ import print_function |
| 8 | from __future__ import division |
| 9 | from __future__ import absolute_import |
| 10 | |
| 11 | import os |
| 12 | import re |
| 13 | |
| 14 | |
| 15 | # Number of seconds in various periods. |
| 16 | SECS_PER_MINUTE = 60 |
| 17 | SECS_PER_HOUR = SECS_PER_MINUTE * 60 |
| 18 | SECS_PER_DAY = SECS_PER_HOUR * 24 |
| 19 | SECS_PER_MONTH = SECS_PER_DAY * 30 |
| 20 | SECS_PER_YEAR = SECS_PER_DAY * 365 |
| 21 | |
| 22 | # When we write to memcache, let the values expire so that we don't |
| 23 | # get any unexpected super-old values as we make code changes over the |
| 24 | # years. Also, searches can contain date terms like [opened<today-1] |
| 25 | # that would become wrong if cached for a long time. |
| 26 | CACHE_EXPIRATION = 6 * SECS_PER_HOUR |
| 27 | |
| 28 | # Fulltext indexing happens asynchronously and we get no notification |
| 29 | # when the indexing operation has completed. So, when we cache searches |
| 30 | # that use fulltext terms, the results might be stale. We still do |
| 31 | # cache them and use the cached values, but we expire them so that the |
| 32 | # results cannot be stale for a long period of time. |
| 33 | FULLTEXT_MEMCACHE_EXPIRATION = 3 * SECS_PER_MINUTE |
| 34 | |
| 35 | # Size in bytes of the largest form submission that we will accept |
| 36 | MAX_POST_BODY_SIZE = 10 * 1024 * 1024 # = 10 MB |
| 37 | |
| 38 | # Special issue ID to use when an issue is explicitly not specified. |
| 39 | NO_ISSUE_SPECIFIED = 0 |
| 40 | |
| 41 | # Special user ID and name to use when no user was specified. |
| 42 | NO_USER_SPECIFIED = 0 |
| 43 | NO_SESSION_SPECIFIED = 0 |
| 44 | NO_USER_NAME = '----' |
| 45 | DELETED_USER_NAME = 'a_deleted_user' |
| 46 | DELETED_USER_ID = 1 |
| 47 | USER_NOT_FOUND_NAME = 'user_not_found' |
| 48 | |
| 49 | # Queues for deleting users tasks. |
| 50 | QUEUE_SEND_WIPEOUT_USER_LISTS = 'wipeoutsendusers' |
| 51 | QUEUE_FETCH_WIPEOUT_DELETED_USERS = 'wipeoutdeleteusers' |
| 52 | QUEUE_DELETE_USERS = 'deleteusers' |
| 53 | |
| 54 | # We remember the time of each user's last page view, but to reduce the |
| 55 | # number of database writes, we only update it if it is newer by an hour. |
| 56 | VISIT_RESOLUTION = 1 * SECS_PER_HOUR |
| 57 | |
| 58 | # String to display when some field has no value. |
| 59 | NO_VALUES = '----' |
| 60 | |
| 61 | # If the user enters one or more dashes, that means "no value". This is useful |
| 62 | # in bulk edit, inbound email, and commit log command where a blank field |
| 63 | # means "keep what was there" or is ignored. |
| 64 | NO_VALUE_RE = re.compile(r'^-+$') |
| 65 | |
| 66 | # Used to loosely validate column spec. Mainly guards against malicious input. |
| 67 | COLSPEC_RE = re.compile(r'^[-.\w\s/]*$', re.UNICODE) |
| 68 | COLSPEC_COL_RE = re.compile(r'[-.\w/]+', re.UNICODE) |
| 69 | MAX_COL_PARTS = 25 |
| 70 | MAX_COL_LEN = 50 |
| 71 | |
| 72 | # Used to loosely validate sort spec. Mainly guards against malicious input. |
| 73 | SORTSPEC_RE = re.compile(r'^[-.\w\s/]*$', re.UNICODE) |
| 74 | MAX_SORT_PARTS = 6 |
| 75 | |
| 76 | # For the artifact search box autosizing when the user types a long query. |
| 77 | MIN_ARTIFACT_SEARCH_FIELD_SIZE = 38 |
| 78 | MAX_ARTIFACT_SEARCH_FIELD_SIZE = 75 |
| 79 | AUTOSIZE_STEP = 3 |
| 80 | |
| 81 | # Regular expressions used in parsing label and status configuration text |
| 82 | IDENTIFIER_REGEX = r'[-.\w]+' |
| 83 | IDENTIFIER_RE = re.compile(IDENTIFIER_REGEX, re.UNICODE) |
| 84 | # Labels and status values that are prefixed by a pound-sign are not displayed |
| 85 | # in autocomplete menus. |
| 86 | IDENTIFIER_DOCSTRING_RE = re.compile( |
| 87 | r'^(#?%s)[ \t]*=?[ \t]*(.*)$' % IDENTIFIER_REGEX, |
| 88 | re.MULTILINE | re.UNICODE) |
| 89 | |
| 90 | # Number of label text fields that we can display on a web form for issues. |
| 91 | MAX_LABELS = 24 |
| 92 | |
| 93 | # Default number of comments to display on an artifact detail page at one time. |
| 94 | # Other comments will be paginated. |
| 95 | DEFAULT_COMMENTS_PER_PAGE = 100 |
| 96 | |
| 97 | # Content type to use when serving JSON. |
| 98 | CONTENT_TYPE_JSON = 'application/json; charset=UTF-8' |
| 99 | CONTENT_TYPE_JSON_OPTIONS = 'nosniff' |
| 100 | |
| 101 | # Maximum comments to index to keep the search index from choking. E.g., if an |
| 102 | # artifact had 1200 comments, only 0..99 and 701..1200 would be indexed. |
| 103 | # This mainly affects advocacy issues which are highly redundant anyway. |
| 104 | INITIAL_COMMENTS_TO_INDEX = 100 |
| 105 | FINAL_COMMENTS_TO_INDEX = 500 |
| 106 | |
| 107 | # This is the longest string that GAE search will accept in one field. |
| 108 | # The entire search document is also limited to 1MB, so our limit is 200 * 1024 |
| 109 | # chars so that each can be 4 bytes and the comments leave room for metadata. |
| 110 | # https://cloud.google.com/appengine/docs/standard/python/search/#documents |
| 111 | MAX_FTS_FIELD_SIZE = 200 * 1024 |
| 112 | |
| 113 | # Base path to EZT templates. |
| 114 | this_dir = os.path.dirname(__file__) |
| 115 | TEMPLATE_PATH = this_dir[:this_dir.rindex('/')] + '/templates/' |
| 116 | |
| 117 | # Defaults for dooming a project. |
| 118 | DEFAULT_DOOM_REASON = 'No longer needed' |
| 119 | DEFAULT_DOOM_PERIOD = SECS_PER_DAY * 90 |
| 120 | |
| 121 | MAX_PROJECT_PEOPLE = 1000 |
| 122 | |
| 123 | MAX_HOTLIST_NAME_LENGTH = 80 |
| 124 | |
| 125 | # When logging potentially long debugging strings, only show this many chars. |
| 126 | LOGGING_MAX_LENGTH = 2000 |
| 127 | |
| 128 | # Maps languages supported by google-code-prettify |
| 129 | # to the class name that should be added to code blocks in that language. |
| 130 | # This list should be kept in sync with the handlers registered |
| 131 | # in lang-*.js and prettify.js from the prettify project. |
| 132 | PRETTIFY_CLASS_MAP = { |
| 133 | ext: 'lang-' + ext |
| 134 | for ext in [ |
| 135 | # Supported in lang-*.js |
| 136 | 'apollo', 'agc', 'aea', 'lisp', 'el', 'cl', 'scm', |
| 137 | 'css', 'go', 'hs', 'lua', 'fs', 'ml', 'proto', 'scala', 'sql', 'vb', |
| 138 | 'vbs', 'vhdl', 'vhd', 'wiki', 'yaml', 'yml', 'clj', |
| 139 | # Supported in prettify.js |
| 140 | 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl', |
| 141 | 'c', 'cc', 'cpp', 'cxx', 'cyc', 'm', |
| 142 | 'json', 'cs', 'java', 'bsh', 'csh', 'sh', 'cv', 'py', 'perl', 'pl', |
| 143 | 'pm', 'rb', 'js', 'coffee', |
| 144 | ]} |
| 145 | |
| 146 | # Languages which are not specifically mentioned in prettify.js |
| 147 | # but which render intelligibly with the default handler. |
| 148 | PRETTIFY_CLASS_MAP.update( |
| 149 | (ext, '') for ext in [ |
| 150 | 'hpp', 'hxx', 'hh', 'h', 'inl', 'idl', 'swig', 'd', |
| 151 | 'php', 'tcl', 'aspx', 'cfc', 'cfm', |
| 152 | 'ent', 'mod', 'as', |
| 153 | 'y', 'lex', 'awk', 'n', 'pde', |
| 154 | ]) |
| 155 | |
| 156 | # Languages which are not specifically mentioned in prettify.js |
| 157 | # but which should be rendered using a certain prettify module. |
| 158 | PRETTIFY_CLASS_MAP.update({ |
| 159 | 'docbook': 'lang-xml', |
| 160 | 'dtd': 'lang-xml', |
| 161 | 'duby': 'lang-rb', |
| 162 | 'mk': 'lang-sh', |
| 163 | 'mak': 'lang-sh', |
| 164 | 'make': 'lang-sh', |
| 165 | 'mirah': 'lang-rb', |
| 166 | 'ss': 'lang-lisp', |
| 167 | 'vcproj': 'lang-xml', |
| 168 | 'xsd': 'lang-xml', |
| 169 | 'xslt': 'lang-xml', |
| 170 | }) |
| 171 | |
| 172 | PRETTIFY_FILENAME_CLASS_MAP = { |
| 173 | 'makefile': 'lang-sh', |
| 174 | 'makefile.in': 'lang-sh', |
| 175 | 'doxyfile': 'lang-sh', # Key-value pairs with hash comments |
| 176 | '.checkstyle': 'lang-xml', |
| 177 | '.classpath': 'lang-xml', |
| 178 | '.project': 'lang-xml', |
| 179 | } |
| 180 | |
| 181 | OAUTH_SCOPE = 'https://www.googleapis.com/auth/userinfo.email' |
| 182 | MONORAIL_SCOPE = 'https://www.googleapis.com/auth/monorail' |
| 183 | |
| 184 | FILENAME_RE = re.compile('^[-_.a-zA-Z0-9 #+()]+$') |