ebookerr-sdk
The toolkit for writing ebookerr plugins: the plugin
contract (ebookerr_sdk.spi), the host that runs a plugin (ebookerr_sdk.host), a test kit
(ebookerr_sdk.testing), the pack command, and helper kits for EPUB files, downloads,
validation, library servers and text generation.
- Guide: https://github.com/ArcCdr/lit-ebookerr/blob/main/docs/PLUGIN_DEV.md
- API reference: https://arccdr.github.io/lit-ebookerr/
- Plugins: https://github.com/ArcCdr/ebookerr-plugins
Install
pip install "ebookerr-sdk==3.5.*"
The SDK's MAJOR.MINOR is the SPI version it speaks: ebookerr-sdk 3.5.x speaks SPI 3.5. It needs
Python 3.11 or later.
Start a plugin
python -m ebookerr_sdk.pack new hello_book --type book
pytest hello_book/tests
python -m ebookerr_sdk.pack check hello_book
python -m ebookerr_sdk.pack build hello_book --out dist
new writes a plugin that passes check and its own test; --type is source, epub, book
or catalog. The guide explains what to write next and how to install the zip in ebookerr.
Compatibility
| ebookerr | SPI | ebookerr-sdk |
|---|---|---|
| 2.24 | 3.0 | 3.0.x |
| 2.24.1 | 3.1 | 3.1.x |
| 2.24.7 | 3.2 | 3.2.x |
| 2.24.9 | 3.3 | 3.3.x |
| 2.24.10 | 3.4 | 3.4.x |
| 2.24.11 | 3.5 | 3.5.x |
ebookerr loads a plugin when its spi_version has ebookerr's SPI MAJOR and a MINOR not above
ebookerr's; otherwise it shows the plugin as incompatible and offers a compatible release.
Versioning
- A MINOR release only adds: an optional manifest key whose default keeps today's behaviour, or a new protocol, role, operation, context method, event or trigger scope that you opt into.
- Anything else — removing or renaming, changing a default or a meaning, making a key required, refusing a manifest that was valid — waits for the next MAJOR release.
- ebookerr ignores manifest keys it does not know, with a warning; your plugin should ignore
request keys it does not know.
python -m ebookerr_sdk.pack checkrefuses unknown manifest keys and settings-field types, so a typo is caught before you release. - Before it is removed, a public item is deprecated: named in these release notes and logged once per plugin as a warning when used, it keeps working for at least two MINOR releases and six months.
- An ebookerr release supports one SPI MAJOR, and moves to a new MAJOR only once every official plugin has a compatible release.
- A PATCH release of the SDK fixes defects only; it never changes the public API.
- The public API is
manifest.toml,ebookerr_sdk.spi,ebookerr_sdk.host,ebookerr_sdk.testing,python -m ebookerr_sdk.packand the kitsebookerr_sdk.epub,.validate,.download,.generation,.providersand.domain.ebookerr_sdk.wire,.readpos,.registry_indexand every_-prefixed name are internal and may change in any release.
Release notes
3.5.0
SPI 3.5. A library-server plugin can ask capture_position to warn about a book it cannot
capture only once; later sentences of this section name each change. A plugin written for SPI
3.4 needs no change.
ebookerr_sdk.providers.capture_warnings.CaptureWarnings(ctx) remembers, in the plugin's own state,
the capture failure last warned about for each server item; pass it as capture_position(..., warnings=) and a book that keeps failing the same way is warned about once (again after a week, or
when the failure changes), then logged at DEBUG. join_anchors logs its summary at DEBUG.
parse_text_to_book decides the paragraph rule per chapter, so a text written one paragraph per
line keeps its paragraphs even when a blank line sets off its chapter headings, and a heading may
end in a full stop or a colon (CHAPTER I., Chapter One:).
3.4.0
SPI 3.4. The domain and EPUB kits gain the helpers ebookerr's own doors share; later sentences of this section name each one. A plugin written for SPI 3.3 needs no change.
ebookerr_sdk.epub.opf.UNTYPED_IDENTIFIER_SCHEMES names the identifier schemes a package cannot carry as a book identifier (url, uri, uuid, calibre, http, https, urn); PackageDocument.set_typed_identifiers no longer writes them, so writing back what typed_identifiers read changes nothing. PackageDocument.set_title drops a changed title's stale sort key (calibre:title_sort, or an EPUB 3 file-as refinement), so a reader re-derives it. ebookerr_sdk.domain.authors is the one parser of a book's author text: split_authors and join_authors read and write the names joined by AUTHOR_SEPARATOR (" & ", an & with whitespace on both sides), authors_key compares two texts whatever the order and case, and includes_authors tells whether a book is by given people. ebookerr_sdk.domain.adoption.author_set and score_pair's author signal compare the set of names, so co-authors listed in another order match. ebookerr_sdk.domain.ids.normalise_site, ebookerr_sdk.domain.series_rules (names_itself, without_self_references) and ebookerr_sdk.domain.metadata's normalise_token_list, IDENTIFIER_RE, parse_identifiers and format_identifiers are the helpers ebookerr itself uses for those fields. ebookerr_sdk.domain.epub_metadata.epub_book_fields maps what an EPUB says to the library fields every door stores — every author, the publisher unless it only names the site, typed identifiers, series, categories and tags — so a book pulled from a link and the same file uploaded agree. epub_publisher (the publisher an EPUB names, unless it only names the site) and title_or_file_stem (the title, or the file's name without its extension when the title is blank, Untitled or Unknown) are the two rules it is built from.
3.3.0
SPI 3.3. The EPUB kit gains helpers for the EPUBs ebookerr writes; later sentences of this
section name each one. A plugin written for SPI 3.2 needs no change. build_epub writes its package through ebookerr_sdk.epub.builder: the NCX dtb:uid is the OPF identifier and the package carries its creation date, so a built book validates without findings. EpubDocument.set_title writes a new title into the package and every table of contents (NcxDocument.set_doc_title, NavDocument.set_doc_title), so a retitled book's OPF and NCX agree. retitle_built_epub gives a build_epub output a new title in its package, tables of contents and title page; convert_stage and download_convert_stage use it, so a converted book's file carries the title the book gets. ebookerr_sdk.epub.text_convert.is_chapter_heading names the prose chapter-heading rule. convert_stage titles an uploaded document after its own title, else its file name unless the name is a placeholder such as Document1 or Untitled, else a first line that is no chapter heading. Book.front_matter holds the text above a document's first heading; build_epub puts it on the title page, and parse_text_to_book fills it instead of making that text a chapter. parse_text_to_book keeps each line of a text that has no blank line at all as its own paragraph. convert_stage and download_convert_stage pass a user_facing conversion error's message through unchanged and answer "The file could not be converted." for any other failure, so no library message or path reaches a user. EpubDocument.drm_protected() tells a DRM-protected book (a rights.xml, or an encryption.xml using anything but font obfuscation) from one whose fonts are only obfuscated.
3.2.0
SPI 3.2. A story can name the multi-part work it is one part of: StoryPatch.work and
StoryPatch.work_url. series and series_url mean a series the site itself declares —
separate works in a declared order — never the work a chapter belongs to. BookView.work_url
carries the work a book is a chapter of. ebookerr_sdk.domain.adoption gains same_series and
same_work; AdoptionSide.work_url and Evidence.same_work are new, and signal E5 is "same
series or same work". EBOOKERR_META_KEYS gains work_url. A plugin written for SPI 3.1 needs
no change.
3.1.0
SPI 3.1. A [[ui_triggers]] entry's icon is optional and defaults to the plugin's icon;
declare one only when a plugin has more than one action. Every glyph name must be one the
self-hosted Material Symbols font renders (ebookerr_sdk/spi/material_symbols.txt): pack check
reports an unknown name, two actions of one scope showing the same glyph, and a trigger without
icon in a manifest that still declares spi_version = "3.0". pack check now reports a declared
requirement that is not installed where it runs instead of guessing its module names. A plugin
written for SPI 3.0 needs no change.
3.0.0
SPI 3.0. A plugin written for SPI 2.x declares spi_version = "3.0" and applies these changes:
spi_versionis required.- Roles are declared only as
[roles.<name>]tables. The top-level keysexclusive_group,provider,delete_mode,reader_url_template,handles_merge_proposals,catch_allandextract_url_patternsare gone (provider,delete_modeandreader_url_templateremain keys of[roles.library_server]). network,auth_methods,headless,headedanddefault_enabledare no longer manifest keys. A plugin runs on events when it declaresevents, and runs by hand when it declares abook_selection_actionorcover_invalidatetrigger;PluginManifest.headedis derived from its triggers.- Settings-field types are
string,textarea,int,float,bool,url,url_list,threshold_list,record_listandcommand: a secret issecret = trueon astring, a drop-down isoptionswithoptions_strict = trueon astring; the typestext,secretandselectare gone.SettingsGroup.collapsedis gone. UiFilterandUiTrigger.filtersare gone.PluginContext.ask_yes_noreturnsTrue,False, orNonewhen the prompt was abandoned or timed out;PluginContext.ask_yes_no_answerandPluginContext.queueare gone.UpdateCheckingSource.check_for_updatealways receivesctx; itscancel_eventparameter is gone.BookView.erotica_tagsis gone; useBookView.tags.ProviderAnchor,ProviderBookmarkandReadPositionAnchoringare imported fromebookerr_sdk.providersonly.- New:
PluginContext.credentials(url)andSiteCredential— the stored sign-in for a site the plugin may use: a host in itsauth_sites("*"for any site it processes) or the host of acredential = trueURL setting. - New:
python -m ebookerr_sdk.pack newstarts a plugin;pack checkrefuses unknown manifest keys, settings-field types and trigger scopes. ebookerr_sdk.spiis split into modules (errors,settings,types,views,declarations,context,protocols); every name still imports fromebookerr_sdk.spi.ebookerr_sdk.wire,ebookerr_sdk.readposandebookerr_sdk.registry_indexare internal.
Licence
ebookerr-sdk is released under the MIT licence. Each plugin carries its own licence.
Metadata
Release files for ebookerr-sdk 3.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ebookerr_sdk-3.5.0.tar.gz | 297.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ebookerr_sdk-3.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 641.7 kB
Release files / ebookerr_sdk-3.5.0.tar.gz
| Download URL | ebookerr_sdk-3.5.0.tar.gz |
|---|---|
| Size | 297.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bf7e105fc73c0310137275d50370c7ea94b9dfe630842c639f96627ce980c953
|
|
BLAKE2b-256 checksum How to use checksums |
c85a4cddf0fae0c760d9275b3bc3b4f8cbe89fcf67174b08eef1de651736acdc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / ebookerr_sdk-3.5.0-py3-none-any.whl
| Download URL | ebookerr_sdk-3.5.0-py3-none-any.whl |
|---|---|
| Size | 343.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6287fe8ae7e21c923cb7838fc45c34897c400c0d01396197ef0668a44709ed6e
|
|
BLAKE2b-256 checksum How to use checksums |
321c4b21700ef1eb137bc920ed735da3b77e22178e4a0b9971f4902fb9f15962
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logSecurity for ebookerr-sdk 3.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ebookerr_sdk-3.5.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.