Skip to content

Commit c3aa06e

Browse files
committed
Add ability to select measuring unit for attributes
This patch adds ability explicitly specify measuring units (in requirements file) for paragraphs, sections and fonts size
1 parent 250e9fa commit c3aa06e

File tree

5 files changed

+133
-87
lines changed

5 files changed

+133
-87
lines changed

examples/example_1.yaml

+30-24
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,41 @@
22
styles:
33
Heading 1:
44
font:
5-
- 14.0
6-
- bold
7-
- Times New Roman
5+
unit: pt
6+
attributes:
7+
- 14
8+
- bold
9+
- Times New Roman
810
paragraph:
9-
alignment: 1
10-
line_spacing: 1.0
11+
unit: cm
12+
attributes:
13+
alignment: 1
14+
line_spacing: 1
1115
Heading 2:
1216
font:
13-
- 14.0
14-
- bold
15-
- Times New Roman
17+
unit: pt
18+
attributes:
19+
- 14
20+
- bold
21+
- Times New Roman
1622
paragraph:
17-
alignment: 0
18-
line_spacing: 1.0
23+
unit: cm
24+
attributes:
25+
alignment: 0
26+
line_spacing: 1
1927
Normal:
2028
font:
21-
- 14.0
22-
- Times New Roman
29+
unit: pt
30+
attributes:
31+
- 14
32+
- Times New Roman
2333
paragraph:
24-
alignment: 0
25-
line_spacing: 1.0
34+
unit: cm
35+
attributes:
36+
alignment: 0
37+
line_spacing: 1
2638
sections:
27-
- right_margin: 1.0
28-
start_type: 2
29-
top_margin: 2.0
30-
footer_distance: 1.25
31-
header_distance: 1.25
32-
left_margin: 2.0
33-
bottom_margin: 2.0
34-
orientation: 0
35-
page_height: 29.7
36-
page_width: 21.0
39+
- unit: cm
40+
attributes:
41+
right_margin: 1
42+
start_type: 2

examples/example_2.yaml

+40-26
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,51 @@
22
styles:
33
papertitle:
44
font:
5-
- 14.0
6-
- bold
7-
- Times New Roman
5+
unit: pt
6+
attributes:
7+
- 14.0
8+
- bold
9+
- Times New Roman
810
paragraph:
9-
alignment: 1
10-
line_spacing: 0.635
11-
first_line_indent: 0
11+
unit: cm
12+
attributes:
13+
alignment: 1
14+
line_spacing: 0.635
15+
first_line_indent: 0
1216
heading1:
1317
font:
14-
- 12.0
15-
- cs_bold
16-
- Times New Roman
18+
unit: pt
19+
attributes:
20+
- 12.0
21+
- cs_bold
22+
- Times New Roman
1723
paragraph:
18-
alignment: 0
19-
line_spacing: 0.529
24+
unit: cm
25+
attributes:
26+
alignment: 0
27+
line_spacing: 0.529
2028
Normal:
2129
font:
22-
- 10.0
23-
- Times New Roman
30+
unit: pt
31+
attributes:
32+
- 10.0
33+
- Times New Roman
2434
paragraph:
25-
alignment: 3
26-
line_spacing: 1
27-
first_line_indent: 0.4
35+
unit: cm
36+
attributes:
37+
alignment: 3
38+
line_spacing: 1
39+
first_line_indent: 0.4
2840
sections:
29-
- right_margin: 4.4
30-
start_type: 2
31-
top_margin: 5.2
32-
footer_distance: 4.1
33-
header_distance: 0.0
34-
left_margin: 4.4
35-
bottom_margin: 5.2
36-
orientation: 0
37-
page_height: 29.7
38-
page_width: 21.0
41+
- unit: cm
42+
attributes:
43+
right_margin: 4.4
44+
start_type: 2
45+
top_margin: 5.2
46+
footer_distance: 4.1
47+
header_distance: 0.0
48+
left_margin: 4.4
49+
bottom_margin: 5.2
50+
orientation: 0
51+
page_height: 29.7
52+
page_width: 21.0

requirements.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@
33
# process, which may cause wedges in the gate later.
44
python-docx>=0.8.6
55
PyYAML>=3.1.0 # MIT
6-
cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0
7-
jsonschema # MIT
6+
jsonschema # MIT

validocx/schema.py

