mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
...
This commit is contained in:
parent
e56f6b08f4
commit
02e92ca871
209
src/calibre/library/catalog.py
Normal file
209
src/calibre/library/catalog.py
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from calibre.customize import CatalogPlugin
|
||||||
|
|
||||||
|
class CSV_XML(CatalogPlugin):
|
||||||
|
'CSV/XML catalog generator'
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
Option = namedtuple('Option', 'option, default, dest, help')
|
||||||
|
|
||||||
|
name = 'Catalog_CSV_XML'
|
||||||
|
description = 'CSV/XML catalog generator'
|
||||||
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
author = 'Greg Riker'
|
||||||
|
version = (1, 0, 0)
|
||||||
|
file_types = set(['csv','xml'])
|
||||||
|
|
||||||
|
cli_options = [
|
||||||
|
Option('--fields',
|
||||||
|
default = 'all',
|
||||||
|
dest = 'fields',
|
||||||
|
help = _('The fields to output when cataloging books in the '
|
||||||
|
'database. Should be a comma-separated list of fields.\n'
|
||||||
|
'Available fields: all, author_sort, authors, comments, '
|
||||||
|
'cover, formats, id, isbn, pubdate, publisher, rating, '
|
||||||
|
'series_index, series, size, tags, timestamp, title, uuid.\n'
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: CSV, XML output formats")),
|
||||||
|
|
||||||
|
Option('--sort-by',
|
||||||
|
default = 'id',
|
||||||
|
dest = 'sort_by',
|
||||||
|
help = _('Output field to sort on.\n'
|
||||||
|
'Available fields: author_sort, id, rating, size, timestamp, title.\n'
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: CSV, XML output formats"))]
|
||||||
|
|
||||||
|
def run(self, path_to_output, opts, db):
|
||||||
|
from calibre.utils.logging import Log
|
||||||
|
|
||||||
|
log = Log()
|
||||||
|
self.fmt = path_to_output[path_to_output.rfind('.') + 1:]
|
||||||
|
if opts.verbose:
|
||||||
|
log("%s:run" % self.name)
|
||||||
|
log(" path_to_output: %s" % path_to_output)
|
||||||
|
log(" Output format: %s" % self.fmt)
|
||||||
|
|
||||||
|
# Display opts
|
||||||
|
opts_dict = vars(opts)
|
||||||
|
keys = opts_dict.keys()
|
||||||
|
keys.sort()
|
||||||
|
log(" opts:")
|
||||||
|
for key in keys:
|
||||||
|
log(" %s: %s" % (key, opts_dict[key]))
|
||||||
|
|
||||||
|
# Get the sorted, filtered database as a dictionary
|
||||||
|
data = self.search_sort_db_as_dict(db, opts)
|
||||||
|
|
||||||
|
if not len(data):
|
||||||
|
log.error("\nNo matching database entries for search criteria '%s'" % opts.search_text)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
# Get the requested output fields as a list
|
||||||
|
fields = self.get_output_fields(opts)
|
||||||
|
|
||||||
|
if self.fmt == 'csv':
|
||||||
|
outfile = open(path_to_output, 'w')
|
||||||
|
|
||||||
|
# Output the field headers
|
||||||
|
outfile.write('%s\n' % ','.join(fields))
|
||||||
|
|
||||||
|
# Output the entry fields
|
||||||
|
for entry in data:
|
||||||
|
outstr = ''
|
||||||
|
for (x, field) in enumerate(fields):
|
||||||
|
item = entry[field]
|
||||||
|
if field in ['authors','tags','formats']:
|
||||||
|
item = ', '.join(item)
|
||||||
|
if x < len(fields) - 1:
|
||||||
|
if item is not None:
|
||||||
|
outstr += '"%s",' % str(item).replace('"','""')
|
||||||
|
else:
|
||||||
|
outstr += '"",'
|
||||||
|
else:
|
||||||
|
if item is not None:
|
||||||
|
outstr += '"%s"\n' % str(item).replace('"','""')
|
||||||
|
else:
|
||||||
|
outstr += '""\n'
|
||||||
|
outfile.write(outstr)
|
||||||
|
outfile.close()
|
||||||
|
|
||||||
|
elif self.fmt == 'xml':
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
from calibre.utils.genshi.template import MarkupTemplate
|
||||||
|
|
||||||
|
PY_NAMESPACE = "http://genshi.edgewall.org/"
|
||||||
|
PY = "{%s}" % PY_NAMESPACE
|
||||||
|
NSMAP = {'py' : PY_NAMESPACE}
|
||||||
|
root = etree.Element('calibredb', nsmap=NSMAP)
|
||||||
|
py_for = etree.SubElement(root, PY + 'for', each="record in data")
|
||||||
|
record = etree.SubElement(py_for, 'record')
|
||||||
|
|
||||||
|
if 'id' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'id')
|
||||||
|
record_child.set(PY + "if", "record['id']")
|
||||||
|
record_child.text = "${record['id']}"
|
||||||
|
|
||||||
|
if 'uuid' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'uuid')
|
||||||
|
record_child.set(PY + "if", "record['uuid']")
|
||||||
|
record_child.text = "${record['uuid']}"
|
||||||
|
|
||||||
|
if 'title' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'title')
|
||||||
|
record_child.set(PY + "if", "record['title']")
|
||||||
|
record_child.text = "${record['title']}"
|
||||||
|
|
||||||
|
if 'authors' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'authors', sort="${record['author_sort']}")
|
||||||
|
record_subchild = etree.SubElement(record_child, PY + 'for', each="author in record['authors']")
|
||||||
|
record_subsubchild = etree.SubElement(record_subchild, 'author')
|
||||||
|
record_subsubchild.text = '$author'
|
||||||
|
|
||||||
|
if 'publisher' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'publisher')
|
||||||
|
record_child.set(PY + "if", "record['publisher']")
|
||||||
|
record_child.text = "${record['publisher']}"
|
||||||
|
|
||||||
|
if 'rating' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'rating')
|
||||||
|
record_child.set(PY + "if", "record['rating']")
|
||||||
|
record_child.text = "${record['rating']}"
|
||||||
|
|
||||||
|
if 'date' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'date')
|
||||||
|
record_child.set(PY + "if", "record['date']")
|
||||||
|
record_child.text = "${record['date']}"
|
||||||
|
|
||||||
|
if 'pubdate' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'pubdate')
|
||||||
|
record_child.set(PY + "if", "record['pubdate']")
|
||||||
|
record_child.text = "${record['pubdate']}"
|
||||||
|
|
||||||
|
if 'size' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'size')
|
||||||
|
record_child.set(PY + "if", "record['size']")
|
||||||
|
record_child.text = "${record['size']}"
|
||||||
|
|
||||||
|
if 'tags' in fields:
|
||||||
|
# <tags py:if="record['tags']">
|
||||||
|
# <py:for each="tag in record['tags']">
|
||||||
|
# <tag>$tag</tag>
|
||||||
|
# </py:for>
|
||||||
|
# </tags>
|
||||||
|
record_child = etree.SubElement(record, 'tags')
|
||||||
|
record_child.set(PY + "if", "record['tags']")
|
||||||
|
record_subchild = etree.SubElement(record_child, PY + 'for', each="tag in record['tags']")
|
||||||
|
record_subsubchild = etree.SubElement(record_subchild, 'tag')
|
||||||
|
record_subsubchild.text = '$tag'
|
||||||
|
|
||||||
|
if 'comments' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'comments')
|
||||||
|
record_child.set(PY + "if", "record['comments']")
|
||||||
|
record_child.text = "${record['comments']}"
|
||||||
|
|
||||||
|
if 'series' in fields:
|
||||||
|
# <series py:if="record['series']" index="${record['series_index']}">
|
||||||
|
# ${record['series']}
|
||||||
|
# </series>
|
||||||
|
record_child = etree.SubElement(record, 'series')
|
||||||
|
record_child.set(PY + "if", "record['series']")
|
||||||
|
record_child.set('index', "${record['series_index']}")
|
||||||
|
record_child.text = "${record['series']}"
|
||||||
|
|
||||||
|
if 'isbn' in fields:
|
||||||
|
record_child = etree.SubElement(record, 'isbn')
|
||||||
|
record_child.set(PY + "if", "record['isbn']")
|
||||||
|
record_child.text = "${record['isbn']}"
|
||||||
|
|
||||||
|
if 'cover' in fields:
|
||||||
|
# <cover py:if="record['cover']">
|
||||||
|
# ${record['cover'].replace(os.sep, '/')}
|
||||||
|
# </cover>
|
||||||
|
record_child = etree.SubElement(record, 'cover')
|
||||||
|
record_child.set(PY + "if", "record['cover']")
|
||||||
|
record_child.text = "${record['cover']}"
|
||||||
|
|
||||||
|
if 'formats' in fields:
|
||||||
|
# <formats py:if="record['formats']">
|
||||||
|
# <py:for each="path in record['formats']">
|
||||||
|
# <format>${path.replace(os.sep, '/')}</format>
|
||||||
|
# </py:for>
|
||||||
|
# </formats>
|
||||||
|
record_child = etree.SubElement(record, 'formats')
|
||||||
|
record_child.set(PY + "if", "record['formats']")
|
||||||
|
record_subchild = etree.SubElement(record_child, PY + 'for', each="path in record['formats']")
|
||||||
|
record_subsubchild = etree.SubElement(record_subchild, 'format')
|
||||||
|
record_subsubchild.text = "${path.replace(os.sep, '/')}"
|
||||||
|
|
||||||
|
outfile = open(path_to_output, 'w')
|
||||||
|
template = MarkupTemplate(etree.tostring(root, xml_declaration=True,
|
||||||
|
encoding="UTF-8", pretty_print=True))
|
||||||
|
outfile.write(template.generate(data=data, os=os).render('xml'))
|
||||||
|
outfile.close()
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user