mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Catalog plugin file extension converted to lowercase for format comparison
This commit is contained in:
commit
6ce60a0b0c
@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||
|
||||
class TheForce(BasicNewsRecipe):
|
||||
title = u'The Force'
|
||||
@ -21,11 +20,11 @@ class TheForce(BasicNewsRecipe):
|
||||
#dict(name='div', attrs={'class':['pt-box-title', 'pt-box-content', 'blog-entry-footer', 'item-list', 'article-sub-meta']}),
|
||||
#dict(name='div', attrs={'id':['block-td_search_160', 'block-cam_search_160']}),
|
||||
#dict(name='table', attrs={'cellspacing':'0'}),
|
||||
#dict(name='ul', attrs={'class':'articleTools'}),
|
||||
#dict(name='ul', attrs={'class':'articleTools'}),
|
||||
]
|
||||
|
||||
feeds = [
|
||||
('The Force',
|
||||
('The Force',
|
||||
'http://www.theforce.net/outnews/tfnrdf.xml'),
|
||||
]
|
||||
|
||||
|
12
resources/recipes/think_progress.recipe
Normal file
12
resources/recipes/think_progress.recipe
Normal file
@ -0,0 +1,12 @@
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class AdvancedUserRecipe1263409732(BasicNewsRecipe):
|
||||
title = u'Think Progress'
|
||||
description = u'A compilation of progressive articles on social and economic justice, healthy communities, media accountability, global and domestic security.'
|
||||
__author__ = u'Xanthan Gum'
|
||||
language = 'en'
|
||||
|
||||
oldest_article = 7
|
||||
max_articles_per_feed = 100
|
||||
|
||||
feeds = [(u'News Articles', u'http://thinkprogress.org/feed/')]
|
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
|
||||
|
@ -619,7 +619,7 @@ def catalog_option_parser(args):
|
||||
|
||||
# Validate plugin exists for specified output format
|
||||
output = os.path.abspath(args[0])
|
||||
file_extension = output[output.rfind('.') + 1:]
|
||||
file_extension = output[output.rfind('.') + 1:].lower()
|
||||
|
||||
if not file_extension in available_catalog_formats():
|
||||
print_help(parser, log)
|
||||
@ -633,7 +633,7 @@ def catalog_option_parser(args):
|
||||
log = Log()
|
||||
parser = get_parser(_(
|
||||
'''
|
||||
%prog catalog /path/to/destination.(epub|csv|xml|...) [options]
|
||||
%prog catalog /path/to/destination.(csv|epub|mobi|xml ...) [options]
|
||||
|
||||
Export a catalog in format specified by path/to/destination extension.
|
||||
Options control how entries are displayed in the generated catalog ouput.
|
||||
|
Loading…
x
Reference in New Issue
Block a user