+47-24
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,26 @@ def styles_schema(self):
2828
"paragraph": {
2929
"type": "object",
3030
"properties": {
31-
"first_line_indent": {"type": "number"},
32-
"keep_together": {"type": "number"},
33-
"keep_with_next": {"type": "number"},
34-
"left_indent": {"type": "number"},
35-
"line_spacing": {"type": "number"},
36-
"line_spacing_rule": {"type": "number"},
37-
"page_break_before": {"type": "number"},
38-
"right_indent": {"type": "number"},
39-
"space_after": {"type": "number"},
40-
"space_before": {"type": "number"}
41-
}
31+
"unit": {"type": "string"},
32+
"attributes": {
33+
"type": "object",
34+
"properties": {
35+
"alignment": {"type": "number"},
36+
"first_line_indent": {"type": "number"},
37+
"keep_together": {"type": "number"},
38+
"keep_with_next": {"type": "number"},
39+
"left_indent": {"type": "number"},
40+
"line_spacing": {"type": "number"},
41+
"line_spacing_rule": {"type": "number"},
42+
"page_break_before": {"type": "number"},
43+
"right_indent": {"type": "number"},
44+
"space_after": {"type": "number"},
45+
"space_before": {"type": "number"}
46+
},
47+
"additionalProperties": False
48+
}
49+
},
50+
"required": ["unit", "attributes"],
4251
}
4352
},
4453
"required": ["font", "paragraph"],
@@ -52,24 +61,38 @@ def sections_schema(self):
5261
"items": {
5362
"type": "object",
5463
"properties": {
55-
"right_margin": {"type": "number"},
56-
"start_type": {"type": "number"},
57-
"top_margin": {"type": "number"},
58-
"footer_distance": {"type": "number"},
59-
"header_distance": {"type": "number"},
60-
"left_margin": {"type": "number"},
61-
"bottom_margin": {"type": "number"},
62-
"orientation": {"type": "number"},
63-
"page_height": {"type": "number"},
64-
"page_width": {"type": "number"}
64+
"unit": {"type": "string"},
65+
"attributes": {
66+
"type": "object",
67+
"properties": {
68+
"right_margin": {"type": "number"},
69+
"start_type": {"type": "number"},
70+
"top_margin": {"type": "number"},
71+
"footer_distance": {"type": "number"},
72+
"header_distance": {"type": "number"},
73+
"left_margin": {"type": "number"},
74+
"bottom_margin": {"type": "number"},
75+
"orientation": {"type": "number"},
76+
"page_height": {"type": "number"},
77+
"page_width": {"type": "number"}
78+
},
79+
"additionalProperties": False
80+
}
6581
},
66-
"additionalProperties": False
82+
"required": ["unit", "attributes"],
6783
}
6884
}
6985

7086
@property
7187
def font_schema(self):
7288
return {
73-
"type": "array",
74-
"uniqueItems": True
89+
"type": "object",
90+
"properties": {
91+
"unit": {"type": "string"},
92+
"attributes": {
93+
"type": "array",
94+
"uniqueItems": True
95+
}
96+
},
97+
"required": ["unit", "attributes"],
7598
}

validocx/validator.py

+15-11
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@ def __init__(self, document):
3030
def validate_sections(self, section_requirements):
3131
"""Validate sections of a document."""
3232

33-
for item, section in enumerate(self._docx.iter_sections()):
34-
fetched_attr = self._docx.get_section_attributes(section)
35-
for attr, value in section_requirements[item].items():
33+
for i, section in enumerate(self._docx.iter_sections()):
34+
unit = section_requirements[i]['unit']
35+
fetched_attr = self._docx.get_section_attributes(section,
36+
unit=unit)
37+
for attr, value in section_requirements[i]['attributes'].items():
3638
if not math.isclose(fetched_attr[attr], value, rel_tol=1e-02):
3739
msg = ("Section '{0}': attribute '{1}' with value {2} "
3840
"does not match required value "
39-
"{3}".format(item, attr, fetched_attr[attr], value))
41+
"{3}".format(i, attr, fetched_attr[attr], value))
4042
logger.error(msg)
41-
raise ValueError(msg)
4243

4344
def validate_styles(self, style_requirements):
4445
"""Validate styles of a document, i.e. font and paragraph."""
@@ -59,21 +60,25 @@ def validate_styles(self, style_requirements):
5960
def validate_font(self, paragraph, font_requirements):
6061
"""Validate font in a specified paragraph."""
6162

62-
fetched_attr = self._docx.get_font_attributes(paragraph)
63+
unit = font_requirements['unit']
64+
requirements = font_requirements['attributes']
65+
fetched_attr = self._docx.get_font_attributes(paragraph, unit=unit)
6366
for i, attr in enumerate(fetched_attr):
64-
if set(attr) ^ set(font_requirements):
67+
if set(attr) ^ set(requirements):
6568
msg = ("Font attributes ({0}) mismatch required ({1}) in "
6669
"paragraph with style '{2}':\n'{3}'".format(
6770
', '.join(str(a) for a in attr),
68-
', '.join(str(r) for r in font_requirements),
71+
', '.join(str(r) for r in requirements),
6972
paragraph.style.name, paragraph.runs[i].text))
7073
logger.error(msg)
7174

7275
def validate_paragraph(self, paragraph, paragraph_requirements):
7376
"""Validate paragraph."""
7477

75-
fetched_attr = self._docx.get_paragraph_attributes(paragraph)
76-
for attr, value in paragraph_requirements.items():
78+
unit = paragraph_requirements['unit']
79+
fetched_attr = self._docx.get_paragraph_attributes(paragraph,
80+
unit=unit)
81+
for attr, value in paragraph_requirements['attributes'].items():
7782
if fetched_attr[attr] is not None:
7883
if not math.isclose(fetched_attr[attr], value, rel_tol=1e-02):
7984
msg = ("The attribute of paragraph '{0}' ({1}) with value "
@@ -92,7 +97,6 @@ def validate(self, document_requirements):
9297

9398
self._validate_schema(document_requirements,
9499
self.schema.requirements_schema)
95-
96100
logger.info("Start validating sections.")
97101
self.validate_sections(document_requirements['sections'])
98102
logger.info("Start validating styles.")

0 commit comments

Comments
 (0)