Repository: tatuylonen/wiktextract

Issue:
Problems with some German pronoun forms
So far, we have detected only one case: the pronoun “sein” in its various forms is incorrectly formed. However, in Wiktionary it does appear correctly conjugated as a pronoun. I have attached some evidence for this below.

![Image](https://github.com/user-attachments/assets/db8920dc-769d-4653-ac08-0aad373d09c2)

![Image](https://github.com/user-attachments/assets/c7691f80-69b3-48fa-8710-f7da9aac9857)

Discussion:

Solution patch:
diff --git a/src/wiktextract/extractor/de/inflection.py b/src/wiktextract/extractor/de/inflection.py
index 0074dd82..651bba7c 100644
--- a/src/wiktextract/extractor/de/inflection.py
+++ b/src/wiktextract/extractor/de/inflection.py
@@ -42,6 +42,8 @@ def extract_inf_table_template(
         or t_node.template_name == "Kardinalzahl 2-12"
     ):
         process_verb_table(wxr, word_entry, t_node)
+    elif t_node.template_name == "Deutsch Possessivpronomen":
+        extract_pronoun_table(wxr, word_entry, t_node)
 
 
 @dataclass
@@ -240,3 +242,72 @@ def process_adj_table(
                         form.raw_tags.append(column_headers[col_index])
                     translate_raw_tags(form)
                     word_entry.forms.append(form)
+
+
+def extract_pronoun_table(
+    wxr: WiktextractContext, word_entry: WordEntry, t_node: TemplateNode
+) -> None:
+    # Vorlage:Deutsch Possessivpronomen
+    expanded_template = wxr.wtp.parse(
+        wxr.wtp.node_to_wikitext(t_node), expand_all=True
+    )
+    table_nodes = list(expanded_template.find_child(NodeKind.TABLE))
+    if len(table_nodes) == 0:
+        return
+    table_node = table_nodes[0]
+    col_headers = []
+    table_header = ""
+    for row in table_node.find_child(NodeKind.TABLE_ROW):
+        row_header = ""
+        row_has_data = row.contain_node(NodeKind.TABLE_CELL)
+        col_index = 0
+        article = ""
+        for cell in row.find_child(
+            NodeKind.TABLE_HEADER_CELL | NodeKind.TABLE_CELL
+        ):
+            cell_text = clean_node(wxr, None, cell)
+            if cell.kind == NodeKind.TABLE_HEADER_CELL:
+                if cell_text == "":
+                    continue
+                elif row_has_data:
+                    row_header = cell_text
+                elif len(list(row.find_child(NodeKind.TABLE_HEADER_CELL))) == 1:
+                    table_header = cell_text
+                    col_headers.clear()  # new table
+                    article = ""
+                else:
+                    colspan = 1
+                    colspan_str = cell.attrs.get("colspan", "1")
+                    if re.fullmatch(r"\d+", colspan_str):
+                        colspan = int(colspan_str)
+                    if cell_text != "—":
+                        col_headers.append(
+                            RowspanHeader(cell_text, col_index, colspan)
+                        )
+                    col_index += colspan
+            elif cell.kind == NodeKind.TABLE_CELL:
+                if col_index % 2 == 0:
+                    article = cell_text
+                else:
+                    form_str = (
+                        article + " " + cell_text
+                        if article not in ["", "—"]
+                        else cell_text
+                    )
+                    form = Form(form=form_str)
+                    if table_header != "":
+                        form.raw_tags.append(table_header)
+                    if row_header != "":
+                        form.raw_tags.append(row_header)
+                    for header in col_headers:
+                        if (
+                            col_index >= header.index
+                            and col_index < header.index + header.span
+                            and header.text != "Wortform"
+                        ):
+                            form.raw_tags.append(header.text)
+                    translate_raw_tags(form)
+                    if form.form != wxr.wtp.title:
+                        word_entry.forms.append(form)
+                    article = ""
+                col_index += 1


Test patch:
diff --git a/tests/test_de_forms.py b/tests/test_de_forms.py
index 5c03b53b..84005153 100644
--- a/tests/test_de_forms.py
+++ b/tests/test_de_forms.py
@@ -429,3 +429,114 @@ class TestDeForms(TestCase):
                 },
             ],
         )
