|
From: <mi...@us...> - 2026-08-31 08:26:53
|
Revision: 10397
http://sourceforge.net/p/docutils/code/10397
Author: milde
Date: 2026-08-31 08:26:50 +0000 (Mon, 31 Aug 2026)
Log Message:
-----------
Store the "colwidth" attribute as a `str` variable.
To match the definition as a measure (value + optional unit) in the
"Exchange Table Model", the `"colwidth" attribute`_ is stored as
a `str` value (instead of `int`) in Python element instances.
This opens the way to allow fixed length units in later Docutils versions
and to change the default unit to the Exchange Table Model's "pt".
The "xml" writer adds the "proportional unit" symbol "*" to "colwidth" values.
Modified Paths:
--------------
trunk/docutils/HISTORY.rst
trunk/docutils/RELEASE-NOTES.rst
trunk/docutils/docs/ref/doctree.rst
trunk/docutils/docutils/nodes.py
trunk/docutils/docutils/parsers/rst/directives/__init__.py
trunk/docutils/docutils/parsers/rst/directives/tables.py
trunk/docutils/docutils/parsers/rst/states.py
trunk/docutils/docutils/writers/docutils_xml.py
trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py
Modified: trunk/docutils/HISTORY.rst
===================================================================
--- trunk/docutils/HISTORY.rst 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/HISTORY.rst 2026-08-31 08:26:50 UTC (rev 10397)
@@ -58,6 +58,7 @@
generate identifiers only if the `legacy_ids`_ setting is True.
- Add `Targetable` to parent classes of `inline` to allow test whether
inline internal targets are referenced.
+ - `validate_colwidth()` now returns a `str`.
* docutils/parsers/__init__.py
@@ -76,6 +77,8 @@
* docutils/parsers/rst/directives/__init__.py
- Remove `length_units` (replaced by the tuple CSS3_LENGTH_UNITS).
+ - New option conversion function `column_widths()` (provisional):
+ ignore "proportional unit symbol" ``*``, return list of strings.
* docutils/parsers/rst/directives/images.py
@@ -95,6 +98,8 @@
arguments has content above and below directive options.
- Ignore the "match_titles" argument of `RSTState.nested_list_parse()`.
- Use <inline> elements in `inline_internal_target()`.
+ - The "colwidth_" attribute of `nodes.colspec` instances
+ is now stored as a `str` (instead of numerical) value .
* docutils/readers/standalone.py
@@ -182,6 +187,8 @@
- Do not activate the "external-general-entities" feature of the
SAX parser used to check raw XML content. Fixes bug #521.
+ - Add the "proportional unit" ``*`` to "colwidth_" attribute values
+ (to comply with with the CALS `Exchange Table Model`).
Release 0.23 (2026-05-27)
@@ -5081,10 +5088,11 @@
.. _length unit:
.. _length units: docs/ref/rst/restructuredtext.html#length-units
-.. _<meta>: docs/ref/doctree.html#meta
+.. _colwidth: docs/ref/doctree.html#colwidth
.. _<image>: docs/ref/doctree.html#image
.. _<inline>: docs/ref/doctree.html#inline
.. _<literal>: docs/ref/doctree.html#literal
+.. _<meta>: docs/ref/doctree.html#meta
.. Emacs settings
Modified: trunk/docutils/RELEASE-NOTES.rst
===================================================================
--- trunk/docutils/RELEASE-NOTES.rst 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/RELEASE-NOTES.rst 2026-08-31 08:26:50 UTC (rev 10397)
@@ -50,10 +50,9 @@
deprecated and will be invalid in Docutils 2.0. (The "rst" parser
uses <inline> elements for `inline targets`_ since Docutils 1.0.)
-* To match the definition in the "Exchange Table Model", the
- `"colwidth" attribute`_ will be stored as a `str` (instead of
- numerical) value in Python element instances in Docutils 1.0.
- Proportional values will be stored with unit "*" in Docutils 2.0.
+* To match the definition in the "Exchange Table Model", values of the
+ `"colwidth" attribute`_ will be stored with the "proportional unit
+ symbol" ``*`` and accept fixed length units in Docutils 2.0.
The default unit will change to "pt" in Docutils 3.0.
* The `\<doctest_block>`_ element will be deprecated in Docutils 1.0.
@@ -217,6 +216,9 @@
to customize the <table> element's attribute list in Docutils 1.0.
- Inline `\<target>`_ elements and <target> elements with content are
deprecated.
+ - The `"colwidth" attribute`_ of `nodes.colspec` instances
+ is now stored as a `str` (instead of `int`) value.
+ The XML writer adds the "proportional unit symbol" ``*``.
Configuration changes:
- `Auto-detection`_ of the input encoding is no longer supported.
Modified: trunk/docutils/docs/ref/doctree.rst
===================================================================
--- trunk/docutils/docs/ref/doctree.rst 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/docs/ref/doctree.rst 2026-08-31 08:26:50 UTC (rev 10397)
@@ -4733,13 +4733,13 @@
(positive number followed by "*", e.g., "5*" for 5 times the
`unit proportion`_ , or just "*" for one unit proportion)
or a *fixed measure* (e.g., 2.5cm).
+
Docutils supports only proportional measures.
.. important::
- Currently, Docutils stores "colwidth" values as numbers and
- interprets unitless values as proportional measures while the
- `Exchange Table Model` uses the default unit "pt".
- This will change__ in future versions of Docutils.
+ Currently, Docutils interprets unitless values as proportional
+ measures while the `Exchange Table Model` uses the default unit "pt".
+ This will change__ in future versions.
__ https://www.oasis-open.org/specs/tm9901.html#AEN530
__ ../../RELEASE-NOTES.html#document-tree-docutils-dtd
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/docutils/nodes.py 2026-08-31 08:26:50 UTC (rev 10397)
@@ -2613,9 +2613,19 @@
__ https://docutils.sourceforge.io/docs/ref/doctree.html#colwidth
"""
- # Move current implementation of validate_colwidth() here
- # in Docutils 1.0
- return validate_colwidth(self.get('colwidth', ''))
+ measure = self.get('colwidth', '')
+ if isinstance(measure, (int, float)):
+ value = measure
+ elif measure in ('*', ''): # short for '1*'
+ value = 1
+ else:
+ try:
+ value, _unit = parse_measure(measure, unit_pattern='[*]?')
+ except ValueError:
+ value = -1
+ if value <= 0:
+ raise ValueError(f'"{measure}" is no proportional measure.')
+ return value
class thead(Part, Element):
@@ -3227,29 +3237,27 @@
return f'{value}{unit}'
-def validate_colwidth(measure: str|int|float) -> int|float:
+def validate_colwidth(measure: str|int|float) -> str:
"""Validate the "colwidth__" attribute.
Provisional:
- `measure` must be a `str` and will be returned as normalized `str`
- (with unit "*" for proportional values) in Docutils 1.0.
+ Accept fixed length units in Docutils 2.0.
+ The default unit will change to "pt" in Docutils 3.0.
- The default unit will change to "pt" in Docutils 2.0.
-
__ https://docutils.sourceforge.io/docs/ref/doctree.html#colwidth
"""
if isinstance(measure, (int, float)):
- value = measure
+ value, unit = measure, ''
elif measure in ('*', ''): # short for '1*'
- value = 1
+ value, unit = 1, ''
else:
try:
- value, _unit = parse_measure(measure, unit_pattern='[*]?')
+ value, unit = parse_measure(measure, unit_pattern='[*]?')
except ValueError:
value = -1
if value <= 0:
raise ValueError(f'"{measure}" is no proportional measure.')
- return value
+ return f'{value}{unit}'
def validate_NMTOKEN(value: str) -> str:
Modified: trunk/docutils/docutils/parsers/rst/directives/__init__.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/__init__.py 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/docutils/parsers/rst/directives/__init__.py 2026-08-31 08:26:50 UTC (rev 10397)
@@ -399,6 +399,8 @@
(Directive option conversion function.)
Raises ValueError for non-positive-integer values.
+
+ Provisional. May be removed in Docutils 2.0 or later.
"""
if ',' in argument:
entries = argument.split(',')
@@ -482,3 +484,23 @@
return parsers.get_parser_class(argument)
except ImportError as err:
raise ValueError(str(err))
+
+
+def column_widths(argument: str) -> list[str]:
+ """
+ Conversion function for the ``widths`` option of the table directives.
+
+ Converts string with a space- or comma-separated list of proportional
+ width values (with optional unit symbol "*") into a list of values.
+ Raises ValueError for non-positive and non-integer values.
+
+ Provisional.
+ See docs/ref/rst/directives.html#table-options
+ and docs/ref/doctree.html#colwidth.
+ """
+ # remove optional "proportional unit" symbol:
+ argument = argument.replace('*', '')
+ # extract values:
+ widths = positive_int_list(argument)
+ # return list of strings
+ return [f'{width}' for width in widths]
Modified: trunk/docutils/docutils/parsers/rst/directives/tables.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/tables.py 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/docutils/parsers/rst/directives/tables.py 2026-08-31 08:26:50 UTC (rev 10397)
@@ -39,7 +39,7 @@
'align': align,
'width': directives.length_or_percentage_or_unitless,
'widths': directives.value_or(('auto', 'grid'),
- directives.positive_int_list)}
+ directives.column_widths)}
has_content = True
def make_title(self):
@@ -108,7 +108,7 @@
raise SystemMessagePropagation(error)
col_widths = self.widths
elif n_cols:
- col_widths = [100 // n_cols] * n_cols
+ col_widths = [f'{100//n_cols}'] * n_cols
else:
error = self.reporter.error('No table data detected in CSV file.',
nodes.literal_block(self.block_text, self.block_text),
@@ -181,7 +181,7 @@
'header': directives.unchanged,
'width': directives.length_or_percentage_or_unitless,
'widths': directives.value_or(('auto', ),
- directives.positive_int_list),
+ directives.column_widths),
'file': directives.path,
'url': directives.uri,
'encoding': directives.encoding,
@@ -377,7 +377,7 @@
'stub-columns': directives.nonnegative_int,
'width': directives.length_or_percentage_or_unitless,
'widths': directives.value_or(('auto', ),
- directives.positive_int_list),
+ directives.column_widths),
'class': directives.class_option,
'name': directives.unchanged,
'align': align}
Modified: trunk/docutils/docutils/parsers/rst/states.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/states.py 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/docutils/parsers/rst/states.py 2026-08-31 08:26:50 UTC (rev 10397)
@@ -1915,7 +1915,7 @@
tgroup = nodes.tgroup(cols=len(colwidths))
table += tgroup
for colwidth in colwidths:
- colspec = nodes.colspec(colwidth=colwidth)
+ colspec = nodes.colspec(colwidth=str(colwidth))
if stub_columns:
colspec.attributes['stub'] = True
stub_columns -= 1
Modified: trunk/docutils/docutils/writers/docutils_xml.py
===================================================================
--- trunk/docutils/docutils/writers/docutils_xml.py 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/docutils/writers/docutils_xml.py 2026-08-31 08:26:50 UTC (rev 10397)
@@ -157,6 +157,18 @@
def depart_Text(self, node) -> None:
pass
+ def visit_colspec(self, node):
+ # add the "proportional unit" (``*``)
+ # provisional, will be removed in Docutils 2.0
+ cspec = node.copy()
+ cwidth = cspec['colwidth']
+ if cwidth and cwidth[-1].isdigit():
+ cspec['colwidth'] = f"{cwidth}*"
+ self.default_visit(cspec)
+
+ def depart_cospec(self, node):
+ self.default_departure(node)
+
def visit_raw(self, node):
if 'xml' not in node.get('format', '').split():
# skip other raw content?
Modified: trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/test/functional/expected/standalone_rst_docutils_xml.xml 2026-08-31 08:26:50 UTC (rev 10397)
@@ -853,8 +853,8 @@
<legend>
<table>
<tgroup cols="2">
- <colspec colwidth="12"></colspec>
- <colspec colwidth="47"></colspec>
+ <colspec colwidth="12*"></colspec>
+ <colspec colwidth="47*"></colspec>
<tbody>
<row>
<entry>
@@ -929,8 +929,8 @@
<table align="left">
<title>left-aligned table</title>
<tgroup cols="2">
- <colspec colwidth="5"></colspec>
- <colspec colwidth="5"></colspec>
+ <colspec colwidth="5*"></colspec>
+ <colspec colwidth="5*"></colspec>
<thead>
<row>
<entry>
@@ -964,8 +964,8 @@
<table align="center">
<title>center-aligned table</title>
<tgroup cols="2">
- <colspec colwidth="5"></colspec>
- <colspec colwidth="5"></colspec>
+ <colspec colwidth="5*"></colspec>
+ <colspec colwidth="5*"></colspec>
<thead>
<row>
<entry>
@@ -999,8 +999,8 @@
<table align="right">
<title>right-aligned table</title>
<tgroup cols="2">
- <colspec colwidth="5"></colspec>
- <colspec colwidth="5"></colspec>
+ <colspec colwidth="5*"></colspec>
+ <colspec colwidth="5*"></colspec>
<thead>
<row>
<entry>
@@ -1038,9 +1038,9 @@
<target refid="target2"></target>
<table classes="colwidths-auto" ids="target2 target1" names="target2 target1">
<tgroup cols="3">
- <colspec colwidth="7"></colspec>
- <colspec colwidth="7"></colspec>
- <colspec colwidth="10"></colspec>
+ <colspec colwidth="7*"></colspec>
+ <colspec colwidth="7*"></colspec>
+ <colspec colwidth="10*"></colspec>
<thead>
<row>
<entry>
@@ -1254,9 +1254,9 @@
elements in one logical paragraph. First a table,</paragraph>
<table>
<tgroup cols="3">
- <colspec colwidth="20"></colspec>
- <colspec colwidth="20"></colspec>
- <colspec colwidth="20"></colspec>
+ <colspec colwidth="20*"></colspec>
+ <colspec colwidth="20*"></colspec>
+ <colspec colwidth="20*"></colspec>
<tbody>
<row>
<entry>
@@ -1424,9 +1424,9 @@
<paragraph>This table has a cell spanning two columns:</paragraph>
<table>
<tgroup cols="3">
- <colspec colwidth="5"></colspec>
- <colspec colwidth="5"></colspec>
- <colspec colwidth="6"></colspec>
+ <colspec colwidth="5*"></colspec>
+ <colspec colwidth="5*"></colspec>
+ <colspec colwidth="6*"></colspec>
<thead>
<row>
<entry morecols="1">
@@ -1502,9 +1502,9 @@
<paragraph>Here's a table with cells spanning several rows:</paragraph>
<table>
<tgroup cols="3">
- <colspec colwidth="24"></colspec>
- <colspec colwidth="12"></colspec>
- <colspec colwidth="18"></colspec>
+ <colspec colwidth="24*"></colspec>
+ <colspec colwidth="12*"></colspec>
+ <colspec colwidth="18*"></colspec>
<thead>
<row>
<entry>
@@ -1559,10 +1559,10 @@
<paragraph>Here's a complex table, which should test all features.</paragraph>
<table>
<tgroup cols="4">
- <colspec colwidth="24"></colspec>
- <colspec colwidth="12"></colspec>
- <colspec colwidth="10"></colspec>
- <colspec colwidth="10"></colspec>
+ <colspec colwidth="24*"></colspec>
+ <colspec colwidth="12*"></colspec>
+ <colspec colwidth="10*"></colspec>
+ <colspec colwidth="10*"></colspec>
<thead>
<row>
<entry>
@@ -1652,9 +1652,9 @@
<table classes="colwidths-given test" width="95%">
<title>list table with integral header</title>
<tgroup cols="3">
- <colspec colwidth="10" stub="1"></colspec>
- <colspec colwidth="8"></colspec>
- <colspec colwidth="20"></colspec>
+ <colspec colwidth="10*" stub="1"></colspec>
+ <colspec colwidth="8*"></colspec>
+ <colspec colwidth="20*"></colspec>
<thead>
<row>
<entry>
@@ -1709,8 +1709,8 @@
<table align="center" classes="colwidths-auto">
<title>center aligned list table</title>
<tgroup cols="2">
- <colspec colwidth="50"></colspec>
- <colspec colwidth="50"></colspec>
+ <colspec colwidth="50*"></colspec>
+ <colspec colwidth="50*"></colspec>
<tbody>
<row>
<entry>
Modified: trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py
===================================================================
--- trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py 2026-08-30 19:26:53 UTC (rev 10396)
+++ trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py 2026-08-31 08:26:50 UTC (rev 10397)
@@ -165,12 +165,12 @@
# from the Exchange Table Model. This will eventually change
# (see https://docutils.sourceforge.io/docs/ref/doctree.html#colwidth).
xml = '<colspec colwidth="33*" stub="1" />'
- expected = {'colwidth': 33, 'stub': 1}
+ expected = {'colwidth': '33*', 'stub': True}
node = docutils_xml.parse_element(xml)
self.assertEqual(node.attributes, self.common_attributes | expected)
# Note: the upstream default unit is "pt", not "*".
xml = '<colspec colwidth="33" stub="1" />'
- expected = {'colwidth': 33, 'stub': 1}
+ expected = {'colwidth': '33', 'stub': True}
node = docutils_xml.parse_element(xml)
self.assertEqual(node.attributes, self.common_attributes | expected)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|