| # 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} |