SF.net SVN: docutils:[9936 ] trunk/docutils
milde--- via Docutils-checkins <[email protected]>
| Newsgroups | gmane.text.docutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
Revision: 9936
http://sourceforge.net/p/docutils/code/9936
Author: milde
Date: 2024-09-20 08:32:41 +0000 (Fri, 20 Sep 2024)
Log Message:
-----------
Use `nodes.parse_measure()` in rST directive option conversion.
Simplify `parsers.rst.directives.get_measure()` by using
`nodes.parse_measure()`.
Sort the list of supported length units in the order used in the
rST specification (based on the CSS specification).
Update and extend the lenght value handling tests.
Clarify and test behaviour:
* case of length units is preserved (in contrast to CSS)
* the restriction of supported units is a rST feature
while the Docutils Doctree allows any run of ASCII letters + {U+03BC}
or a percent sign as units on attributes with value type "measure".
Modified Paths:
--------------
trunk/docutils/docutils/parsers/rst/directives/__init__.py
trunk/docutils/test/test_nodes.py
trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_images.py
Modified: trunk/docutils/docutils/parsers/rst/directives/__init__.py
===================================================================
--- trunk/docutils/docutils/parsers/rst/directives/__init__.py 2024-09-20 08:32:28 UTC (rev 9935)
+++ trunk/docutils/docutils/parsers/rst/directives/__init__.py 2024-09-20 08:32:41 UTC (rev 9936)
@@ -244,26 +244,24 @@
return nonnegative_int(argument)
-length_units = ['em', 'ex', 'px', 'in', 'cm', 'mm', 'pt', 'pc']
+length_units = ['em', 'ex', 'in', 'cm', 'mm', 'pt', 'pc', 'px']
def get_measure(argument, units):
"""
- Check for a positive argument of one of the units and return a
- normalized string of the form "<value><unit>" (without space in
- between).
- (Directive option conversion function.)
+ Check for a positive argument of one of the `units`.
+ Return a normalized string of the form "<value><unit>"
+ (without space inbetween).
+
To be called from directive option conversion functions.
"""
- match = re.match(r'^([0-9.]+) *(%s)$' % '|'.join(units), argument)
- try:
- float(match.group(1))
- except (AttributeError, ValueError):
+ value, unit = nodes.parse_measure(argument)
+ if value < 0 or unit not in units:
raise ValueError(
- 'not a positive measure of one of the following units:\n"%s"'
- % '" "'.join(units))
- return match.group(1) + match.group(2)
+ 'not a positive number or measure of one of the following units:\n'
+ + ', '.join(u for u in units if u))
+ return f'{value}{unit}'
def length_or_unitless(argument: str) -> str:
@@ -289,12 +287,11 @@
"""
try:
return get_measure(argument, length_units + ['%'])
- except ValueError:
+ except ValueError as error:
try:
return get_measure(argument, ['']) + default
except ValueError:
- # raise ValueError with list of valid units:
- return get_measure(argument, length_units + ['%'])
+ raise error
def class_option(argument: str) -> list[str]:
Modified: trunk/docutils/test/test_nodes.py
===================================================================
--- trunk/docutils/test/test_nodes.py 2024-09-20 08:32:28 UTC (rev 9935)
+++ trunk/docutils/test/test_nodes.py 2024-09-20 08:32:41 UTC (rev 9936)
@@ -1172,10 +1172,21 @@
def test_validate_measure(self):
# number (may be decimal fraction) + optional unit
- self.assertEqual(nodes.validate_measure('8ex'), '8ex')
+ # internal whitespace is removed
+ self.assertEqual(nodes.validate_measure('8 ex'), '8ex')
self.assertEqual(nodes.validate_measure('2'), '2')
- # internal whitespace is removed
+ # unit is "%" or a run of ASCII letters plus "µ"; case is preserved
self.assertEqual(nodes.validate_measure('3.5 %'), '3.5%')
+ self.assertEqual(nodes.validate_measure('300 µm'), '300µm')
+ self.assertEqual(nodes.validate_measure('4 kHz'), '4kHz')
+ # other characters and whitespace are not allowed in a unit identifier
+ with self.assertRaisesRegex(ValueError, 'no valid measure'):
+ nodes.validate_measure('3 micro-farads')
+ with self.assertRaisesRegex(ValueError, 'no valid measure'):
+ nodes.validate_measure('3 micro farads')
+ # a number is required
+ with self.assertRaisesRegex(ValueError, '"ex" is no valid measure'):
+ nodes.validate_measure('ex')
# padding whitespace is not valid
with self.assertRaisesRegex(ValueError, '"8ex " is no valid measure'):
nodes.validate_measure('8ex ')
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 2024-09-20 08:32:28 UTC (rev 9935)
+++ trunk/docutils/test/test_parsers/test_docutils_xml/test_parse_element.py 2024-09-20 08:32:41 UTC (rev 9936)
@@ -82,9 +82,10 @@
def test_element_with_attributes(self):
xml = ('<image align="left" alt="a barking dog" height="3ex"'
- ' loading="embed" scale="3" uri="dog.jpg" width="4cm"/>')
+ ' loading="embed" scale="3" uri="dog.jpg" width="4.50 cm"/>')
node = docutils_xml.parse_element(xml)
- self.assertEqual(xml, str(node))
+ # attribute values are normalized:
+ self.assertEqual(xml.replace('4.50 cm', '4.5cm'), str(node))
def test_element_with_invalid_attributes(self):
"""Silently accept invalid attribute names and values.
@@ -91,13 +92,15 @@
Validation reports problems.
"""
- xml = ('<image breadth="3 cm" height="3 inch"/>')
+ xml = ('<image breadth="3 cm" height="three inch"/>')
node = docutils_xml.parse_element(xml)
- self.assertEqual(xml.replace('3 inch', '3inch'), str(node))
- with self.assertRaisesRegex(ValueError,
- 'Element <image breadth="3 cm".*invalid:\n'
- '.*"breadth" not one of "ids", '
- ):
+ self.assertEqual(xml, str(node))
+ with self.assertRaisesRegex(
+ ValueError,
+ 'Element <image .*> invalid:\n'
+ ' Attribute "breadth" not one of "ids", .*, "loading".\n'
+ ' Attribute "height" has invalid value "three inch".\n'
+ ' "three inch" is no valid measure.'):
node.validate()
@@ -116,8 +119,8 @@
'names': []}
def test_alt(self): # CDATA (str)
- xml = ('<image alt="a barking dog" align="left" height="3ex"'
- ' loading="embed" scale="3" uri="dog.jpg" width="4cm"/>')
+ xml = ('<image alt="a barking dog" align="left" height="3 ex"'
+ ' loading="embed" scale="3" uri="dog.jpg" width="4 cm"/>')
expected = {'alt': 'a barking dog',
'align': 'left',
'height': '3ex',
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_images.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_images.py 2024-09-20 08:32:28 UTC (rev 9935)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_images.py 2024-09-20 08:32:41 UTC (rev 9936)
@@ -23,6 +23,8 @@
class ParserTestCase(unittest.TestCase):
+ maxDiff = None
+
def test_parser(self):
parser = Parser()
settings = get_default_settings(Parser)
@@ -170,14 +172,34 @@
<document source="test data">
<image height="100em" uri="picture.png" width="200px">
"""],
+# as in CSS3, units are case-insensitive (new in Docutils 0.22)
["""\
.. image:: picture.png
+ :width: 50 mm
+ :height: 100 em
+""",
+"""\
+<document source="test data">
+ <image height="100em" uri="picture.png" width="50mm">
+"""],
+# TODO: support CSS3 units (cf. [feature-requests:#57]
+["""\
+.. image:: picture.png
:width: 50%
- :height: 10mm
+ :height: 10vh
""",
"""\
<document source="test data">
- <image height="10mm" uri="picture.png" width="50%">
+ <system_message level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Error in "image" directive:
+ invalid option value: (option: "height"; value: '10vh')
+ not a positive number or measure of one of the following units:
+ em, ex, in, cm, mm, pt, pc, px.
+ <literal_block xml:space="preserve">
+ .. image:: picture.png
+ :width: 50%
+ :height: 10vh
"""],
["""\
.. image:: picture.png
@@ -190,8 +212,8 @@
<paragraph>
Error in "image" directive:
invalid option value: (option: "height"; value: \'40%\')
- not a positive measure of one of the following units:
- "em" "ex" "px" "in" "cm" "mm" "pt" "pc" "".
+ not a positive number or measure of one of the following units:
+ em, ex, in, cm, mm, pt, pc, px.
<literal_block xml:space="preserve">
.. image:: picture.png
:width: 50%
@@ -207,8 +229,8 @@
<paragraph>
Error in "image" directive:
invalid option value: (option: "width"; value: \'20mc\')
- not a positive measure of one of the following units:
- "em" "ex" "px" "in" "cm" "mm" "pt" "pc" "%".
+ not a positive number or measure of one of the following units:
+ em, ex, in, cm, mm, pt, pc, px, %.
<literal_block xml:space="preserve">
.. image:: picture.png
:width: 20mc
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
_______________________________________________
Docutils-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/docutils-checkins