python-hwpx 2.2__py3-none-any.whl → 2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
hwpx/oxml/document.py CHANGED
@@ -1782,33 +1782,71 @@ class HwpxOxmlTable:
1782
1782
  def rows(self) -> list[HwpxOxmlTableRow]:
1783
1783
  return [HwpxOxmlTableRow(row, self) for row in self.element.findall(f"{_HP}tr")]
1784
1784
 
1785
- def _build_cell_grid(self) -> dict[tuple[int, int], HwpxTableGridPosition]:
1786
- mapping: dict[tuple[int, int], HwpxTableGridPosition] = {}
1787
- for row in self.element.findall(f"{_HP}tr"):
1788
- for cell_element in row.findall(f"{_HP}tc"):
1789
- wrapper = HwpxOxmlTableCell(cell_element, self, row)
1790
- start_row, start_col = wrapper.address
1791
- span_row, span_col = wrapper.span
1792
- for logical_row in range(start_row, start_row + span_row):
1793
- for logical_col in range(start_col, start_col + span_col):
1794
- key = (logical_row, logical_col)
1795
- existing = mapping.get(key)
1796
- entry = HwpxTableGridPosition(
1785
+ def _build_cell_grid(self) -> dict[tuple[int, int], HwpxTableGridPosition]:
1786
+ mapping: dict[tuple[int, int], HwpxTableGridPosition] = {}
1787
+
1788
+ def _is_deactivated_cell(
1789
+ cell: HwpxOxmlTableCell, span: tuple[int, int]
1790
+ ) -> bool:
1791
+ span_row, span_col = span
1792
+ if span_row != 1 or span_col != 1:
1793
+ return False
1794
+ if cell.width != 0 or cell.height != 0:
1795
+ return False
1796
+ for text_element in cell.element.findall(f".//{_HP}t"):
1797
+ if text_element.text:
1798
+ return False
1799
+ return True
1800
+
1801
+ for row in self.element.findall(f"{_HP}tr"):
1802
+ for cell_element in row.findall(f"{_HP}tc"):
1803
+ wrapper = HwpxOxmlTableCell(cell_element, self, row)
1804
+ start_row, start_col = wrapper.address
1805
+ span_row, span_col = wrapper.span
1806
+ wrapper_span = (span_row, span_col)
1807
+ wrapper_is_deactivated = _is_deactivated_cell(wrapper, wrapper_span)
1808
+ for logical_row in range(start_row, start_row + span_row):
1809
+ for logical_col in range(start_col, start_col + span_col):
1810
+ key = (logical_row, logical_col)
1811
+ existing = mapping.get(key)
1812
+ entry = HwpxTableGridPosition(
1797
1813
  row=logical_row,
1798
1814
  column=logical_col,
1799
1815
  cell=wrapper,
1800
1816
  anchor=(start_row, start_col),
1801
- span=(span_row, span_col),
1802
- )
1803
- if (
1804
- existing is not None
1805
- and existing.cell.element is not wrapper.element
1806
- ):
1807
- raise ValueError(
1808
- "table grid contains overlapping cell spans"
1809
- )
1810
- mapping[key] = entry
1811
- return mapping
1817
+ span=(span_row, span_col),
1818
+ )
1819
+ if (
1820
+ existing is not None
1821
+ and existing.cell.element is not wrapper.element
1822
+ ):
1823
+ existing_span = existing.span
1824
+ existing_spans_multiple = (
1825
+ existing_span[0] != 1 or existing_span[1] != 1
1826
+ )
1827
+ wrapper_spans_multiple = (
1828
+ wrapper_span[0] != 1 or wrapper_span[1] != 1
1829
+ )
1830
+ existing_is_deactivated = _is_deactivated_cell(
1831
+ existing.cell, existing_span
1832
+ )
1833
+
1834
+ if (
1835
+ wrapper_is_deactivated
1836
+ and existing_spans_multiple
1837
+ ):
1838
+ continue
1839
+ if (
1840
+ existing_is_deactivated
1841
+ and wrapper_spans_multiple
1842
+ ):
1843
+ mapping[key] = entry
1844
+ continue
1845
+ raise ValueError(
1846
+ "table grid contains overlapping cell spans"
1847
+ )
1848
+ mapping[key] = entry
1849
+ return mapping
1812
1850
 
1813
1851
  def _grid_entry(self, row_index: int, col_index: int) -> HwpxTableGridPosition:
1814
1852
  if row_index < 0 or col_index < 0:
@@ -2096,21 +2134,23 @@ class HwpxOxmlTable:
2096
2134
  if cell.element is not target.element:
2097
2135
  removal_elements.add(cell.element)
2098
2136
 
