diff --git a/src/oca_pre_commit_hooks/checks_odoo_module_xml.py b/src/oca_pre_commit_hooks/checks_odoo_module_xml.py
index dfe0cfa..426c501 100644
--- a/src/oca_pre_commit_hooks/checks_odoo_module_xml.py
+++ b/src/oca_pre_commit_hooks/checks_odoo_module_xml.py
@@ -686,7 +686,7 @@ def check_xml_double_quotes_py(self):
message='Escaped double quotes " for python code detected',
info=f"Use single quote instead: `{new_py_code}`",
filepath=manifest_data["filename_short"],
- line=elem.sourceline,
+ line=node_content.start_sourceline or elem.sourceline,
)
during2 = node_content.content_node.replace(b""", b"'")
if self.autofix and during2 != node_content.content_node:
@@ -705,12 +705,20 @@ def check_xml_double_quotes_py(self):
node_content = node_xml.NodeContent(manifest_data["filename"], elem)
if b""" not in node_content.content_node:
continue
+
+ locator = self._get_tag_locator(manifest_data)
+ attr_span = locator.get_attr(elem, attr_name)
+ if attr_span:
+ line_no = locator.content[: attr_span.name_start].count(b"\n") + 1
+ else:
+ line_no = node_content.start_sourceline or elem.sourceline
+
self.register_error(
code="xml-double-quotes-py",
message='Escaped double quotes " for python code detected use',
info=f"Use single quote instead: `{new_py_code}`",
filepath=manifest_data["filename_short"],
- line=elem.sourceline,
+ line=line_no,
)
during2 = node_content.content_node.replace(b""", b"'")
if self.autofix and during2 != node_content.content_node:
diff --git a/src/oca_pre_commit_hooks/node_xml.py b/src/oca_pre_commit_hooks/node_xml.py
index 004cd69..07c57ef 100644
--- a/src/oca_pre_commit_hooks/node_xml.py
+++ b/src/oca_pre_commit_hooks/node_xml.py
@@ -1,4 +1,5 @@
# Based on https://github.com/mitsuhiko/sloppy-xml-py
+import re
from dataclasses import dataclass
@@ -243,11 +244,11 @@ def _read_node(self): # noqa:C901 pylint:disable=too-complex
# TODO: Get the sourceline of a particular attribute
# Determine the search start line
if (node_previous := self.node.getprevious()) is not None:
- search_start_line = node_previous.sourceline + 1
+ search_start_line = node_previous.sourceline
elif (node_parent := self.node.getparent()) is not None:
- search_start_line = node_parent.sourceline + 1
+ search_start_line = node_parent.sourceline
else:
- search_start_line = 2 # first element and it is the root
+ search_start_line = 1 # first element and it is the root
search_end_line = self.node.sourceline
node_tag = self.node.tag.encode() if isinstance(self.node.tag, str) else self.node.tag
@@ -257,14 +258,19 @@ def _read_node(self): # noqa:C901 pylint:disable=too-complex
all_lines = list((i, line) for i, line in enumerate(f_content, start=1))
# Find the actual node start by looking for the tag
+
+ node_start_re = re.compile(b"<" + node_tag + b"(?:[ />\n\r\t]|$)")
node_start_idx = None
- for idx, (no_line, line) in enumerate(all_lines):
- if search_start_line <= no_line <= search_end_line:
- stripped_line = line.lstrip()
- if stripped_line.startswith(b"<" + node_tag):
- node_start_idx = idx
- self.start_sourceline = no_line
- break
+
+ end_idx = min(search_end_line - 1, len(all_lines) - 1)
+ start_idx = max(search_start_line - 1, 0)
+
+ for idx in range(end_idx, start_idx - 1, -1):
+ no_line, line = all_lines[idx]
+ if node_start_re.search(line):
+ node_start_idx = idx
+ self.start_sourceline = no_line
+ break
if node_start_idx is None:
# Fallback: use search_end_line
diff --git a/test_repo/test_module/model_view.xml b/test_repo/test_module/model_view.xml
index 1fef119..b5179df 100644
--- a/test_repo/test_module/model_view.xml
+++ b/test_repo/test_module/model_view.xml
@@ -22,5 +22,23 @@
+
+
+
+
+
+ - Name: , date
+ - Percentage
+ %
+
+
+
+
+
diff --git a/tests/test_checks.py b/tests/test_checks.py
index 9b863ca..b4c5535 100644
--- a/tests/test_checks.py
+++ b/tests/test_checks.py
@@ -38,7 +38,7 @@
"xml-deprecated-qweb-directive-15": 4,
"xml-deprecated-qweb-directive": 2,
"xml-deprecated-tree-attribute": 3,
- "xml-double-quotes-py": 3,
+ "xml-double-quotes-py": 5,
"xml-duplicate-fields": 3,
"xml-duplicate-record-id": 2,
"xml-not-valid-char-link": 2,