+
+    def test_pron_table(self):
+        self.wxr.wtp.add_page(
+            "Vorlage:Deutsch Possessivpronomen",
+            10,
+            """{| class="wikitable float-right"
+! style="background-color:#c6e2ff;" colspan="9" | attributiv (vor Substantiv)
+|-
+! rowspan="3" |
+! colspan="6" | [[Hilfe:Singular|Singular]]
+! colspan="2" | [[Hilfe:Plural|Plural]]
+|-
+! colspan="2" | [[Hilfe:Maskulinum|Maskulinum]]
+! colspan="2" | [[Hilfe:Femininum|Femininum]]
+! colspan="2" | [[Hilfe:Neutrum|Neutrum]]
+! colspan="2" | —
+|-
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+|-
+! style="text-align:left" | [[Hilfe:Nominativ|Nominativ]]
+| style="text-align:center" | —
+| mein
+| style="text-align:center" | —
+| [[meine|meine]]
+| style="text-align:center" | —
+| mein
+| style="text-align:center" | —
+| [[meine|meine]]
+|-
+! style="background-color:#c6e2ff;" colspan="9" | nicht attributiv, mit Artikel
+|-
+! rowspan="3" |
+! colspan="6" | [[Hilfe:Singular|Singular]]
+! colspan="2" | [[Hilfe:Plural|Plural]]
+|-
+! colspan="2" | [[Hilfe:Maskulinum|Maskulinum]]
+! colspan="2" | [[Hilfe:Femininum|Femininum]]
+! colspan="2" | [[Hilfe:Neutrum|Neutrum]]
+! colspan="2" | —
+|-
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+! style="background:#F9F9F9" | [[Hilfe:Artikel|Artikel]]
+! style="background:#F9F9F9" | [[Hilfe:Wortform|Wortform]]
+|-
+! style="text-align:left" | [[Hilfe:Nominativ|Nominativ]]
+| der
+| [[meine|meine]]
+| die
+| [[meine|meine]]
+| das
+| [[meine|meine]]
+| die
+| [[meinen|meinen]]
+|}""",
+        )
+        page_data = parse_page(
+            self.wxr,
+            "mein",
+            """== mein ({{Sprache|Deutsch}}) ==
+=== {{Wortart|Possessivpronomen|Deutsch}}, ''1. Person Singular'' ===
+{{Deutsch Possessivpronomen|mein}}
+====Bedeutungen====
+:[1] zeigt den Besitz""",
+        )
+        self.assertEqual(
+            page_data[0]["forms"],
+            [
+                {
+                    "form": "meine",
+                    "tags": ["nominative", "singular", "feminine"],
+                    "raw_tags": ["attributiv (vor Substantiv)"],
+                },
+                {
+                    "form": "meine",
+                    "tags": ["nominative", "plural"],
+                    "raw_tags": ["attributiv (vor Substantiv)"],
+                },
+                {
+                    "form": "der meine",
+                    "tags": ["nominative", "singular", "masculine"],
+                    "raw_tags": ["nicht attributiv, mit Artikel"],
+                },
+                {
+                    "form": "die meine",
+                    "tags": ["nominative", "singular", "feminine"],
+                    "raw_tags": ["nicht attributiv, mit Artikel"],
+                },
+                {
+                    "form": "das meine",
+                    "tags": ["nominative", "singular", "neuter"],
+                    "raw_tags": ["nicht attributiv, mit Artikel"],
+                },
+                {
+                    "form": "die meinen",
+                    "tags": ["nominative", "plural"],
+                    "raw_tags": ["nicht attributiv, mit Artikel"],
+                },
+            ],
+        )