diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c67d875..c183e0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: run: python build_differ.py ${{ steps.rid.outputs.rid }} - name: Install packages (editable) - run: pip install -e packages/core -e packages/ooxmlpowertools -e packages/docxodus pytest + run: pip install -e packages/core -e packages/ooxmlpowertools -e packages/clippit -e packages/docxodus pytest - name: Run tests run: python -m pytest tests/ -v @@ -91,6 +91,7 @@ jobs: for rid in ${{ matrix.rids }}; do python build_differ.py "$rid" python -m build --wheel --no-isolation packages/ooxmlpowertools --outdir dist + python -m build --wheel --no-isolation packages/clippit --outdir dist python -m build --wheel --no-isolation packages/docxodus --outdir dist done - name: Check wheels diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index ff781d7..1ad7064 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -1,8 +1,9 @@ name: Upload Python Package -# Builds and publishes all three packages on a tagged release: +# Builds and publishes all packages on a tagged release: # python-redlines (core, pure-Python sdist + wheel) # python-redlines-ooxmlpowertools (per-platform engine wheels) +# python-redlines-clippit (per-platform engine wheels) # python-redlines-docxodus (per-platform engine wheels) on: @@ -54,6 +55,7 @@ jobs: for rid in ${{ matrix.rids }}; do python build_differ.py "$rid" python -m build --wheel --no-isolation packages/ooxmlpowertools --outdir dist + python -m build --wheel --no-isolation packages/clippit --outdir dist python -m build --wheel --no-isolation packages/docxodus --outdir dist done - uses: actions/upload-artifact@v4 diff --git a/.gitignore b/.gitignore index 5d501c3..8f0192d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ __pycache__/ # C# Build Dirs csproj/bin/* csproj/obj/* +csproj-clippit/bin/* +csproj-clippit/obj/* docxodus/**/bin/* docxodus/**/obj/* @@ -239,4 +241,4 @@ fabric.properties .idea/httpRequests # Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser \ No newline at end of file +.idea/caches/build_file_checksums.ser diff --git a/CLAUDE.md b/CLAUDE.md index ac58114..d9c48cc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,22 +6,24 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Python-Redlines generates `.docx` redline/tracked-changes documents by comparing two Word files. A pure-Python wrapper drives compiled C# (.NET 8) engine binaries; the Python layer handles platform detection, binary extraction, temp file management, and subprocess execution. -Two comparison engines are available: +Three comparison engines are available: - **XmlPowerToolsEngine** — wraps Open-XML-PowerTools WmlComparer (original engine) +- **ClippitEngine** — wraps Clippit, an actively-maintained .NET 8 fork of Open-XML-PowerTools (same WmlComparer API) - **DocxodusEngine** — wraps Docxodus, a modernized .NET 8.0 fork with better move detection -## Monorepo structure — three published packages +## Monorepo structure — four published packages -This repo publishes **three** PyPI packages, each with its own `pyproject.toml` under `packages/`: +This repo publishes **four** PyPI packages, each with its own `pyproject.toml` under `packages/`: | Directory | PyPI name | Contents | Wheel | |---|---|---|---| | `packages/core` | `python-redlines` | Pure-Python wrapper (`engines.py`) | `py3-none-any` | | `packages/ooxmlpowertools` | `python-redlines-ooxmlpowertools` | Open-XML-PowerTools binary | per-platform | +| `packages/clippit` | `python-redlines-clippit` | Clippit binary | per-platform | | `packages/docxodus` | `python-redlines-docxodus` | Docxodus binary | per-platform | Engine binaries are **optional dependencies**. Users install an engine via an extra: -`pip install python-redlines[docxodus]`, `[ooxmlpowertools]`, or `[all]`. The core +`pip install python-redlines[docxodus]`, `[ooxmlpowertools]`, `[clippit]`, or `[all]`. The core package has no binaries; each binary package ships one platform's compiled binary as a prebuilt wheel, so end users never compile anything. @@ -39,8 +41,8 @@ git submodule update --init --recursive python build_differ.py linux-x64 python build_differ.py --all -# Install all three packages editable for development -pip install -e packages/core -e packages/ooxmlpowertools -e packages/docxodus pytest +# Install all packages editable for development +pip install -e packages/core -e packages/ooxmlpowertools -e packages/clippit -e packages/docxodus pytest # Run tests (from repo root) python -m pytest tests/ @@ -57,15 +59,15 @@ python -m build --wheel packages/docxodus # needs an archive in _binaries/ - `BaseEngine` — locates the engine binary in its companion package via `importlib.resources`, extracts the platform archive once into a writable user cache dir (`platformdirs.user_cache_dir`), and runs it via subprocess. - - `XmlPowerToolsEngine` / `DocxodusEngine` — subclasses declaring `BINARY_PACKAGE`, - `BINARY_BASE_NAME`, and `EXTRA_NAME`. + - `XmlPowerToolsEngine` / `ClippitEngine` / `DocxodusEngine` — subclasses declaring + `BINARY_PACKAGE`, `BINARY_BASE_NAME`, and `EXTRA_NAME`. - `EngineNotInstalledError` — raised on instantiation if the companion binary package is missing, with the `pip install` command to fix it. - Both engines expose `run_redline(author_tag, original, modified, **kwargs)`. + All engines expose `run_redline(author_tag, original, modified, **kwargs)`. `DocxodusEngine` overrides `_build_command()` to translate kwargs (e.g. `detect_moves`, - `detail_threshold`) into CLI flags. `XmlPowerToolsEngine` uses the legacy - 4-positional-arg format and ignores kwargs. + `detail_threshold`) into CLI flags. `XmlPowerToolsEngine` and `ClippitEngine` use the + legacy 4-positional-arg format and ignore kwargs. 2. **Binary packages** ship one platform archive under `src//_binaries/.tar.gz` (or `.zip` for Windows). The archive is @@ -74,6 +76,7 @@ python -m build --wheel packages/docxodus # needs an archive in _binaries/ 3. **C# sources**: - `csproj/Program.cs` — Open-XML-PowerTools CLI tool + - `csproj-clippit/Program.cs` — Clippit CLI tool (Clippit pulled from NuGet, no submodule) - `docxodus/tools/redline/Program.cs` — Docxodus CLI tool (git submodule) `build_differ.py` compiles an engine for a given RID with `dotnet publish` and @@ -86,22 +89,23 @@ python -m build --wheel packages/docxodus # needs an archive in _binaries/ the wheel, repeat. - `.github/workflows/ci.yml` — tests on each OS (native RID) + builds all wheels. - `.github/workflows/python-publish.yml` — on release, builds per-platform engine - wheels across 3 OS runners, the core sdist+wheel, and publishes all three packages. + wheels across 3 OS runners, the core sdist+wheel, and publishes all packages. ## Version management `packages/core/src/python_redlines/__about__.py` is the single source of truth. -The two binary packages read it via `[tool.hatch.version] path = "../core/..."`, -so all three always share one version. Bump only that file. +The binary packages read it via `[tool.hatch.version] path = "../core/..."`, +so all packages always share one version. Bump only that file. ## Testing Notes Tests live in repo-root `tests/` and must be run from the repo root (fixtures use -relative paths like `tests/fixtures/original.docx`). They require all three packages +relative paths like `tests/fixtures/original.docx`). They require all packages installed and the binaries built for the current platform. The XmlPowerToolsEngine integration test validates exactly 9 revisions on the fixture documents. ## Stdout Format Differences - **XmlPowerToolsEngine**: `"Revisions found: 9"` +- **ClippitEngine**: `"Revisions found: 9"` (same WmlComparer-based format) - **DocxodusEngine**: `"Redline complete: 9 revision(s) found"` diff --git a/README.md b/README.md index eec3ff7..dbd0217 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,8 @@ comparison settings, and how the packages are built and distributed. ## Comparison Engines -Python-Redlines provides **two comparison engines**. `DocxodusEngine` is the default and -recommended choice; `XmlPowerToolsEngine` remains available as a legacy option. +Python-Redlines provides **three comparison engines**. `DocxodusEngine` is the default and +recommended choice; `ClippitEngine` and `XmlPowerToolsEngine` are also available. ### `DocxodusEngine` — Default (Recommended) @@ -61,6 +61,19 @@ engine = DocxodusEngine() redline_bytes, stdout, stderr = engine.run_redline("AuthorName", original_bytes, modified_bytes) ``` +### `ClippitEngine` + +Wraps [Clippit](https://github.com/sergey-tihon/Clippit), an actively-maintained .NET 8 fork of +Open-XML-PowerTools. It uses the same `WmlComparer` API as `XmlPowerToolsEngine` (same options and +`Revisions found: N` stdout) but rides a maintained, modern dependency. + +```python +from python_redlines import ClippitEngine + +engine = ClippitEngine() +redline_bytes, stdout, stderr = engine.run_redline("AuthorName", original_bytes, modified_bytes) +``` + ### `XmlPowerToolsEngine` — Legacy Wraps the original [Open-XML-PowerTools](https://github.com/OpenXmlDev/Open-Xml-PowerTools) `WmlComparer`. This @@ -76,7 +89,7 @@ redline_bytes, stdout, stderr = engine.run_redline("AuthorName", original_bytes, > **Note:** Open-XML-PowerTools was archived by Microsoft and is no longer maintained. It uses an older > version of the Open XML SDK. While it works for many purposes, Docxodus is the recommended engine going forward. -Both engines share the same API — the only difference is the class you instantiate and the stdout format +All engines share the same API — the only difference is the class you instantiate and the stdout format (see [Stdout Differences](#stdout-differences) below). ## Getting Started @@ -92,8 +105,9 @@ as extras: ```commandline pip install python-redlines[docxodus] # Docxodus engine +pip install python-redlines[clippit] # Clippit engine (maintained OOXML PowerTools fork) pip install python-redlines[ooxmlpowertools] # Open-XML-PowerTools engine -pip install python-redlines[all] # both engines +pip install python-redlines[all] # all engines ``` Prebuilt wheels are available for Linux, macOS, and Windows (x64 and arm64); `pip` @@ -146,12 +160,13 @@ redline_bytes, stdout, stderr = engine.run_redline( Both engines follow the same pattern: a Python wrapper class invokes a self-contained C# binary via subprocess. -The repository is a **monorepo of three separately-published packages**: +The repository is a **monorepo of four separately-published packages**: | Package | PyPI name | Contents | |---|---|---| | `packages/core` | `python-redlines` | Pure-Python wrapper; no binaries | | `packages/ooxmlpowertools` | `python-redlines-ooxmlpowertools` | Open-XML-PowerTools engine binary | +| `packages/clippit` | `python-redlines-clippit` | Clippit engine binary | | `packages/docxodus` | `python-redlines-docxodus` | Docxodus engine binary | The core package's `[docxodus]` / `[ooxmlpowertools]` / `[all]` extras pull in the @@ -189,6 +204,7 @@ The two engines produce slightly different stdout messages: | Engine | Example stdout | |---|---| | `XmlPowerToolsEngine` | `Revisions found: 9` | +| `ClippitEngine` | `Revisions found: 9` | | `DocxodusEngine` | `Redline complete: 9 revision(s) found` | ## Development @@ -211,8 +227,8 @@ git submodule update --init --recursive # Build the engine binaries for your platform (RIDs: linux-x64, win-x64, osx-arm64, ...) python build_differ.py linux-x64 -# Install all three packages editable -pip install -e packages/core -e packages/ooxmlpowertools -e packages/docxodus pytest +# Install all packages editable +pip install -e packages/core -e packages/ooxmlpowertools -e packages/clippit -e packages/docxodus pytest ``` ### Commands diff --git a/build_differ.py b/build_differ.py index 17c5315..63b1161 100644 --- a/build_differ.py +++ b/build_differ.py @@ -30,6 +30,15 @@ "python_redlines_ooxmlpowertools", "_binaries", ), }, + { + "name": "clippit", + "csproj": os.path.join("csproj-clippit"), + "csproj_file": os.path.join("csproj-clippit", "clippit-redline.csproj"), + "binaries_dir": os.path.join( + "packages", "clippit", "src", + "python_redlines_clippit", "_binaries", + ), + }, { "name": "docxodus", "csproj": os.path.join("docxodus", "tools", "redline"), diff --git a/csproj-clippit/Program.cs b/csproj-clippit/Program.cs new file mode 100644 index 0000000..d3a37f3 --- /dev/null +++ b/csproj-clippit/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using Clippit; +using Clippit.Word; +using DocumentFormat.OpenXml.Packaging; + +class Program +{ + static void Main(string[] args) + { + if (args.Length != 4) + { + Console.WriteLine("Usage: clippit "); + return; + } + + string authorTag = args[0]; + string originalFilePath = args[1]; + string modifiedFilePath = args[2]; + string outputFilePath = args[3]; + + if (!File.Exists(originalFilePath) || !File.Exists(modifiedFilePath)) + { + Console.WriteLine("Error: One or both files do not exist."); + return; + } + + try + { + var originalBytes = File.ReadAllBytes(originalFilePath); + var modifiedBytes = File.ReadAllBytes(modifiedFilePath); + var originalDocument = new WmlDocument(originalFilePath, originalBytes); + var modifiedDocument = new WmlDocument(modifiedFilePath, modifiedBytes); + + var comparisonSettings = new WmlComparerSettings + { + AuthorForRevisions = authorTag, + DetailThreshold = 0 + }; + + var comparisonResults = WmlComparer.Compare(originalDocument, modifiedDocument, comparisonSettings); + var revisions = WmlComparer.GetRevisions(comparisonResults, comparisonSettings); + + // Output results + Console.WriteLine($"Revisions found: {revisions.Count}"); + + File.WriteAllBytes(outputFilePath, comparisonResults.DocumentByteArray); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + Console.WriteLine("Detailed Stack Trace:"); + Console.WriteLine(ex.StackTrace); + } + } +} diff --git a/csproj-clippit/clippit-redline.csproj b/csproj-clippit/clippit-redline.csproj new file mode 100644 index 0000000..8d215f9 --- /dev/null +++ b/csproj-clippit/clippit-redline.csproj @@ -0,0 +1,17 @@ + + + + Exe + net8.0 + enable + enable + + clippit-redline + + + + + + + diff --git a/packages/clippit/README.md b/packages/clippit/README.md new file mode 100644 index 0000000..9a9bc03 --- /dev/null +++ b/packages/clippit/README.md @@ -0,0 +1,11 @@ +# python-redlines-clippit + +Compiled Clippit redline engine binary for +[`python-redlines`](https://pypi.org/project/python-redlines/). + +This package only contains the platform-specific engine binary. Install it via +the `python-redlines` extra rather than directly: + +```bash +pip install python-redlines[clippit] +``` diff --git a/packages/clippit/hatch_build.py b/packages/clippit/hatch_build.py new file mode 100644 index 0000000..120046d --- /dev/null +++ b/packages/clippit/hatch_build.py @@ -0,0 +1,42 @@ +"""Wheel build hook: stamp the platform tag from the bundled binary archive. + +Each binary package wheel must target exactly one platform. The archive placed +in src//_binaries/ by build_differ.py determines the wheel's platform tag. +""" +import pathlib + +from hatchling.builders.hooks.plugin.interface import BuildHookInterface + +# .NET runtime identifier -> wheel platform tag +PLATFORM_TAGS = { + "linux-x64": "manylinux2014_x86_64", + "linux-arm64": "manylinux2014_aarch64", + "win-x64": "win_amd64", + "win-arm64": "win_arm64", + "osx-x64": "macosx_11_0_x86_64", + "osx-arm64": "macosx_11_0_arm64", +} + + +class RedlinesBinaryBuildHook(BuildHookInterface): + PLUGIN_NAME = "custom" + + def initialize(self, version, build_data): + archives = sorted( + p for p in (pathlib.Path(self.root) / "src").glob("*/_binaries/*") + if p.name.endswith((".tar.gz", ".zip")) + ) + if len(archives) != 1: + raise ValueError( + f"Expected exactly one binary archive under src/*/_binaries/, " + f"found {len(archives)}: {[a.name for a in archives]}. " + f"Run `python build_differ.py ` to populate it before building." + ) + + rid = archives[0].name.split(".", 1)[0] + if rid not in PLATFORM_TAGS: + raise ValueError(f"Unknown runtime identifier '{rid}' from archive {archives[0].name}") + + build_data["pure_python"] = False + build_data["infer_tag"] = False + build_data["tag"] = f"py3-none-{PLATFORM_TAGS[rid]}" diff --git a/packages/clippit/pyproject.toml b/packages/clippit/pyproject.toml new file mode 100644 index 0000000..cc766c1 --- /dev/null +++ b/packages/clippit/pyproject.toml @@ -0,0 +1,35 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "python-redlines-clippit" +dynamic = ["version"] +description = "Clippit redline engine binary for python-redlines." +readme = "README.md" +requires-python = ">=3.9" +license = "MIT" +authors = [ + { name = "John Scrudato IV" }, +] +classifiers = [ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", +] + +[project.urls] +Homepage = "https://github.com/JSv4/Python-Redlines" +Source = "https://github.com/JSv4/Python-Redlines" + +# Version is single-sourced from the core package so all packages release together. +[tool.hatch.version] +path = "../core/src/python_redlines/__about__.py" + +[tool.hatch.build.targets.wheel] +packages = ["src/python_redlines_clippit"] +artifacts = ["*.tar.gz", "*.zip"] + +# Stamps the wheel with the correct platform tag based on the archive in _binaries/. +[tool.hatch.build.targets.wheel.hooks.custom] +path = "hatch_build.py" diff --git a/packages/clippit/src/python_redlines_clippit/__init__.py b/packages/clippit/src/python_redlines_clippit/__init__.py new file mode 100644 index 0000000..268e4a7 --- /dev/null +++ b/packages/clippit/src/python_redlines_clippit/__init__.py @@ -0,0 +1,10 @@ +"""Clippit redline engine binary for python-redlines. + +This package ships only the compiled engine binary for a single platform, +under ``_binaries/``. It is installed automatically via:: + + pip install python-redlines[clippit] + +It is not meant to be imported directly; ``python_redlines.ClippitEngine`` +locates the binary here at runtime. +""" diff --git a/packages/clippit/src/python_redlines_clippit/_binaries/.gitkeep b/packages/clippit/src/python_redlines_clippit/_binaries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/packages/core/README.md b/packages/core/README.md index f75be0b..1ca5cdf 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -8,8 +8,9 @@ the one(s) you need as extras: ```bash pip install python-redlines[docxodus] # Docxodus engine +pip install python-redlines[clippit] # Clippit engine pip install python-redlines[ooxmlpowertools] # Open-XML-PowerTools engine -pip install python-redlines[all] # both +pip install python-redlines[all] # all ``` Binaries are prebuilt for each platform and embedded in the companion package's diff --git a/packages/core/pyproject.toml b/packages/core/pyproject.toml index 62d0bee..4df7389 100644 --- a/packages/core/pyproject.toml +++ b/packages/core/pyproject.toml @@ -28,12 +28,13 @@ dependencies = [ ] # Engine binaries ship in separate companion packages. Install an engine via -# its extra, e.g. `pip install python-redlines[docxodus]`. All three packages -# are released together from the same repository on each tagged release. +# its extra, e.g. `pip install python-redlines[docxodus]`. All packages are +# released together from the same repository on each tagged release. [project.optional-dependencies] ooxmlpowertools = ["python-redlines-ooxmlpowertools"] +clippit = ["python-redlines-clippit"] docxodus = ["python-redlines-docxodus"] -all = ["python-redlines-ooxmlpowertools", "python-redlines-docxodus"] +all = ["python-redlines-ooxmlpowertools", "python-redlines-clippit", "python-redlines-docxodus"] [project.urls] Homepage = "https://github.com/JSv4/Python-Redlines" diff --git a/packages/core/src/python_redlines/__init__.py b/packages/core/src/python_redlines/__init__.py index 56014f6..9e3203e 100644 --- a/packages/core/src/python_redlines/__init__.py +++ b/packages/core/src/python_redlines/__init__.py @@ -5,6 +5,7 @@ from .__about__ import __version__ from .engines import ( BaseEngine, + ClippitEngine, DocxodusEngine, EngineNotInstalledError, XmlPowerToolsEngine, @@ -13,6 +14,7 @@ __all__ = [ "BaseEngine", "XmlPowerToolsEngine", + "ClippitEngine", "DocxodusEngine", "EngineNotInstalledError", "__version__", diff --git a/packages/core/src/python_redlines/engines.py b/packages/core/src/python_redlines/engines.py index 63e07af..59e7669 100644 --- a/packages/core/src/python_redlines/engines.py +++ b/packages/core/src/python_redlines/engines.py @@ -189,6 +189,18 @@ class XmlPowerToolsEngine(BaseEngine): EXTRA_NAME = 'ooxmlpowertools' +class ClippitEngine(BaseEngine): + """Wraps Clippit, an actively-maintained .NET 8 fork of Open-XML-PowerTools. + + Uses the same WmlComparer API and the legacy 4-positional-arg CLI format as + XmlPowerToolsEngine, so it inherits BaseEngine._build_command() unchanged and + ignores engine-specific kwargs. + """ + BINARY_PACKAGE = 'python_redlines_clippit' + BINARY_BASE_NAME = 'clippit-redline' + EXTRA_NAME = 'clippit' + + class DocxodusEngine(BaseEngine): BINARY_PACKAGE = 'python_redlines_docxodus' BINARY_BASE_NAME = 'redline' diff --git a/tests/test_clippit_engine.py b/tests/test_clippit_engine.py new file mode 100644 index 0000000..b69080b --- /dev/null +++ b/tests/test_clippit_engine.py @@ -0,0 +1,41 @@ +import pytest + +from python_redlines.engines import ClippitEngine + + +def load_docx_bytes(file_path): + with open(file_path, 'rb') as file: + return file.read() + + +@pytest.fixture +def original_docx(): + return load_docx_bytes('tests/fixtures/original.docx') + + +@pytest.fixture +def modified_docx(): + return load_docx_bytes('tests/fixtures/modified.docx') + + +def test_run_clippit_with_real_files(original_docx, modified_docx): + wrapper = ClippitEngine() + + author_tag = "TestAuthor" + + redline_output, stdout, stderr = wrapper.run_redline(author_tag, original_docx, modified_docx) + + assert redline_output is not None + assert isinstance(redline_output, bytes) + assert len(redline_output) > 0 + assert stderr is None + # Clippit wraps the same WmlComparer API as Open-XML-PowerTools and emits the + # same stdout format. + assert "Revisions found:" in stdout + + +def test_clippit_uses_positional_command(): + """ClippitEngine inherits the legacy 4-positional-arg CLI format.""" + engine = ClippitEngine() + cmd = engine._build_command("Author", "/tmp/orig.docx", "/tmp/mod.docx", "/tmp/out.docx") + assert cmd[1:] == ["Author", "/tmp/orig.docx", "/tmp/mod.docx", "/tmp/out.docx"] diff --git a/tests/test_engine_contract.py b/tests/test_engine_contract.py index fa60769..4b8a9bf 100644 --- a/tests/test_engine_contract.py +++ b/tests/test_engine_contract.py @@ -1,6 +1,6 @@ import pytest -from python_redlines.engines import XmlPowerToolsEngine, DocxodusEngine +from python_redlines.engines import XmlPowerToolsEngine, ClippitEngine, DocxodusEngine def load_docx_bytes(file_path): @@ -18,7 +18,7 @@ def modified_docx(): return load_docx_bytes('tests/fixtures/modified.docx') -@pytest.mark.parametrize("engine_class", [XmlPowerToolsEngine, DocxodusEngine]) +@pytest.mark.parametrize("engine_class", [XmlPowerToolsEngine, ClippitEngine, DocxodusEngine]) def test_engine_returns_bytes(engine_class, original_docx, modified_docx): engine = engine_class() redline_output, stdout, stderr = engine.run_redline("TestAuthor", original_docx, modified_docx) @@ -28,7 +28,7 @@ def test_engine_returns_bytes(engine_class, original_docx, modified_docx): assert len(redline_output) > 0 -@pytest.mark.parametrize("engine_class", [XmlPowerToolsEngine, DocxodusEngine]) +@pytest.mark.parametrize("engine_class", [XmlPowerToolsEngine, ClippitEngine, DocxodusEngine]) def test_engine_no_stderr(engine_class, original_docx, modified_docx): engine = engine_class() _, _, stderr = engine.run_redline("TestAuthor", original_docx, modified_docx) @@ -36,7 +36,7 @@ def test_engine_no_stderr(engine_class, original_docx, modified_docx): assert stderr is None -@pytest.mark.parametrize("engine_class", [XmlPowerToolsEngine, DocxodusEngine]) +@pytest.mark.parametrize("engine_class", [XmlPowerToolsEngine, ClippitEngine, DocxodusEngine]) def test_engine_has_stdout(engine_class, original_docx, modified_docx): engine = engine_class() _, stdout, _ = engine.run_redline("TestAuthor", original_docx, modified_docx)