Support for editing RTF metadata and documentation updates.

This commit is contained in:
Kovid Goyal 2007-06-02 19:42:53 +00:00
parent f119bb5994
commit 3bab77322e
5 changed files with 90 additions and 16 deletions

View File

@ -13,7 +13,7 @@
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
''' E-book management software'''
__version__ = "0.3.44"
__version__ = "0.3.45"
__docformat__ = "epytext"
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"

View File

@ -95,7 +95,8 @@ class TransferBuffer(list):
"""
Return a string representation of this buffer.
Packets are represented as hex strings, in 2-byte pairs, S{<=} 16 bytes to a line. An ASCII representation is included. For example::
Packets are represented as hex strings, in 2-byte pairs, S{<=} 16 bytes to a line.
An ASCII representation is included. For example::
0700 0100 0000 0000 0000 0000 0c00 0000 ................
0200 0000 0400 0000 4461 7461 ........Data
"""

View File

@ -13,8 +13,8 @@
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
This package contains logic to read and write LRF files. The LRF file format is documented at U{http://www.sven.de/librie/Librie/LrfFormat}.
At the time fo writing, this package only supports reading and writing LRF meat information. See L{meta}.
This package contains logic to read and write LRF files.
The LRF file format is documented at U{http://www.sven.de/librie/Librie/LrfFormat}.
"""
from optparse import OptionParser, OptionValueError
@ -53,8 +53,8 @@ def option_parser(usage):
dest="title", help="Set the title. Default: filename.")
metadata.add_option("-a", "--author", action="store", type="string", \
dest="author", help="Set the author. Default: %default", default='Unknown')
metadata.add_option("--freetext", action="store", type="string", \
dest="freetext", help="Set the comments.", default=' ')
metadata.add_option("--comment", action="store", type="string", \
dest="freetext", help="Set the comment.", default=' ')
metadata.add_option("--category", action="store", type="string", \
dest="category", help="Set the category", default=' ')
metadata.add_option('--title-sort', action='store', default='', dest='title_sort',

View File

@ -19,8 +19,26 @@ the L{libprs500.lrf.meta} module.
__docformat__ = "epytext"
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
from optparse import OptionParser
from libprs500 import __version__ as VERSION
def get_parser(extension):
''' Return an option parser with the basic metadata options already setup'''
parser = OptionParser(version='libprs500 version: '+VERSION,
usage='''%prog [options] myfile.'''+extension)
parser.add_option("-t", "--title", action="store", type="string", \
dest="title", help="Set the book title")
parser.add_option("-a", "--authors", action="store", type="string", \
dest="authors", help="Set the authors", default=None)
parser.add_option("-c", "--category", action="store", type="string", \
dest="category", help="The category this book belongs"+\
" to. E.g.: History", default=None)
parser.add_option('--comment', dest='comment', default=None, action='store',
help='Set the comment')
return parser
class MetaInformation(object):
'''Convenient encapsulation of book metadata'''
def __init__(self, title, author):
self.title = title

View File

@ -13,11 +13,11 @@
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Read metadata from RTF files.
Edit metadata in RTF files.
"""
import re, cStringIO
import re, cStringIO, sys
from libprs500.ebooks.metadata import MetaInformation
from libprs500.ebooks.metadata import MetaInformation, get_parser
title_pat = re.compile(r'\{\\info.*?\{\\title(.*?)(?<!\\)\}', re.DOTALL)
author_pat = re.compile(r'\{\\info.*?\{\\author(.*?)(?<!\\)\}', re.DOTALL)
@ -27,7 +27,7 @@ category_pat = re.compile(r'\{\\info.*?\{\\category(.*?)(?<!\\)\}', re.DOTALL)
def get_document_info(stream):
"""
Extract the \info block from an RTF file.
Return the info block as a stringa and the position in the file at which it
Return the info block as a string and the position in the file at which it
starts.
@param stream: File like object pointing to the RTF file.
"""
@ -81,7 +81,7 @@ def get_metadata(stream):
author = author_match.group(1).strip()
comment_match = comment_pat.search(block)
if comment_match:
title = comment_match.group(1).strip()
comment = comment_match.group(1).strip()
category_match = category_pat.search(block)
if category_match:
category = category_match.group(1).strip()
@ -90,12 +90,67 @@ def get_metadata(stream):
mi.category = category
return mi
def main():
import sys
if len(sys.argv) != 2:
print >> sys.stderr, "Usage:", sys.argv[0], " mybook.rtf"
def set_metadata(stream, options):
'''
Modify/add RTF metadata in stream
@param options: Object with metadata attributes title, author, comment, category
'''
def add_metadata_item(src, name, val):
index = src.rindex('}')
return src[:index] + r'{\ '[:-1] + name + ' ' + val + '}}'
src, pos = get_document_info(stream)
olen = len(src)
base_pat = r'\{\\name(.*?)(?<!\\)\}'
title = options.title
if title != None:
title = title.encode('ascii', 'replace')
pat = re.compile(base_pat.replace('name', 'title'), re.DOTALL)
if pat.search(src):
src = pat.sub(r'{\\title ' + title + r'}', src)
else:
src = add_metadata_item(src, 'title', title)
comment = options.comment
if comment != None:
comment = comment.encode('ascii', 'replace')
pat = re.compile(base_pat.replace('name', 'subject'), re.DOTALL)
if pat.search(src):
src = pat.sub(r'{\\subject ' + comment + r'}', src)
else:
src = add_metadata_item(src, 'subject', comment)
author = options.authors
if author != None:
author = author.encode('ascii', 'replace')
pat = re.compile(base_pat.replace('name', 'author'), re.DOTALL)
if pat.search(src):
src = pat.sub(r'{\\author ' + author + r'}', src)
else:
src = add_metadata_item(src, 'author', author)
category = options.category
if category != None:
category = category.encode('ascii', 'replace')
pat = re.compile(base_pat.replace('name', 'category'), re.DOTALL)
if pat.search(src):
src = pat.sub(r'{\\category ' + category + r'}', src)
else:
src = add_metadata_item(src, 'category', category)
stream.seek(pos + olen)
after = stream.read()
stream.seek(pos)
stream.truncate()
stream.write(src)
stream.write(after)
def main(args=sys.argv):
parser = get_parser('rtf')
options, args = parser.parse_args(args)
if len(args) != 2:
parser.print_help()
sys.exit(1)
print get_metadata(open(sys.argv[1]))
stream = open(args[1], 'r+b')
set_metadata(stream, options)
mi = get_metadata(stream)
return mi
if __name__ == '__main__':
main()