
This change establishes Python 3 compatibility for the major part of Gerrit build tool chain. Only two scripts remain non Python 3 compatible: * Documentation/replace_macros.py * tools/bzl/license-map.py Those scripts explicitly invoked with python2 version. Test Plan: a. Python 2.7 * Switch to system where /usr/bin/python points to Python 2.7 * bazel build release * bazel test //... * tools/eclipse/project.py b. Python 3.6 * Switch to system where /usr/bin/python points to Python 3.6 * bazel build release * bazel test //... * tools/eclipse/project.py Pre-requisites for the test plan: In case bazel action and repository caching is activated on the SUT, the caches would need to be wiped out, to make sure that the complete build tool chain was tested. On my system I had to run these commands: * bazel clean --expunge_async * rm -rf ~/.gerritcodereview/buck-cache/downloaded-artifacts/* * rm -rf ~/.gerritcodereview/bazel-cache/cas/* * rm -rf ~/.gerritcodereview/bazel-cache/repository/* Bug: Issue 8151 Change-Id: Iece59d0c5149b77a02754b3fed4ce84d5d8085ee
279 lines
8.1 KiB
Python
Executable File
279 lines
8.1 KiB
Python
Executable File
#!/usr/bin/env python2
|
|
# coding=utf-8
|
|
# Copyright (C) 2013 The Android Open Source Project
|
|
#
|
|
# 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.
|
|
|
|
from optparse import OptionParser
|
|
import re
|
|
import sys
|
|
|
|
PAT_GERRIT = re.compile(r'^GERRIT')
|
|
PAT_INCLUDE = re.compile(r'^(include::.*)(\[\])$')
|
|
PAT_GET = re.compile(r'^get::([^ \t\n]*)')
|
|
PAT_TITLE = re.compile(r'^\.(.*)')
|
|
PAT_STARS = re.compile(r'^\*\*\*\*')
|
|
PAT_SEARCHBOX = re.compile(r'^SEARCHBOX')
|
|
|
|
GERRIT_UPLINK = """
|
|
|
|
++++
|
|
<hr style=\"
|
|
height: 2px;
|
|
color: silver;
|
|
margin-top: 1.2em;
|
|
margin-bottom: 0.5em;
|
|
\">
|
|
++++
|
|
|
|
"""
|
|
|
|
GET_TITLE = '<div class="title">%s</div>'
|
|
|
|
GET_MACRO = """
|
|
|
|
++++
|
|
<div class="listingblock">
|
|
%s
|
|
<div class="content">
|
|
<a id=\"{0}\" onmousedown="javascript:
|
|
var i = document.URL.lastIndexOf(\'/Documentation/\');
|
|
var url = document.URL.substring(0, i) + \'{0}\';
|
|
document.getElementById(\'{0}\').href = url;">
|
|
GET {0} HTTP/1.0
|
|
</a>
|
|
</div>
|
|
</div>
|
|
++++
|
|
|
|
"""
|
|
|
|
SEARCH_BOX = """
|
|
|
|
++++
|
|
<div style="
|
|
position:fixed;
|
|
top:0px;
|
|
right:0px;
|
|
text-align:
|
|
right;
|
|
padding-top:2px;
|
|
padding-right:0.5em;
|
|
padding-bottom:2px;">
|
|
<input size="40"
|
|
style="line-height: 0.75em;font-size: 0.75em;"
|
|
id="docSearch"
|
|
type="text">
|
|
<button style="
|
|
background:none!important;
|
|
border:none;
|
|
padding:0!important;
|
|
vertical-align:bottom;
|
|
font-family:'Open Sans','DejaVu Sans',sans-serif;
|
|
font-size:0.8em;
|
|
color:#1d4b8f;
|
|
text-decoration:none;"
|
|
type="button"
|
|
id="searchBox">
|
|
Search
|
|
</button>
|
|
<script type="text/javascript">
|
|
var f = function() {
|
|
window.location = '../#/Documentation/' +
|
|
encodeURIComponent(document.getElementById("docSearch").value);
|
|
}
|
|
document.getElementById("searchBox").onclick = f;
|
|
document.getElementById("docSearch").onkeypress = function(e) {
|
|
if (13 == (e.keyCode ? e.keyCode : e.which)) {
|
|
f();
|
|
}
|
|
}
|
|
</script>
|
|
</div>
|
|
++++
|
|
|
|
"""
|
|
|
|
LINK_SCRIPT = """
|
|
|
|
++++
|
|
<script type="text/javascript">
|
|
decorate(document.getElementsByTagName('h1'));
|
|
decorate(document.getElementsByTagName('h2'));
|
|
decorate(document.getElementsByTagName('h3'));
|
|
decorate(document.getElementsByTagName('h4'));
|
|
|
|
var divs = document.getElementsByTagName('div');
|
|
var arr = new Array();
|
|
var excluded = getExcludedIds();
|
|
for(var i = 0; i < divs.length; i++) {
|
|
var d = divs[i];
|
|
var id = d.getAttribute('id');
|
|
if (id != null && !(id in excluded)) {
|
|
arr[arr.length] = d;
|
|
}
|
|
}
|
|
decorate(arr);
|
|
|
|
var anchors = document.getElementsByTagName('a');
|
|
arr = new Array();
|
|
for(var i = 0; i < anchors.length; i++) {
|
|
var a = anchors[i];
|
|
// if the anchor has no id there is no target to
|
|
// which we can link
|
|
if (a.getAttribute('id') != null) {
|
|
// if the anchor is empty there is no content which
|
|
// can receive the mouseover event, an empty anchor
|
|
// applies to the element that follows, move the
|
|
// element that follows into the anchor so that there
|
|
// is content which can receive the mouseover event
|
|
if (a.firstChild == null) {
|
|
var next = a.nextSibling;
|
|
if (next != null) {
|
|
next.parentNode.removeChild(next);
|
|
a.appendChild(next);
|
|
}
|
|
}
|
|
arr[arr.length] = a;
|
|
}
|
|
}
|
|
decorate(arr);
|
|
|
|
function decorate(e) {
|
|
for(var i = 0; i < e.length; i++) {
|
|
e[i].onmouseover = function (evt) {
|
|
var element = this;
|
|
// do nothing if the link icon is currently showing
|
|
var a = element.firstChild;
|
|
if (a != null && a instanceof Element
|
|
&& a.getAttribute('id') == 'LINK') {
|
|
return;
|
|
}
|
|
|
|
// if there is no id there is no target to link to
|
|
var id = element.getAttribute('id');
|
|
if (id == null) {
|
|
return;
|
|
}
|
|
|
|
// create and show a link icon that links to this element
|
|
a = document.createElement('a');
|
|
a.setAttribute('id', 'LINK');
|
|
a.setAttribute('href', '#' + id);
|
|
a.setAttribute('style', 'position: absolute;'
|
|
+ ' left: ' + (element.offsetLeft - 16 - 2 * 4) + 'px;'
|
|
+ ' padding-left: 4px; padding-right: 4px;');
|
|
var span = document.createElement('span');
|
|
span.setAttribute('style', 'height: ' + element.offsetHeight + 'px;'
|
|
+ ' display: inline-block; vertical-align: baseline;'
|
|
+ ' font-size: 16px; text-decoration: none; color: grey;');
|
|
a.appendChild(span);
|
|
var link = document.createTextNode('🔗');
|
|
span.appendChild(link);
|
|
element.insertBefore(a, element.firstChild);
|
|
|
|
// remove the link icon when the mouse is moved away,
|
|
// but keep it shown if the mouse is over the element, the link or the icon
|
|
hide = function(evt) {
|
|
if (document.elementFromPoint(evt.clientX, evt.clientY) != element
|
|
&& document.elementFromPoint(evt.clientX, evt.clientY) != a
|
|
&& document.elementFromPoint(evt.clientX, evt.clientY) != span
|
|
&& document.elementFromPoint(evt.clientX, evt.clientY) != link
|
|
&& element.contains(a)) {
|
|
element.removeChild(a);
|
|
}
|
|
}
|
|
element.onmouseout = hide;
|
|
a.onmouseout = hide;
|
|
span.onmouseout = hide;
|
|
link.onmouseout = hide;
|
|
}
|
|
}
|
|
}
|
|
|
|
function getExcludedIds() {
|
|
var excluded = {};
|
|
excluded['header'] = true;
|
|
excluded['toc'] = true;
|
|
excluded['toctitle'] = true;
|
|
excluded['content'] = true;
|
|
excluded['preamble'] = true;
|
|
excluded['footer'] = true;
|
|
excluded['footer-text'] = true;
|
|
return excluded;
|
|
}
|
|
</script>
|
|
|
|
++++
|
|
|
|
"""
|
|
|
|
opts = OptionParser()
|
|
opts.add_option('-o', '--out', help='output file')
|
|
opts.add_option('-s', '--src', help='source file')
|
|
opts.add_option('-x', '--suffix', help='suffix for included filenames')
|
|
opts.add_option('-b', '--searchbox', action="store_true", default=True,
|
|
help="generate the search boxes")
|
|
opts.add_option('--no-searchbox', action="store_false", dest='searchbox',
|
|
help="don't generate the search boxes")
|
|
options, _ = opts.parse_args()
|
|
|
|
try:
|
|
out_file = open(options.out, 'w')
|
|
src_file = open(options.src, 'r')
|
|
last_line = ''
|
|
ignore_next_line = False
|
|
last_title = ''
|
|
for line in src_file.xreadlines():
|
|
if PAT_GERRIT.match(last_line):
|
|
# Case of "GERRIT\n------" at the footer
|
|
out_file.write(GERRIT_UPLINK)
|
|
last_line = ''
|
|
elif PAT_SEARCHBOX.match(last_line):
|
|
# Case of 'SEARCHBOX\n---------'
|
|
if options.searchbox:
|
|
out_file.write(SEARCH_BOX)
|
|
last_line = ''
|
|
elif PAT_INCLUDE.match(line):
|
|
# Case of 'include::<filename>'
|
|
match = PAT_INCLUDE.match(line)
|
|
out_file.write(last_line)
|
|
last_line = match.group(1) + options.suffix + match.group(2) + '\n'
|
|
elif PAT_STARS.match(line):
|
|
if PAT_TITLE.match(last_line):
|
|
# Case of the title in '.<title>\n****\nget::<url>\n****'
|
|
match = PAT_TITLE.match(last_line)
|
|
last_title = GET_TITLE % match.group(1)
|
|
else:
|
|
out_file.write(last_line)
|
|
last_title = ''
|
|
elif PAT_GET.match(line):
|
|
# Case of '****\nget::<url>\n****' in rest api
|
|
url = PAT_GET.match(line).group(1)
|
|
out_file.write(GET_MACRO.format(url) % last_title)
|
|
ignore_next_line = True
|
|
elif ignore_next_line:
|
|
# Handle the trailing '****' of the 'get::' case
|
|
last_line = ''
|
|
ignore_next_line = False
|
|
else:
|
|
out_file.write(last_line)
|
|
last_line = line
|
|
out_file.write(last_line)
|
|
out_file.write(LINK_SCRIPT)
|
|
out_file.close()
|
|
except IOError as err:
|
|
sys.stderr.write(
|
|
"error while expanding %s to %s: %s" % (options.src, options.out, err))
|
|
exit(1)
|