1
- """
2
- Convert an XML/HTML document Bootstrap code from an older version to a newer one.
3
- """
1
+ """Convert an XML/HTML document Bootstrap code from an older version to a newer one."""
4
2
5
3
import logging
6
4
import os .path
29
27
30
28
31
29
def _xpath_has_class (context , * cls ):
32
- """Extension function for xpath to check if the context node has all the classes passed as arguments"""
30
+ """Extension function for xpath to check if the context node has all the classes passed as arguments. """
33
31
node_classes = set (context .context_node .attrib .get ("class" , "" ).split ())
34
32
return node_classes .issuperset (cls )
35
33
@@ -49,10 +47,7 @@ def _xpath_has_t_class_inner(attrs_values, classes):
49
47
50
48
51
49
def _xpath_has_t_class (context , * cls ):
52
- """
53
- Extension function for xpath to check if the context node has all the classes passed as arguments
54
- in one of ``class`` or ``t-att(f)-class`` attributes.
55
- """
50
+ """Extension function for xpath to check if the context node has all the classes passed as arguments in one of ``class`` or ``t-att(f)-class`` attributes."""
56
51
return _xpath_has_class (context , * cls ) or _xpath_has_t_class_inner (
57
52
tuple (map (context .context_node .attrib .get , ("t-att-class" , "t-attf-class" ))), cls
58
53
)
@@ -65,7 +60,7 @@ def _xpath_regex_inner(pattern, item):
65
60
66
61
67
62
def _xpath_regex (context , item , pattern ):
68
- """Extension function for xpath to check if the passed item (attribute or text) matches the passed regex pattern"""
63
+ """Extension function for xpath to check if the passed item (attribute or text) matches the passed regex pattern. """
69
64
if not item :
70
65
return False
71
66
if isinstance (item , list ):
@@ -84,7 +79,7 @@ def _xpath_regex(context, item, pattern):
84
79
85
80
def innerxml (element , is_html = False ):
86
81
"""
87
- Returns the inner XML of an element as a string.
82
+ Return the inner XML of an element as a string.
88
83
89
84
:param etree.ElementBase element: the element to convert.
90
85
:param bool is_html: whether to use HTML for serialization, XML otherwise. Defaults to False.
@@ -96,23 +91,24 @@ def innerxml(element, is_html=False):
96
91
97
92
98
93
def split_classes (* joined_classes ):
99
- """Returns a list of classes given one or more strings of joined classes separated by spaces"""
94
+ """Return a list of classes given one or more strings of joined classes separated by spaces. """
100
95
return [c for classes in joined_classes for c in (classes or "" ).split (" " ) if c ]
101
96
102
97
103
98
def get_classes (element ):
104
- """Returns the list of classes from the ``class`` attribute of an element"""
99
+ """Return the list of classes from the ``class`` attribute of an element. """
105
100
return split_classes (element .get ("class" , "" ))
106
101
107
102
108
103
def join_classes (classes ):
109
- """Returns a string of classes joined by space given a list of classes"""
104
+ """Return a string of classes joined by space given a list of classes. """
110
105
return " " .join (classes )
111
106
112
107
113
108
def set_classes (element , classes ):
114
109
"""
115
- Sets the ``class`` attribute of an element from a list of classes.
110
+ Set the ``class`` attribute of an element from a list of classes.
111
+
116
112
If the list is empty, the attribute is removed.
117
113
"""
118
114
if classes :
@@ -123,7 +119,7 @@ def set_classes(element, classes):
123
119
124
120
def edit_classlist (classes , add , remove ):
125
121
"""
126
- Helper function to edit a class list, adding and removing classes.
122
+ Edit a class list, adding and removing classes.
127
123
128
124
:param str | typing.List[str] classes: the original classes list or str to edit.
129
125
:param str | typing.Iterable[str] | None add: if specified, adds the given class(es) to the list.
@@ -161,8 +157,7 @@ def edit_classlist(classes, add, remove):
161
157
162
158
def edit_element_t_classes (element , add , remove ):
163
159
"""
164
- Helper function to edit inplace qweb ``t-att-class`` and ``t-attf-class`` attributes of an element,
165
- adding and removing the specified classes.
160
+ Edit inplace qweb ``t-att-class`` and ``t-attf-class`` attributes of an element, adding and removing the specified classes.
166
161
167
162
N.B. adding new classes will not work if neither ``t-att-class`` nor ``t-attf-class`` are present.
168
163
@@ -222,7 +217,7 @@ def edit_element_t_classes(element, add, remove):
222
217
223
218
def edit_element_classes (element , add , remove , is_qweb = False ):
224
219
"""
225
- Helper function to edit inplace the "class" attribute of an element, adding and removing classes.
220
+ Edit inplace the "class" attribute of an element, adding and removing classes.
226
221
227
222
:param etree.ElementBase element: the element to edit.
228
223
:param str | typing.Iterable[str] | None add: if specified, adds the given class(es) to the element.
@@ -243,7 +238,8 @@ def edit_element_classes(element, add, remove, is_qweb=False):
243
238
244
239
def simple_css_selector_to_xpath (selector , prefix = "//" ):
245
240
"""
246
- Converts a basic CSS selector cases to an XPath expression.
241
+ Convert a basic CSS selector cases to an XPath expression.
242
+
247
243
Supports node names, classes, ``>`` and ``,`` combinators.
248
244
249
245
:param str selector: the CSS selector to convert.
@@ -313,13 +309,11 @@ def adapt_xpath_for_qweb(xpath):
313
309
314
310
315
311
class ElementOperation :
316
- """
317
- Abstract base class for defining operations to be applied on etree elements.
318
- """
312
+ """Abstract base class for defining operations to be applied on etree elements."""
319
313
320
314
def __call__ (self , element , converter ):
321
315
"""
322
- Performs the operation on the given element.
316
+ Perform the operation on the given element.
323
317
324
318
Abstract method that must be implemented by subclasses.
325
319
@@ -343,8 +337,7 @@ def xpath(self, xpath=None):
343
337
@classmethod
344
338
def op (cls , * args , xpath = None , ** kwargs ):
345
339
"""
346
- Creates a definition of an operation with the given arguments, and returns
347
- a tuple of (xpath, operations list) that can be used in the converter definition list.
340
+ Create a definition of an operation with the given arguments, and returns a tuple of (xpath, operations list) that can be used in the converter definition list.
348
341
349
342
:param typing.Any args: positional arguments to pass to the operation :meth:`~.__init__`.
350
343
:param typing.Any kwargs: keyword arguments to pass to the operation :meth:`~.__init__`.
@@ -356,9 +349,7 @@ def op(cls, *args, xpath=None, **kwargs):
356
349
357
350
358
351
class RemoveElement (ElementOperation ):
359
- """
360
- Removes the matched element(s) from the document.
361
- """
352
+ """Remove the matched element(s) from the document."""
362
353
363
354
def __call__ (self , element , converter ):
364
355
parent = element .getparent ()
@@ -369,7 +360,7 @@ def __call__(self, element, converter):
369
360
370
361
class EditClasses (ElementOperation ):
371
362
"""
372
- Adds and/or removes classes.
363
+ Add and/or remove classes.
373
364
374
365
:param str | typing.Iterable[str] | None add: classes to add to the elements.
375
366
:param str | typing.Iterable[str] | ALL | None remove: classes to remove from the elements.
@@ -411,10 +402,6 @@ def xpath(self, xpath=None):
411
402
412
403
413
404
class AddClasses (EditClasses ):
414
- """
415
- Adds classes.
416
- """
417
-
418
405
def __init__ (self , * classes ):
419
406
super ().__init__ (add = classes )
420
407
@@ -423,7 +410,7 @@ def __init__(self, *classes):
423
410
424
411
class RemoveClasses (EditClasses ):
425
412
"""
426
- Removes classes.
413
+ Remove classes.
427
414
428
415
N.B. no checks are made to ensure the class(es) to remove are actually present on the elements.
429
416
"""
@@ -434,7 +421,7 @@ def __init__(self, *classes):
434
421
435
422
class ReplaceClasses (EditClasses ):
436
423
"""
437
- Replaces old classes with new ones.
424
+ Replace old classes with new ones.
438
425
439
426
:param str | typing.Iterable[str] | ALL old: classes to remove from the elements.
440
427
:param str | typing.Iterable[str] | None new: classes to add to the elements.
@@ -448,10 +435,10 @@ def __init__(self, old, new):
448
435
449
436
class PullUp (ElementOperation ):
450
437
"""
451
- Pulls up the element's children to the parent element, then removes the original element.
438
+ Pull up the element's children to the parent element, then removes the original element.
452
439
453
440
Example:
454
-
441
+ -------
455
442
before::
456
443
.. code-block:: html
457
444
@@ -484,9 +471,7 @@ def __call__(self, element, converter):
484
471
485
472
486
473
class RenameAttribute (ElementOperation ):
487
- """
488
- Renames an attribute. Silently ignores elements that do not have the attribute.
489
- """
474
+ """Rename an attribute. Silently ignores elements that do not have the attribute."""
490
475
491
476
def __init__ (self , old_name , new_name , extra_xpath = "" ):
492
477
self .old_name = old_name
@@ -567,9 +552,7 @@ def __init__(self, pattern, sub, attr="class"):
567
552
568
553
569
554
class BS3to4ConvertBlockquote (ElementOperation ):
570
- """
571
- Converts a BS3 ``<blockquote>`` element to a BS4 ``<div>`` element with the ``blockquote`` class.
572
- """
555
+ """Convert a BS3 ``<blockquote>`` element to a BS4 ``<div>`` element with the ``blockquote`` class."""
573
556
574
557
def __call__ (self , element , converter ):
575
558
blockquote = converter .copy_element (element , tag = "div" , add_classes = "blockquote" , copy_attrs = False )
@@ -581,7 +564,8 @@ def __call__(self, element, converter):
581
564
# TODO abt: merge MakeCard and ConvertCard into one operation class
582
565
class BS3to4MakeCard (ElementOperation ):
583
566
"""
584
- Pre-processes a BS3 panel, thumbnail, or well element to be converted to a BS4 card.
567
+ Pre-processe a BS3 panel, thumbnail, or well element to be converted to a BS4 card.
568
+
585
569
Card components conversion is then handled by the ``ConvertCard`` operation class.
586
570
"""
587
571
@@ -598,9 +582,7 @@ def __call__(self, element, converter):
598
582
599
583
# TODO abt: refactor code
600
584
class BS3to4ConvertCard (ElementOperation ):
601
- """
602
- Fully converts a BS3 panel, thumbnail, or well element and their contents to a BS4 card.
603
- """
585
+ """Fully convert a BS3 panel, thumbnail, or well element and their contents to a BS4 card."""
604
586
605
587
POST_CONVERSIONS = {
606
588
"title" : ["card-title" ],
@@ -682,7 +664,8 @@ def __call__(self, element, converter):
682
664
683
665
class BS4to5ConvertCloseButton (ElementOperation ):
684
666
"""
685
- Converts BS4 ``button.close`` elements to BS5 ``button.btn-close``.
667
+ Convert BS4 ``button.close`` elements to BS5 ``button.btn-close``.
668
+
686
669
Also fixes the ``data-dismiss`` attribute to ``data-bs-dismiss``, and removes any inner contents.
687
670
"""
688
671
@@ -700,9 +683,7 @@ def __call__(self, element, converter):
700
683
701
684
702
685
class BS4to5ConvertCardDeck (ElementOperation ):
703
- """
704
- Converts BS4 ``.card-deck`` elements to grid components (``.row``, ``.col``, etc.).
705
- """
686
+ """Convert BS4 ``.card-deck`` elements to grid components (``.row``, ``.col``, etc.)."""
706
687
707
688
def __call__ (self , element , converter ):
708
689
cards = element .xpath (converter .adapt_xpath ("./*[hasclass('card')]" ))
@@ -719,9 +700,7 @@ def __call__(self, element, converter):
719
700
720
701
721
702
class BS4to5ConvertFormInline (ElementOperation ):
722
- """
723
- Converts BS4 ``.form-inline`` elements to grid components (``.row``, ``.col``, etc.).
724
- """
703
+ """Convert BS4 ``.form-inline`` elements to grid components (``.row``, ``.col``, etc.)."""
725
704
726
705
def __call__ (self , element , converter ):
727
706
edit_element_classes (element , add = "row row-cols-lg-auto" , remove = "form-inline" , is_qweb = converter .is_qweb )
@@ -990,8 +969,7 @@ def get_conversions(cls, src_ver, dst_ver, is_qweb=False):
990
969
991
970
def convert (self , src_version , dst_version ):
992
971
"""
993
- Converts the loaded document inplace from the source version to the destination,
994
- returning the converted document and the number of conversion operations applied.
972
+ Convert the loaded document inplace from the source version to the destination, returning the converted document and the number of conversion operations applied.
995
973
996
974
:param str src_version: the source Bootstrap version.
997
975
:param str dst_version: the destination Bootstrap version.
@@ -1064,7 +1042,8 @@ def convert_file(cls, path, src_version, dst_version, is_html=None, **converter_
1064
1042
1065
1043
def element_factory (self , * args , ** kwargs ):
1066
1044
"""
1067
- Helper method to be used by operation for creating new elements using the correct document type.
1045
+ Create new elements using the correct document type.
1046
+
1068
1047
Basically a wrapper for either etree.XML or etree.HTML depending on the type of document loaded.
1069
1048
1070
1049
:param args: positional arguments to pass to the etree.XML or etree.HTML function.
@@ -1075,7 +1054,8 @@ def element_factory(self, *args, **kwargs):
1075
1054
1076
1055
def build_element (self , tag , classes = None , contents = None , ** attributes ):
1077
1056
"""
1078
- Helper method to create a new element with the given tag, classes, contents and attributes.
1057
+ Create a new element with the given tag, classes, contents and attributes.
1058
+
1079
1059
Like :meth:`~.element_factory`, can be used by operations to create elements abstracting away the document type.
1080
1060
1081
1061
:param str tag: the tag of the element to create.
@@ -1103,7 +1083,8 @@ def copy_element(
1103
1083
** attributes ,
1104
1084
):
1105
1085
"""
1106
- Helper method that creates a copy of an element, optionally changing the tag, classes, contents and attributes.
1086
+ Create a copy of an element, optionally changing the tag, classes, contents and attributes.
1087
+
1107
1088
Like :meth:`~.element_factory`, can be used by operations to copy elements abstracting away the document type.
1108
1089
1109
1090
:param etree.ElementBase element: the element to copy.
@@ -1133,7 +1114,7 @@ def adapt_xpath(self, xpath):
1133
1114
1134
1115
def convert_tree (tree , src_version , dst_version , ** converter_kwargs ):
1135
1116
"""
1136
- Converts an already parsed lxml tree from Bootstrap v3 to v4 inplace.
1117
+ Convert an already parsed lxml tree from Bootstrap v3 to v4 inplace.
1137
1118
1138
1119
:param etree.ElementTree tree: the lxml tree to convert.
1139
1120
:param str src_version: the version of Bootstrap the document is currently using.
0 commit comments