blob: ae109308d04cd5754f20f77b81fa16f0fbbeb366 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
import os
import pathlib
import subprocess
from typing import Any, Dict
from sphinx.ext.doctest import (DocTestBuilder, TestcodeDirective,
TestoutputDirective, doctest, sphinx)
from sphinx.locale import __
class JavaTestcodeDirective(TestcodeDirective):
def run(self):
node_list = super().run()
node_list[0]["language"] = "java"
return node_list
class JavaDocTestBuilder(DocTestBuilder):
"""
Runs java test snippets in the documentation.
"""
name = "javadoctest"
epilog = __(
"Java testing of doctests in the sources finished, look at the "
"results in %(outdir)s/output.txt."
)
def compile(
self, code: str, name: str, type: str, flags: Any, dont_inherit: bool
) -> Any:
# go to project that contains all your arrow maven dependencies
path_arrow_project = pathlib.Path(__file__).parent.parent / "source" / "demo"
# create list of all arrow jar dependencies
subprocess.check_call(
[
"mvn",
"-q",
"dependency:build-classpath",
"-DincludeTypes=jar",
"-Dmdep.outputFile=.cp.tmp",
f"-Darrow.version={self.env.config.version}",
],
cwd=path_arrow_project,
text=True,
)
if not (path_arrow_project / ".cp.tmp").exists():
raise RuntimeError(
__("invalid process to create jshell dependencies library")
)
# get list of all arrow jar dependencies
with open(path_arrow_project / ".cp.tmp") as f:
stdout_dependency = f.read()
if not stdout_dependency:
raise RuntimeError(
__("invalid process to list jshell dependencies library")
)
# execute java testing code thru jshell and read output
# JDK11 support '-' This allows the pipe to work as expected without requiring a shell
# Migrating to /dev/stdin to also support JDK9+
proc_jshell_process = subprocess.Popen(
["jshell", "-R--add-opens=java.base/java.nio=ALL-UNNAMED", "--class-path", stdout_dependency, "-s", "/dev/stdin"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True,
)
out_java_arrow, err_java_arrow = proc_jshell_process.communicate(code)
if err_java_arrow:
raise RuntimeError(__("invalid process to run jshell"))
# continue with python logic code to do java output validation
output = f"print('''{self.clean_output(out_java_arrow)}''')"
# continue with sphinx default logic
return compile(output, name, self.type, flags, dont_inherit)
def clean_output(self, output: str):
if output[-3:] == '-> ':
output = output[:-3]
if output[-1:] == '\n':
output = output[:-1]
output = (4*' ').join(output.split('\t'))
return output
def setup(app) -> Dict[str, Any]:
app.add_directive("testcode", JavaTestcodeDirective)
app.add_directive("testoutput", TestoutputDirective)
app.add_builder(JavaDocTestBuilder)
app.add_config_value("doctest_show_successes", True, False)
# this config value adds to sys.path
app.add_config_value("doctest_path", [], False)
app.add_config_value("doctest_test_doctest_blocks", "default", False)
app.add_config_value("doctest_global_setup", "", False)
app.add_config_value("doctest_global_cleanup", "", False)
app.add_config_value(
"doctest_default_flags",
doctest.DONT_ACCEPT_TRUE_FOR_1
| doctest.ELLIPSIS
| doctest.IGNORE_EXCEPTION_DETAIL,
False,
)
return {"version": sphinx.__display_version__, "parallel_read_safe": True}