Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Calibre > Development

Notices

Reply
 
Thread Tools Search this Thread
Old 09-29-2025, 10:13 AM   #1
mfsav2
Member
mfsav2 began at the beginning.
 
Posts: 23
Karma: 10
Join Date: Jan 2013
Device: Kindle
Question New file type plugin - Issue with metadata

Team,
sorry to bother but is driving me nuts
I want to use Calibre for my physical library together with my electronic library so I avoid to purchase multiple times the same book

I've followed a suggestion I've found in internet that I found super cool to create a file format .pbook (https://www.davideaversa.it/blog/how...sical-library/) with some elements using TOML syntax .

one of my pbook is:
Code:
[metadata]
title=I vostri nomi sono scritti nei cieli. Nel mondo di Rose Busingye
author=Davide Perillo
ISBN=9788817163835
source=GoogleBooks
publication_date=
language=it
tag=Physical
I wrote a plugin to read the file, and it works, but it does not read the Metadata

I tried it as FileType or Input but never works.

__init__.py
Code:
from calibre.customize import Plugin

class PBookWrapperPlugin(Plugin):
    name = 'PBook Metadata Reader'
    description = 'Reads metadata from .pbook files (title, authors, tags, ISBN, language)'
    supported_platforms = ['windows', 'osx', 'linux']
    author = 'Your Name'
    version = (1, 0, 0)
    file_types = ['pbook']
    type = 'metadata'

    # Actual plugin implementation
    actual_plugin = 'pbook_main:PBookMetadataReaderPlugin'
pbook_main.py
Code:
import os
from calibre.customize import MetadataReaderPlugin
from calibre.ebooks.metadata.book.base import Metadata

class PBookMetadataReaderPlugin(MetadataReaderPlugin):
    name = "PBook Metadata Reader"
    description = "Reads metadata (title, authors, tags, ISBN, language) from .pbook files"
    supported_platforms = ["windows", "osx", "linux"]
    author = "Your Name"
    version = (1, 0, 0)
    file_types = {"pbook"}

    def get_metadata(self, path_to_ebook, log, abort, *args, **kwargs):
        """
        This is called by Calibre during Add Books.
        path_to_ebook: full path to the .pbook file
        log: logging object
        abort: function to check for user cancellation
        """
        log.info(f"[PBook] get_metadata called for {path_to_ebook}")

        try:
            with open(path_to_ebook, "r", encoding="utf-8") as f:
                raw = f.read()
            log.info(f"[PBook] raw contents:\n{raw}")
        except Exception as e:
            log.error(f"[PBook] Could not read file: {e}")
            return None

        data = self._parse_pbook(raw, log)

        title = data.get("title") or os.path.splitext(os.path.basename(path_to_ebook))[0]
        mi = Metadata(title)

        authors = data.get("author") or data.get("authors")
        if authors:
            mi.authors = [a.strip() for a in authors.split(",")]

        if "isbn" in data:
            mi.isbn = data["isbn"]

        if "tag" in data or "tags" in data:
            mi.tags = [t.strip() for t in (data.get("tag") or data.get("tags")).split(",")]

        if "language" in data:
            mi.language = data["language"]

        log.info(f"[PBook] Metadata extracted: {mi.__dict__}")
        return mi

    def _parse_pbook(self, raw_data, log):
        data = {}
        for line in raw_data.splitlines():
            if "=" not in line:
                continue
            key, val = line.split("=", 1)
            key = key.strip().lower()
            val = val.strip()
            data[key] = val
            log.info(f"[PBook] parsed {key}={val}")
        log.info(f"[PBook] parsed dict: {data}")
        return data
plugin.xml
Code:
<plugin>
    <name>PBook Metadata Reader</name>
    <description>Reads metadata from .pbook files</description>
    <author>Your Name</author>
    <version>1.0.0</version>
    <type>metadata</type>
    <file_types>pbook</file_types>
</plugin>
Can you help me?
what am I doing wrong?

I want the name, author to be read: working
ISBN, Tags, Language to be added to the file: not working

I've tried to debug and the get_metadata() get invoked as the logs (calibre-debug -g) does not show anything

thanks
M
mfsav2 is offline   Reply With Quote
Old 09-30-2025, 01:52 PM   #2
msavazzi
Member
msavazzi began at the beginning.
 
Posts: 15
Karma: 10
Join Date: Sep 2025
Device: Boox
different approach:

Code:
# -*- coding: utf-8 -*-
__license__   = 'GPL v3'
__copyright__ = '2025 Massimo Savazzi'
__my_version__ = "1.0.0"  # Miscellany

"""
In order to manage Physical Books (.pbook) files, we define a Calibre plugin that treats .pbook files as ebooks.
It does import the info from the file and sets the metadata accordingly.
The .pbook file format is assumed to be a simple text file with key=value pairs, based on TOML e.g.:
[metadata]
title=Boook Title
author=Book Author
publisher=Book Publisher
ISBN=9788888888888
source=if scraped from a website, put the name here
publication_date=Book Publication Date
language=two-letter language code, e.g. it, en, fr
tag=Physical - all tags, comma-separated will be imported
"""

from calibre.customize import FileTypePlugin

class PBookEbookImporter(FileTypePlugin):
    name = "PBook Importer"
    description = "Import .pbook files reading the Metadata and updating it accordingly."
    supported_platforms = ['windows', 'osx', 'linux']
    version = (1, 0, 0)
    author = 'Massimo Savazzi'
    minimum_calibre_version = (6, 8, 0)

    file_types = set(['pbook'])
    ebook = True  # <-- This makes Calibre treat .pbook as a real ebook

    on_postimport = True

    def postimport(self, book_id, book_format, db):
        # Same metadata logic as before
        path = db.format_path(book_id, book_format.upper(), index_is_id=True)
        if not path:
            return

        meta = {}
        in_meta = False
        try:
            with open(path, 'r', encoding='utf-8') as f:
                lines = f.readlines()
        except Exception:
            with open(path, 'r', encoding='latin-1') as f:
                lines = f.readlines()

        for line in lines:
            line = line.strip()
            if line.lower() == '[metadata]':
                in_meta = True
                continue
            if in_meta and line.startswith('['):
                break
            if in_meta and '=' in line:
                k, v = line.split('=', 1)
                meta[k.strip().lower()] = v.strip()

        title = meta.get('title')
        authors = [a.strip() for a in meta.get('author', '').replace(';', ',').split(',') if a.strip()] or None
        publisher = meta.get('publisher')
        source = meta.get('source')
        tags = [t.strip() for t in meta.get('tag', '').split(',') if t.strip()] or None
        language = [meta.get('language')] if meta.get('language') else None
        identifiers = {}
        if meta.get('isbn'):
            identifiers['isbn'] = meta.get('isbn').replace('-', '').strip()

        # Apply metadata
        if authors: db.set_authors(book_id, authors, notify=True)
        if title: db.set_title(book_id, title, notify=True)
        if publisher: db.set_publisher(book_id, publisher, notify=True)
        if source: db.set_tags(book_id, [source], notify=True)  # optional: add source as tag
        if tags: db.set_tags(book_id, tags, notify=True)
        if language: db.set_languages(book_id, language, notify=True)
        if identifiers: db.set_identifiers(book_id, identifiers, notify=True)
The only issue is that title sort is not correct as is equal to title
msavazzi is offline   Reply With Quote
Advert
Old 10-06-2025, 09:52 AM   #3
un_pogaz
Chalut o/
un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.
 
un_pogaz's Avatar
 
Posts: 486
Karma: 678910
Join Date: Dec 2017
Device: Kobo
I recomande you to look the native python module configparser that will produces/reads files with syntax similar to what you are looking for.
un_pogaz is offline   Reply With Quote
Old 10-18-2025, 01:07 PM   #4
msavazzi
Member
msavazzi began at the beginning.
 
Posts: 15
Karma: 10
Join Date: Sep 2025
Device: Boox
This is a very good suggestion, will look into it.

---

I've updated the code to use it

Last edited by msavazzi; 10-21-2025 at 02:46 PM.
msavazzi is offline   Reply With Quote
Old 10-21-2025, 02:47 PM   #5
msavazzi
Member
msavazzi began at the beginning.
 
Posts: 15
Karma: 10
Join Date: Sep 2025
Device: Boox
My initial question was how to add it in a way that with the Import - import from folders the .pbook files are read.
It works manually and if I select them from a folder but not on a scan
msavazzi is offline   Reply With Quote
Advert
Old 10-22-2025, 09:22 AM   #6
un_pogaz
Chalut o/
un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.
 
un_pogaz's Avatar
 
Posts: 486
Karma: 678910
Join Date: Dec 2017
Device: Kobo
What do you mean by "a scan"?
un_pogaz is offline   Reply With Quote
Reply

Tags
input, metadata, plugin


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[File Type Plugin] Auto Multi-Convert Squiffers Plugins 1 06-26-2025 11:46 PM
[File Type Plugin] Extract RIS Citations DaltonST Plugins 26 03-10-2023 05:20 PM
[File Type Plugin] Automatically Add Covers to .djvu Files on Import hazel.noelle Plugins 4 01-07-2023 08:33 AM
[File Type Plugin] Zip to cbz Saumee Plugins 2 07-29-2018 04:38 PM
PDB to PMLZ File type plugin pdurrant Plugins 18 02-20-2010 03:19 PM


All times are GMT -4. The time now is 06:32 AM.


MobileRead.com is a privately owned, operated and funded community.