python-redlines 0.2.1__tar.gz → 0.3.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-redlines
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Generate tracked-change redline .docx documents by comparing Word files.
5
5
  Project-URL: Homepage, https://github.com/JSv4/Python-Redlines
6
6
  Project-URL: Issues, https://github.com/JSv4/Python-Redlines/issues
@@ -57,6 +57,9 @@ redline_bytes, stdout, stderr = engine.run_redline(
57
57
  )
58
58
  ```
59
59
 
60
+ `DocxodusEngine` accepts `engine="wmlcomparer"` (default) or `engine="docxdiff"` to select the
61
+ comparison algorithm. See the [project README](https://github.com/JSv4/Python-Redlines#choosing-an-engine).
62
+
60
63
  If an engine's companion package is not installed, instantiating the engine
61
64
  raises `EngineNotInstalledError` with the `pip install` command to fix it.
62
65
 
@@ -28,6 +28,9 @@ redline_bytes, stdout, stderr = engine.run_redline(
28
28
  )
29
29
  ```
30
30
 
31
+ `DocxodusEngine` accepts `engine="wmlcomparer"` (default) or `engine="docxdiff"` to select the
32
+ comparison algorithm. See the [project README](https://github.com/JSv4/Python-Redlines#choosing-an-engine).
33
+
31
34
  If an engine's companion package is not installed, instantiating the engine
32
35
  raises `EngineNotInstalledError` with the `pip install` command to fix it.
33
36
 
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2024-present U.N. Owen <void@some.where>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "0.2.1"
4
+ __version__ = "0.3.0"
@@ -139,9 +139,14 @@ class BaseEngine(object):
139
139
  (as ``str`` or ``pathlib.Path``). Returns the redline output as bytes.
140
140
 
141
141
  Additional keyword arguments are passed to _build_command() for engine-specific options.
142
- DocxodusEngine supports: detail_threshold, case_insensitive, detect_moves,
142
+ DocxodusEngine supports: engine, detail_threshold, case_insensitive, detect_moves,
143
143
  simplify_move_markup, move_similarity_threshold, move_minimum_word_count,
144
144
  detect_format_changes, conflate_spaces, date_time.
145
+
146
+ DocxodusEngine's engine kwarg selects the comparison algorithm: 'wmlcomparer'
147
+ (the default) or 'docxdiff'. The docxdiff engine ignores detail_threshold,
148
+ simplify_move_markup, and detect_format_changes, so passing them alongside
149
+ engine='docxdiff' raises ValueError rather than silently changing nothing.
145
150
  """
146
151
  temp_files = []
147
152
  try:
@@ -194,6 +199,13 @@ class DocxodusEngine(BaseEngine):
194
199
  BINARY_BASE_NAME = 'redline'
195
200
  EXTRA_NAME = 'docxodus'
196
201
 
202
+ # Comparison engines accepted by the redline CLI's --engine flag.
203
+ ENGINES = ('wmlcomparer', 'docxdiff')
204
+
205
+ # DocxCompare.ToDocxDiffSettings drops these on the docxdiff branch, and the CLI
206
+ # accepts them there without complaint, so reject them before we shell out.
207
+ _WMLCOMPARER_ONLY = ('detail_threshold', 'simplify_move_markup', 'detect_format_changes')
208
+
197
209
  # Boolean flags (default False — presence enables)
198
210
  _BOOL_FLAGS = [
199
211
  ('case_insensitive', '--case-insensitive'),
@@ -215,8 +227,33 @@ class DocxodusEngine(BaseEngine):
215
227
  ('date_time', '--date-time'),
216
228
  ]
217
229
 
218
- @staticmethod
219
- def _validate_kwargs(kwargs):
230
+ @classmethod
231
+ def _normalize_engine(cls, kwargs):
232
+ """The chosen engine, lowercased and stripped, or None if the caller didn't pick one."""
233
+ if 'engine' not in kwargs:
234
+ return None
235
+
236
+ engine = kwargs['engine']
237
+ if not isinstance(engine, str):
238
+ raise ValueError(f"engine must be a string, got {engine!r}")
239
+
240
+ normalized = engine.strip().lower()
241
+ if normalized not in cls.ENGINES:
242
+ raise ValueError(
243
+ f"engine must be one of {', '.join(cls.ENGINES)}, got {engine!r}"
244
+ )
245
+ return normalized
246
+
247
+ @classmethod
248
+ def _validate_kwargs(cls, kwargs):
249
+ if cls._normalize_engine(kwargs) == 'docxdiff':
250
+ for name in cls._WMLCOMPARER_ONLY:
251
+ if name in kwargs:
252
+ raise ValueError(
253
+ f"{name} is not supported by the 'docxdiff' engine "
254
+ f"(WmlComparer-only). Remove it or use engine='wmlcomparer'."
255
+ )
256
+
220
257
  if 'detail_threshold' in kwargs:
221
258
  val = kwargs['detail_threshold']
222
259
  if not isinstance(val, (int, float)) or val < 0.0 or val > 1.0:
@@ -234,10 +271,14 @@ class DocxodusEngine(BaseEngine):
234
271
 
235
272
  def _build_command(self, author_tag, original_path, modified_path, target_path, **kwargs):
236
273
  self._validate_kwargs(kwargs)
274
+ engine = self._normalize_engine(kwargs)
237
275
 
238
276
  cmd = [self.extracted_binaries_path, original_path, modified_path, target_path,
239
277
  f'--author={author_tag}']
240
278
 
279
+ if engine is not None:
280
+ cmd.append(f'--engine={engine}')
281
+
241
282
  for kwarg, flag in self._BOOL_FLAGS:
242
283
  if kwargs.get(kwarg):
243
284
  cmd.append(flag)