2099
- if not removal_elements and target.span == (new_row_span, new_col_span):
2100
- return target
2101
-
2102
- for element in removal_elements:
2103
- row_element = element_to_row.get(element)
2104
- if row_element is not None:
2105
- try:
2106
- row_element.remove(element)
2107
- except ValueError:
2108
- continue
2109
-
2110
- target.set_span(new_row_span, new_col_span)
2111
- target.set_size(total_width or target.width, total_height or target.height)
2112
- self.mark_dirty()
2113
- return target
2137
+ if not removal_elements and target.span == (new_row_span, new_col_span):
2138
+ return target
2139
+
2140
+ for element in removal_elements:
2141
+ row_element = element_to_row.get(element)
2142
+ if row_element is None:
2143
+ continue
2144
+ wrapper = HwpxOxmlTableCell(element, self, row_element)
2145
+ wrapper.set_span(1, 1)
2146
+ wrapper.set_size(0, 0)
2147
+ for text_element in element.findall(f".//{_HP}t"):
2148
+ text_element.text = ""
2149
+
2150
+ target.set_span(new_row_span, new_col_span)
2151
+ target.set_size(total_width or target.width, total_height or target.height)
2152
+ self.mark_dirty()
2153
+ return target
2114
2154
 
2115
2155
  @dataclass
2116
2156
  class HwpxOxmlParagraph:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hwpx
3
- Version: 2.2
3
+ Version: 2.3
4
4
  Summary: Hancom HWPX 패키지를 로드하고 편집하기 위한 Python 유틸리티 모음
5
5
  Author: python-hwpx Maintainers
6
6
  License: Non-Commercial License
@@ -9,7 +9,7 @@ hwpx/opc/xml_utils.py,sha256=-hKV6cZE6bvE1K-AnteRuaReTqoXfd4IlZHqj7j38o0,1628
9
9
  hwpx/oxml/__init__.py,sha256=_vifVi072wFdPty5RTyCoACbdweXxmaA9ed2ztysPOU,5145
10
10
  hwpx/oxml/body.py,sha256=iWyi0hoQ3PqAp9THSqnfiwxqP291RDP6FKYJPD4j-do,13719
11
11
  hwpx/oxml/common.py,sha256=2ZGe_0tAaFMWdDHDrXOpErWpZeS1Kh1x91LEEXwVf-0,1042
12
- hwpx/oxml/document.py,sha256=k7Vyy1l1iC5ZxdajQLt-ze-o28lAtQ_hntI1FuEpRZk,126684
12
+ hwpx/oxml/document.py,sha256=BaIB88MOrSZUy5l6t-EbVmHEz1yFgJFxTd3BqroDQkw,128429
13
13
  hwpx/oxml/header.py,sha256=a53ElDngElCGQZwx4zL_BGGDyaJA0dZRYVDsj1KH5t8,44411
14
14
  hwpx/oxml/header_part.py,sha256=81qNuSamLLP_mJIoGJUrUzCjM2C5b3E9Uag1y8M6g30,203
15
15
  hwpx/oxml/memo.py,sha256=awhHOojaeYDB9iUwFMVFvTqUTFEvX1HAl9f1Zaw-2dY,200
@@ -25,9 +25,9 @@ hwpx/tools/text_extractor.py,sha256=anwGasEWgUObP_8f3FvLJRXAaVbeN1NU3t9PECnxslY,
25
25
  hwpx/tools/validator.py,sha256=tMOghlWd0tstjDEcknfeq6vbyZrEjEJ9_KkqqmsCW20,6163
26
26
  hwpx/tools/_schemas/header.xsd,sha256=6lwERCwYG7ux41GwCc_c-JHQ1RLPkv9esJQUbkj4Z-Y,678
27
27
  hwpx/tools/_schemas/section.xsd,sha256=Yh4OIfVUfudd8DTg6wUpxcIiqMs-0wlD9KMUAaQEjuU,534
28
- python_hwpx-2.2.dist-info/licenses/LICENSE,sha256=e7IU-h7BsVemhh49-5Xn8O368ON7_tyjF8wX6URTiGU,1641
29
- python_hwpx-2.2.dist-info/METADATA,sha256=RtBAuS46ITt5wKSBByeuy45FOUcZddz1YCKZ8JQuRTc,9399
30
- python_hwpx-2.2.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
31
- python_hwpx-2.2.dist-info/entry_points.txt,sha256=wBO_QZkkQ0FIyAxBhJ08EAtv2SmBnN1xabRHE5G2CyM,60
32
- python_hwpx-2.2.dist-info/top_level.txt,sha256=R1iToqDh80Nf2oQhRjTN0rbN2X6kyDUizIocZjkhuxc,5
33
- python_hwpx-2.2.dist-info/RECORD,,
28
+ python_hwpx-2.3.dist-info/licenses/LICENSE,sha256=e7IU-h7BsVemhh49-5Xn8O368ON7_tyjF8wX6URTiGU,1641
29
+ python_hwpx-2.3.dist-info/METADATA,sha256=DXlVL9xG7iPhUSgLCJlkj52OSLMliLxjS9lz_Qrm3z8,9399
30
+ python_hwpx-2.3.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
31
+ python_hwpx-2.3.dist-info/entry_points.txt,sha256=wBO_QZkkQ0FIyAxBhJ08EAtv2SmBnN1xabRHE5G2CyM,60
32
+ python_hwpx-2.3.dist-info/top_level.txt,sha256=R1iToqDh80Nf2oQhRjTN0rbN2X6kyDUizIocZjkhuxc,5
33
+ python_hwpx-2.3.dist-info/RECORD,,