lxml published tag lxml-7.0.0b1-1 on 22 August 2026. GitHub did not mark the object as a prerelease, yet the version string is 7.0.0b1, a beta on the 7.0 line. The notes that matter for XML and HTML pipelines are a silent empty result fix in htmldiff() and a rebuild with Cython 3.3.0.
The full release notes and downloads are on the GitHub release page.
htmldiff() now raises on join failure ¶
htmldiff() compares two HTML fragments and returns a joined diff string. Content jobs use it to detect scrape drift, to gate CMS publishes, and to store change summaries. GH#492 records that failures while joining that diff (string-join in the notes) were swallowed. The function then returned an empty result.
Empty output is easy to misread. A scheduler that treats empty as no change will skip a write. A loader that stores the return value will insert a blank. A warehouse check that allows empty strings will pass. None of those paths tell you that the compare step failed. After this tag the error propagates. The notes credit Juan Carlos Carvajal B for the patch.
Plan for the new exception. Jobs that used to finish green can now fail the task. Fail closed at the job boundary. Log the inputs, alert, and retry only if the failure is transient. Do not catch the error and return an empty string. That restores the old data loss.
If htmldiff() is a gate in your DAG, add a fixture that used to collapse to empty. Confirm the task errors. Then decide skip versus fail for that code path. This is the only runtime behavior change in the notes.
doctestcompare NameError ¶
LP#2143321 is a NameError inside doctestcompare when doctests are processed by a nonstandard module. Rahul Kumar supplied the original patch.
The comparer is a test helper for HTML and XML output, not the libxml2 parse loop. It bites when CI drives doctests through a wrapper, a custom loader, or a plugin that is not the usual module. The NameError aborted the compare before any assertion ran, so the suite reported a crash rather than a mismatch.
If you do not import doctestcompare, ignore this item. If you do, rerun that suite on 7.0.0b1 and check that the NameError is gone. A real mismatch should now fail as a comparison error, which is the signal you want.
Rebuild with Cython 3.3.0 ¶
The remaining note is a toolchain line: built using Cython 3.3.0. lxml ships a C extension over libxml2 and libxslt. Cython emits that C. A version bump changes the generated sources, the wheels, and the compile that an sdist build performs.
Treat it as a binary pin event. Replace vendored wheels and record the new digest. If you compile from sdist inside a locked image, put Cython 3.3.0 in that image so the output matches what the project built. Mixing a new wheel with an older build image is a staging problem, not a production experiment.
A Cython bump is not a feature list. Rerun XML parse, HTML parse, XSLT, and htmldiff() jobs against the new extension. Keep the previous wheel until that suite is green. Native faults after a Cython upgrade are rare. They are still cheaper to find in staging than in a scrape fleet.
Upgrade notes ¶
Pin the exact tag lxml-7.0.0b1-1 or the exact wheel version. A floating lxml~=7.0 constraint can select this beta because GitHub left the prerelease flag unset. Release APIs that filter on that flag will treat the tag as stable. The b1 in the version is the signal. Staging only until you have run the suite above.
The notes for this tag do not list API breaks and do not give migration steps. They also do not claim parser or XPath changes. The operator visible break is htmldiff() raising instead of returning empty. Update try/except around that call. From source builders need Cython 3.3.0.
Do not promote a 7.0 beta into production parsers on the strength of two bug fixes and a compiler bump. Read the GitHub release page for the full text before you change a lock file.
Where to get it ¶
- GitHub release page
- lxml repository
- Tag
lxml-7.0.0b1-1