diff --git a/CHANGES b/CHANGES index c75929ca6a3..a183eba66b1 100644 --- a/CHANGES +++ b/CHANGES @@ -40,6 +40,8 @@ Incompatible changes * #8769: LaTeX refactoring: split sphinx.sty into multiple files and rename some auxiliary files created in ``latex`` build output repertory * #8937: Use explicit title instead of +* #8487: The :file: option for csv-table directive now recognizes an absolute + path as a relative path from source directory Deprecated ---------- diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 10c1dfb22ca..96bc84ff3bc 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -32,11 +32,6 @@ The following is a list of deprecated interfaces. - TBD - ``logo_url`` - * - ``sphinx.directives.patches.CSVTable`` - - 4.0 - - 6.0 - - ``docutils.parsers.rst.diretives.tables.CSVTable`` - * - ``sphinx.directives.patches.ListTable`` - 4.0 - 6.0 diff --git a/sphinx/directives/patches.py b/sphinx/directives/patches.py index 3cfad5a3f36..1c3cfd853bc 100644 --- a/sphinx/directives/patches.py +++ b/sphinx/directives/patches.py @@ -6,7 +6,9 @@ :license: BSD, see LICENSE for details. """ +import os import warnings +from os import path from typing import TYPE_CHECKING, Any, Dict, List, Tuple, cast from docutils import nodes @@ -18,13 +20,19 @@ from sphinx.deprecation import RemovedInSphinx60Warning from sphinx.directives import optional_int from sphinx.domains.math import MathDomain +from sphinx.locale import __ +from sphinx.util import logging from sphinx.util.docutils import SphinxDirective from sphinx.util.nodes import set_source_info +from sphinx.util.osutil import SEP, os_path, relpath if TYPE_CHECKING: from sphinx.application import Sphinx +logger = logging.getLogger(__name__) + + class Figure(images.Figure): """The figure directive which applies `:name:` option to the figure node instead of the image node. @@ -87,21 +95,25 @@ def make_title(self) -> Tuple[nodes.title, List[system_message]]: class CSVTable(tables.CSVTable): - """The csv-table directive which sets source and line information to its caption. - - Only for docutils-0.13 or older version.""" + """The csv-table directive which searches a CSV file from Sphinx project's source + directory when an absolute path is given via :file: option. + """ def run(self) -> List[Node]: - warnings.warn('CSVTable is deprecated.', - RemovedInSphinx60Warning) - return super().run() + if 'file' in self.options and self.options['file'].startswith((SEP, os.sep)): + env = self.state.document.settings.env + filename = self.options['file'] + if path.exists(filename): + logger.warning(__('":file:" option for csv-table directive now recognizes ' + 'an absolute path as a relative path from source directory. ' + 'Please update your document.'), + location=(env.docname, self.lineno)) + else: + abspath = path.join(env.srcdir, os_path(self.options['file'][1:])) + docdir = path.dirname(env.doc2path(env.docname)) + self.options['file'] = relpath(abspath, docdir) - def make_title(self) -> Tuple[nodes.title, List[system_message]]: - title, message = super().make_title() - if title: - set_source_info(self, title) - - return title, message + return super().run() class ListTable(tables.ListTable): @@ -224,6 +236,7 @@ def add_target(self, ret: List[Node]) -> None: def setup(app: "Sphinx") -> Dict[str, Any]: directives.register_directive('figure', Figure) directives.register_directive('meta', Meta) + directives.register_directive('csv-table', CSVTable) directives.register_directive('code', Code) directives.register_directive('math', MathDirective) diff --git a/tests/test_directive_patch.py b/tests/test_directive_patch.py index 7dc568b1d5e..b28e0f1e57d 100644 --- a/tests/test_directive_patch.py +++ b/tests/test_directive_patch.py @@ -8,6 +8,7 @@ :license: BSD, see LICENSE for details. """ +import pytest from docutils import nodes from sphinx.testing import restructuredtext @@ -54,6 +55,37 @@ def test_code_directive(app): assert_node(doctree[0], language="python", linenos=True, highlight_args={'linenostart': 5}) +@pytest.mark.sphinx(testroot='directive-csv-table') +def test_csv_table_directive(app): + # relative path from current document + text = ('.. csv-table::\n' + ' :file: example.csv\n') + doctree = restructuredtext.parse(app, text, docname="subdir/index") + assert_node(doctree, + ([nodes.table, nodes.tgroup, (nodes.colspec, + nodes.colspec, + nodes.colspec, + [nodes.tbody, nodes.row])],)) + assert_node(doctree[0][0][3][0], + ([nodes.entry, nodes.paragraph, "FOO"], + [nodes.entry, nodes.paragraph, "BAR"], + [nodes.entry, nodes.paragraph, "BAZ"])) + + # absolute path from source directory + text = ('.. csv-table::\n' + ' :file: /example.csv\n') + doctree = restructuredtext.parse(app, text, docname="subdir/index") + assert_node(doctree, + ([nodes.table, nodes.tgroup, (nodes.colspec, + nodes.colspec, + nodes.colspec, + [nodes.tbody, nodes.row])],)) + assert_node(doctree[0][0][3][0], + ([nodes.entry, nodes.paragraph, "foo"], + [nodes.entry, nodes.paragraph, "bar"], + [nodes.entry, nodes.paragraph, "baz"])) + + def test_math_directive(app): # normal case text = '.. math:: E = mc^2'