python-hwpx-automation 7.3.3__py3-none-any.whl → 7.3.4__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.
@@ -93,11 +93,16 @@ def _replace_in_runs(runs: list[Any], find_text: str, replace_text: str) -> int:
93
93
  if not runs:
94
94
  return 0
95
95
 
96
- replaced = _replace_within_runs(runs, find_text, replace_text)
97
- merged_after_simple = "".join(run.text or "" for run in runs)
98
- if find_text in merged_after_simple:
99
- replaced += _replace_across_runs(runs, find_text, replace_text)
100
- return replaced
96
+ # Decide from the text before any replacement: re-scanning afterwards would find
97
+ # find_text again inside replace_text when the one contains the other.
98
+ if not _has_match_across_runs([run.text or "" for run in runs], find_text):
99
+ return _replace_within_runs(runs, find_text, replace_text)
100
+ return _replace_across_runs(runs, find_text, replace_text)
101
+
102
+
103
+ def _has_match_across_runs(texts: list[str], find_text: str) -> bool:
104
+ """Whether some occurrence of *find_text* in the joined text spans two runs."""
105
+ return "".join(texts).count(find_text) != sum(text.count(find_text) for text in texts)
101
106
 
102
107
 
103
108
  def _replace_within_xml_runs(run_elements: list[Any], find_text: str, replace_text: str) -> int:
@@ -134,11 +139,9 @@ def _replace_in_xml_runs(run_elements: list[Any], find_text: str, replace_text:
134
139
  if not run_elements:
135
140
  return 0
136
141
 
137
- replaced = _replace_within_xml_runs(run_elements, find_text, replace_text)
138
- merged_after_simple = "".join(_xml_run_text(run_element) for run_element in run_elements)
139
- if find_text in merged_after_simple:
140
- replaced += _replace_across_xml_runs(run_elements, find_text, replace_text)
141
- return replaced
142
+ if not _has_match_across_runs([_xml_run_text(run_element) for run_element in run_elements], find_text):
143
+ return _replace_within_xml_runs(run_elements, find_text, replace_text)
144
+ return _replace_across_xml_runs(run_elements, find_text, replace_text)
142
145
 
143
146
 
144
147
  def find_in_doc(doc: Any, text_to_find: str, match_case: bool = True, max_results: int = 50) -> dict:
@@ -7,9 +7,9 @@
7
7
  "candidate": {
8
8
  "pythonHwpx": "6.6.0",
9
9
  "canonicalDistribution": "python-hwpx-automation",
10
- "canonicalAutomation": "7.3.3",
10
+ "canonicalAutomation": "7.3.4",
11
11
  "compatibilityDistribution": "hwpx-mcp-server",
12
- "compatibility": "7.3.3",
12
+ "compatibility": "7.3.4",
13
13
  "plugin": "2.4.0",
14
14
  "contractHash": "5e5c23651f92785a"
15
15
  },
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hwpx-automation
3
- Version: 7.3.3
3
+ Version: 7.3.4
4
4
  Summary: Task-oriented HWPX document automation for Python, with an optional MCP adapter.
5
5
  Author: Kohkyuhyun
6
6
  License-Expression: Apache-2.0
@@ -74,7 +74,7 @@ Dynamic: license-file
74
74
 
75
75
  <!-- release-state: release-approved -->
76
76
  > [!NOTE]
77
- > 발행이 승인된 7.3.3 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.6.0 → python-hwpx-automation 7.3.3 → hwpx-plugin 2.4.0` (`5e5c23651f92785a`).
77
+ > 발행이 승인된 7.3.4 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.6.0 → python-hwpx-automation 7.3.4 → hwpx-plugin 2.4.0` (`5e5c23651f92785a`).
78
78
  > 공개 트레인: `python-hwpx 6.6.0 → python-hwpx-automation 7.3.1 → hwpx-plugin 2.4.0`.
79
79
  > 공개 좌표는 core·automation PyPI와 plugin GitHub
80
80
  > Release·marketplace·실제 marketplace 설치 관찰 후에만 승격합니다.
@@ -162,7 +162,7 @@ PDF와 쪽 PNG로 렌더합니다. 별도 환경에서 실행하므로 호출하
162
162
  고정 버전을 건드리지 않습니다.
163
163
 
164
164
  ```bash
165
- uvx --from "python-hwpx-automation[oracle]==7.3.3" \
165
+ uvx --from "python-hwpx-automation[oracle]==7.3.4" \
166
166
  hwpx render-pdf in.hwpx out.pdf --png out/page --json
167
167
  ```
168
168
 
@@ -16,7 +16,7 @@ hwpx_automation/form_output_models.py,sha256=qRNtqNjsmTynMWRU6p7SWIfcqglWyAxffmO
16
16
  hwpx_automation/hwp_converter.py,sha256=6i1dVntfbAl1esGicvIhquJKDldg0PxGaIdfiE2VzK8,7611
17
17
  hwpx_automation/hwp_support.py,sha256=EbM5PQiK9QDJDwFhA1dCxh3I7-5wst5pJXgcr4VK3tY,3371
18
18
  hwpx_automation/hwpx_ops.py,sha256=39oO_S_dTQHny1qJhJzUjoQTblAKLTQBnIzITlBwyLY,50991
19
- hwpx_automation/identity.json,sha256=VcotkeMb4PwBX8t8zD5yRSYeRARrcb3quUBILYFi6kQ,9820
19
+ hwpx_automation/identity.json,sha256=1ftzXE-vp1sbPbEvmWZlcIu4QOzH4huWVXzIV5UtUA8,9820
20
20
  hwpx_automation/identity.py,sha256=g62OiZ_Bvo3wL8NCHFPmAEfwDSJY4AG_cc6aBipU9zI,473
21
21
  hwpx_automation/ingest_adapters.py,sha256=7Lm1Pc__tPKdso0rRORLyy1pmUScr8VVmnTnleSYMXo,2726
22
22
  hwpx_automation/markdown_plan.py,sha256=n2H_vhRM-el6Y5KLi21tz-4WzK78-wlE8i8hsUVWu2Y,6886
@@ -50,7 +50,7 @@ hwpx_automation/core/locations.py,sha256=FVbgLhGka9jaUeU2lG8illML15cxi31ouWP05oQ
50
50
  hwpx_automation/core/locator.py,sha256=Q3CfVniPaMSXQ2ABV0JXmTNROkHtKZLz5VR4mCmlJs8,5122
51
51
  hwpx_automation/core/plan.py,sha256=sNFIko5USDhvs7NA_gy4hSUV40q4vIQTc_dZ2d-nFXE,22744
52
52
  hwpx_automation/core/resources.py,sha256=PNPhcGEwq4BrRdMrytgIfeT2_4nrDFB9z97OfxCaQBc,1198
53
- hwpx_automation/core/search.py,sha256=OmUs0wLPxMrmkhbBiiiQQC-YKG8zjz4bHvJbmCae_eU,12280
53
+ hwpx_automation/core/search.py,sha256=M5tSM9DUPvX0Qza6mphkP98PlM41irqGEf1R67C6-Vo,12575
54
54
  hwpx_automation/core/transactions.py,sha256=4Dn13n3fmDl7PHZ3AGRyf09gioNLcC-TgD6-TrqHqzQ,16909
55
55
  hwpx_automation/core/txn.py,sha256=gXbv3JFRnYnWY3L57YeTdpFyQaBBMlvLd-dix7NVFog,1449
56
56
  hwpx_automation/handlers/__init__.py,sha256=iLzNXNd-ernCvKTi4V8h2XzvFDoM4biZp34KIL0fgsg,83
@@ -219,10 +219,10 @@ hwpx_automation/workflow/rendering.py,sha256=MAuL3vSS0vfo-R8ws55E52ddnBrtoYmYikT
219
219
  hwpx_automation/workflow/service.py,sha256=dKhcWQVHVBh8752pIDPSvHPXpsQsmB25hrJD7IsgObc,35945
220
220
  hwpx_automation/workflow/state_machine.py,sha256=8nFj3WPoqBj0H2j9WRbdAUCT7tm3q_ieQsaEX7LPnE4,2230
221
221
  hwpx_automation/workflow/store.py,sha256=S2BTR5g21WgFYfi8ZwvgWQCv7wxUSA8ttlMS9-zNeoU,31663
222
- python_hwpx_automation-7.3.3.dist-info/licenses/LICENSE,sha256=_ubz4wv-BkkT3l3gu-QuH7JGeVjuRYGZoZK95eNsCHU,9688
223
- python_hwpx_automation-7.3.3.dist-info/licenses/NOTICE,sha256=B6vl9SzBdZ0LlAeEd89Q3P6r_rlXZWD6ZJK6Ntz3s6A,644
224
- python_hwpx_automation-7.3.3.dist-info/METADATA,sha256=6SO3powknTW6MECFSnJpEXFYHYQTn85iFMVdDcKnabo,13819
225
- python_hwpx_automation-7.3.3.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
226
- python_hwpx_automation-7.3.3.dist-info/entry_points.txt,sha256=6YDtwFKwyk9BNTR_iCVV0XTwtDRVwENVNvv3wHM81KQ,114
227
- python_hwpx_automation-7.3.3.dist-info/top_level.txt,sha256=jQZZqF1u9rVIJvragSUf8HCHkm0gFVaCViNDZEKfh1A,16
228
- python_hwpx_automation-7.3.3.dist-info/RECORD,,
222
+ python_hwpx_automation-7.3.4.dist-info/licenses/LICENSE,sha256=_ubz4wv-BkkT3l3gu-QuH7JGeVjuRYGZoZK95eNsCHU,9688
223
+ python_hwpx_automation-7.3.4.dist-info/licenses/NOTICE,sha256=B6vl9SzBdZ0LlAeEd89Q3P6r_rlXZWD6ZJK6Ntz3s6A,644
224
+ python_hwpx_automation-7.3.4.dist-info/METADATA,sha256=M2pqQrmq0CGrOdqY4eXWCCcnx-nHDDticK32dOFqieg,13819
225
+ python_hwpx_automation-7.3.4.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
226
+ python_hwpx_automation-7.3.4.dist-info/entry_points.txt,sha256=6YDtwFKwyk9BNTR_iCVV0XTwtDRVwENVNvv3wHM81KQ,114
227
+ python_hwpx_automation-7.3.4.dist-info/top_level.txt,sha256=jQZZqF1u9rVIJvragSUf8HCHkm0gFVaCViNDZEKfh1A,16
228
+ python_hwpx_automation-7.3.4.dist-info/RECORD,,