mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk
This commit is contained in:
commit
6fd9510f19
@ -424,6 +424,7 @@ def entity_to_unicode(match, exceptions=[], encoding='cp1252'):
|
||||
|
||||
if isosx:
|
||||
fdir = os.path.expanduser('~/.fonts')
|
||||
try:
|
||||
if not os.path.exists(fdir):
|
||||
os.makedirs(fdir)
|
||||
if not os.path.exists(os.path.join(fdir, 'LiberationSans_Regular.ttf')):
|
||||
@ -432,6 +433,9 @@ if isosx:
|
||||
l = {}
|
||||
exec 'from calibre.ebooks.lrf.fonts.liberation.'+font+' import font_data' in l
|
||||
open(os.path.join(fdir, font+'.ttf'), 'wb').write(l['font_data'])
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# Migrate from QSettings based config system
|
||||
from calibre.utils.config import migrate
|
||||
|
@ -898,7 +898,7 @@ def config(defaults=None, config_name='html',
|
||||
metadata('title', ['-t', '--title'], default=None,
|
||||
help=_('Set the title. Default is to autodetect.'))
|
||||
metadata('authors', ['-a', '--authors'], default=None,
|
||||
help=_('The author(s) of the ebook, as a comma separated list.'))
|
||||
help=_('The author(s) of the ebook, as a & separated list.'))
|
||||
metadata('tags', ['--subjects'], default=None,
|
||||
help=_('The subject(s) of this book, as a comma separated list.'))
|
||||
metadata('publisher', ['--publisher'], default=None,
|
||||
@ -994,7 +994,9 @@ def merge_metadata(htmlfile, opf, opts):
|
||||
val = getattr(opts, attr, None)
|
||||
if val is None or val == _('Unknown') or val == [_('Unknown')]:
|
||||
continue
|
||||
if attr in ('authors', 'tags'):
|
||||
if attr =='authors':
|
||||
val = [i.strip() for i in val.split('&') if i.strip()]
|
||||
elif attr == 'tags':
|
||||
val = [i.strip() for i in val.split(',') if i.strip()]
|
||||
setattr(mi, attr, val)
|
||||
|
||||
|
@ -170,7 +170,7 @@ def generate_html(rtfpath, tdir):
|
||||
f.write(res)
|
||||
f.close()
|
||||
try:
|
||||
mi = get_metadata(open(rtfpath, 'rb'))
|
||||
mi = get_metadata(open(rtfpath, 'rb'), 'rtf')
|
||||
except:
|
||||
mi = MetaInformation(None, None)
|
||||
if not mi.title:
|
||||
|
@ -16,9 +16,9 @@
|
||||
<dc:description py:if="mi.comments">${mi.comments}</dc:description>
|
||||
<dc:publisher py:if="mi.publisher">${mi.publisher}</dc:publisher>
|
||||
<dc:identifier opf:scheme="ISBN" py:if="mi.isbn">${mi.isbn}</dc:identifier>
|
||||
<series py:if="mi.series">${mi.series}</series>
|
||||
<series_index py:if="mi.series_index is not None">${mi.series_index}</series_index>
|
||||
<rating py:if="mi.rating is not None">${mi.rating}</rating>
|
||||
<meta py:if="mi.series is not None" name="series" content="${mi.series}"/>
|
||||
<meta py:if="mi.series_index is not None" name="series_index" content="${mi.series_index}"/>
|
||||
<meta py:if="mi.rating is not None" name="rating" content="${mi.rating}"/>
|
||||
<py:for each="tag in mi.tags">
|
||||
<dc:subject py:if="mi.tags is not None">${tag}</dc:subject>
|
||||
</py:for>
|
||||
|
@ -392,8 +392,8 @@ class MetadataField(object):
|
||||
def __set__(self, obj, val):
|
||||
elem = obj.get_metadata_element(self.name)
|
||||
if elem is None:
|
||||
elem = obj.create_metadata_element(self.name, ns='dc' if self.is_dc else 'opf')
|
||||
elem.text = unicode(val)
|
||||
elem = obj.create_metadata_element(self.name, is_dc=self.is_dc)
|
||||
obj.set_text(elem, unicode(val))
|
||||
|
||||
class OPF(object):
|
||||
MIMETYPE = 'application/oebps-package+xml'
|
||||
@ -403,16 +403,18 @@ class OPF(object):
|
||||
'dc' : "http://purl.org/dc/elements/1.1/",
|
||||
'opf' : "http://www.idpf.org/2007/opf",
|
||||
}
|
||||
META = '{%s}meta' % NAMESPACES['opf']
|
||||
xpn = NAMESPACES.copy()
|
||||
xpn.pop(None)
|
||||
xpn['re'] = 'http://exslt.org/regular-expressions'
|
||||
XPath = functools.partial(etree.XPath, namespaces=xpn)
|
||||
CONTENT = XPath('self::*[re:match(name(), "meta$", "i")]/@content')
|
||||
TEXT = XPath('string()')
|
||||
|
||||
|
||||
metadata_path = XPath('descendant::*[re:match(name(), "metadata", "i")]')
|
||||
metadata_elem_path = XPath('descendant::*[re:match(name(), $name, "i")]')
|
||||
series_path = XPath('descendant::*[re:match(name(), "series$", "i")]')
|
||||
metadata_elem_path = XPath('descendant::*[re:match(name(), $name, "i") or (re:match(name(), "^meta$", "i") and re:match(@name, $name, "i"))]')
|
||||
series_path = XPath('descendant::*[re:match(name(), "series$", "i") or (re:match(name(), "^meta$", "i") and re:match(@name, "series$", "i"))]')
|
||||
authors_path = XPath('descendant::*[re:match(name(), "creator", "i") and (@role="aut" or @opf:role="aut" or (not(@role) and not(@opf:role)))]')
|
||||
bkp_path = XPath('descendant::*[re:match(name(), "contributor", "i") and (@role="bkp" or @opf:role="bkp")]')
|
||||
tags_path = XPath('descendant::*[re:match(name(), "subject", "i")]')
|
||||
@ -497,7 +499,13 @@ class OPF(object):
|
||||
|
||||
|
||||
def get_text(self, elem):
|
||||
return u''.join(self.TEXT(elem))
|
||||
return u''.join(self.CONTENT(elem) or self.TEXT(elem))
|
||||
|
||||
def set_text(self, elem, content):
|
||||
if elem.tag == self.META:
|
||||
elem.attib['content'] = content
|
||||
else:
|
||||
elem.text = content
|
||||
|
||||
def itermanifest(self):
|
||||
return self.manifest_path(self.root)
|
||||
@ -611,9 +619,9 @@ class OPF(object):
|
||||
for elem in remove:
|
||||
self.metadata.remove(elem)
|
||||
for author in val:
|
||||
elem = self.create_metadata_element('creator', ns='dc',
|
||||
attrib={'{%s}role'%self.NAMESPACES['opf']:'aut'})
|
||||
elem.text = author
|
||||
attrib = {'{%s}role'%self.NAMESPACES['opf']: 'aut'}
|
||||
elem = self.create_metadata_element('creator', attrib=attrib)
|
||||
self.set_text(elem, author)
|
||||
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
@ -650,8 +658,8 @@ class OPF(object):
|
||||
for tag in list(self.tags_path(self.metadata)):
|
||||
self.metadata.remove(tag)
|
||||
for tag in val:
|
||||
elem = self.create_metadata_element('subject', ns='dc')
|
||||
elem.text = unicode(tag)
|
||||
elem = self.create_metadata_element('subject')
|
||||
self.set_text(elem, unicode(tag))
|
||||
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
@ -660,14 +668,15 @@ class OPF(object):
|
||||
|
||||
def fget(self):
|
||||
for match in self.isbn_path(self.metadata):
|
||||
return match.text if match.text else None
|
||||
return self.get_text(match) or None
|
||||
|
||||
def fset(self, val):
|
||||
matches = self.isbn_path(self.metadata)
|
||||
if not matches:
|
||||
matches = [self.create_metadata_element('identifier', ns='dc',
|
||||
attrib={'{%s}scheme'%self.NAMESPACES['opf']:'ISBN'})]
|
||||
matches[0].text = unicode(val)
|
||||
attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'ISBN'}
|
||||
matches = [self.create_metadata_element('identifier',
|
||||
attrib=attrib)]
|
||||
self.set_text(matches[0], unicode(val))
|
||||
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
@ -676,14 +685,15 @@ class OPF(object):
|
||||
|
||||
def fget(self):
|
||||
for match in self.application_id_path(self.metadata):
|
||||
return match.text if match.text else None
|
||||
return self.get_text(match) or None
|
||||
|
||||
def fset(self, val):
|
||||
matches = self.application_id_path(self.metadata)
|
||||
if not matches:
|
||||
matches = [self.create_metadata_element('identifier', ns='dc',
|
||||
attrib={'{%s}scheme'%self.NAMESPACES['opf']:'calibre'})]
|
||||
matches[0].text = unicode(val)
|
||||
attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'calibre'}
|
||||
matches = [self.create_metadata_element('identifier',
|
||||
attrib=attrib)]
|
||||
self.set_text(matches[0], unicode(val))
|
||||
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
@ -693,13 +703,13 @@ class OPF(object):
|
||||
|
||||
def fget(self):
|
||||
for match in self.series_path(self.metadata):
|
||||
return match.text if match.text else None
|
||||
return self.get_text(match) or None
|
||||
|
||||
def fset(self, val):
|
||||
matches = self.series_path(self.metadata)
|
||||
if not matches:
|
||||
matches = [self.create_metadata_element('series')]
|
||||
matches[0].text = unicode(val)
|
||||
matches = [self.create_metadata_element('series', is_dc=False)]
|
||||
self.set_text(matches[0], unicode(val))
|
||||
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
@ -710,14 +720,15 @@ class OPF(object):
|
||||
|
||||
def fget(self):
|
||||
for match in self.bkp_path(self.metadata):
|
||||
return match.text if match.text else None
|
||||
return self.get_text(match) or None
|
||||
|
||||
def fset(self, val):
|
||||
matches = self.bkp_path(self.metadata)
|
||||
if not matches:
|
||||
matches = [self.create_metadata_element('contributor', ns='dc',
|
||||
attrib={'{%s}role'%self.NAMESPACES['opf']:'bkp'})]
|
||||
matches[0].text = unicode(val)
|
||||
attrib = {'{%s}role'%self.NAMESPACES['opf']: 'bkp'}
|
||||
matches = [self.create_metadata_element('contributor',
|
||||
attrib=attrib)]
|
||||
self.set_text(matches[0], unicode(val))
|
||||
return property(fget=fget, fset=fset)
|
||||
|
||||
|
||||
@ -783,9 +794,15 @@ class OPF(object):
|
||||
if matches:
|
||||
return matches[-1]
|
||||
|
||||
def create_metadata_element(self, name, attrib=None, ns='opf'):
|
||||
elem = etree.SubElement(self.metadata, '{%s}%s'%(self.NAMESPACES[ns], name),
|
||||
attrib=attrib, nsmap=self.NAMESPACES)
|
||||
def create_metadata_element(self, name, attrib=None, is_dc=True):
|
||||
if is_dc:
|
||||
name = '{%s}%s' % (self.NAMESPACES['dc'], name)
|
||||
else:
|
||||
attrib = attrib or {}
|
||||
attrib['name'] = name
|
||||
name = '{%s}%s' % (self.NAMESPACES['opf'], 'meta')
|
||||
elem = etree.SubElement(self.metadata, name, attrib=attrib,
|
||||
nsmap=self.NAMESPACES)
|
||||
elem.tail = '\n'
|
||||
return elem
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
# #
|
||||
# #
|
||||
#########################################################################
|
||||
import sys, os
|
||||
import sys, os, shutil
|
||||
|
||||
class Copy:
|
||||
"""Copy each changed file to a directory for debugging purposes"""
|
||||
__dir = ""
|
||||
@ -64,25 +65,7 @@ class Copy:
|
||||
of cp. Otherwise, use a safe python method.
|
||||
"""
|
||||
write_file = os.path.join(Copy.__dir,new_file)
|
||||
platform = sys.platform
|
||||
if platform[:5] == 'linux':
|
||||
command = 'cp %(file)s %(write_file)s' % vars()
|
||||
os.system(command)
|
||||
else:
|
||||
read_obj = open(file,'r')
|
||||
write_obj = open(write_file, 'w')
|
||||
line = "dummy"
|
||||
while line:
|
||||
line = read_obj.read(1000)
|
||||
write_obj.write(line )
|
||||
read_obj.close()
|
||||
write_obj.close()
|
||||
shutil.copyfile(file, write_file)
|
||||
|
||||
def rename(self, source, dest):
|
||||
read_obj = open(source, 'r')
|
||||
write_obj = open(dest, 'w')
|
||||
line = 1
|
||||
while line:
|
||||
line = read_obj.readline()
|
||||
write_obj.write(line)
|
||||
read_obj.close()
|
||||
write_obj.close()
|
||||
shutil.copyfile(source, dest)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -2060,6 +2060,8 @@ allowed_children = {
|
||||
),
|
||||
(TEXTNS,u'chapter') : (
|
||||
),
|
||||
(TEXTNS,u'character-count') : (
|
||||
),
|
||||
(TEXTNS,u'conditional-text') : (
|
||||
),
|
||||
(TEXTNS,u'creation-date') : (
|
||||
@ -2294,6 +2296,8 @@ allowed_children = {
|
||||
(TEXTNS,u'illustration-index-entry-template'),
|
||||
(TEXTNS,u'index-title-template'),
|
||||
),
|
||||
(TEXTNS,u'image-count') : (
|
||||
),
|
||||
# allowed_children
|
||||
(TEXTNS,u'index-body') : (
|
||||
(DR3DNS,u'scene'),
|
||||
@ -2661,6 +2665,8 @@ allowed_children = {
|
||||
),
|
||||
(TEXTNS,u'page') : (
|
||||
),
|
||||
(TEXTNS,u'page-count') : (
|
||||
),
|
||||
(TEXTNS,u'page-continuation') : (
|
||||
),
|
||||
(TEXTNS,u'page-number') : (
|
||||
@ -2672,6 +2678,8 @@ allowed_children = {
|
||||
),
|
||||
(TEXTNS,u'page-variable-set') : (
|
||||
),
|
||||
(TEXTNS,u'paragraph-count') : (
|
||||
),
|
||||
(TEXTNS,u'placeholder') : (
|
||||
),
|
||||
(TEXTNS,u'print-date') : (
|
||||
@ -2686,6 +2694,8 @@ allowed_children = {
|
||||
),
|
||||
(TEXTNS,u'reference-mark-start') : (
|
||||
),
|
||||
(TEXTNS,u'reference-ref') : (
|
||||
),
|
||||
(TEXTNS,u'ruby') : (
|
||||
(TEXTNS,u'ruby-base'),
|
||||
(TEXTNS,u'ruby-text'),
|
||||
@ -3035,6 +3045,8 @@ allowed_children = {
|
||||
),
|
||||
(TEXTNS,u'tab') : (
|
||||
),
|
||||
(TEXTNS,u'table-count') : (
|
||||
),
|
||||
(TEXTNS,u'table-formula') : (
|
||||
),
|
||||
(TEXTNS,u'table-index') : (
|
||||
@ -3132,6 +3144,8 @@ allowed_children = {
|
||||
),
|
||||
(TEXTNS,u'variable-set') : (
|
||||
),
|
||||
(TEXTNS,u'word-count') : (
|
||||
),
|
||||
}
|
||||
|
||||
struct_elements = ( # Unused?
|
||||
@ -3182,6 +3196,7 @@ allows_text = (
|
||||
(PRESENTATIONNS,u'footer-decl'),
|
||||
(PRESENTATIONNS,u'header-decl'),
|
||||
(SVGNS,u'desc'),
|
||||
(SVGNS,u'title'),
|
||||
(TEXTNS,u'a'),
|
||||
(TEXTNS,u'author-initials'),
|
||||
(TEXTNS,u'author-name'),
|
||||
@ -3403,7 +3418,6 @@ required_attributes = {
|
||||
(DRAWNS,u'glue-point'): (
|
||||
(SVGNS,u'y'),
|
||||
(SVGNS,u'x'),
|
||||
(DRAWNS,u'align'),
|
||||
(DRAWNS,u'id'),
|
||||
),
|
||||
(DRAWNS,u'gradient'): (
|
||||
@ -4297,35 +4311,47 @@ allowed_attributes = {
|
||||
(ANIMNS,u'value'),
|
||||
),
|
||||
(ANIMNS,u'seq'):(
|
||||
(PRESENTATIONNS,u'node-type'),
|
||||
(SMILNS,u'decelerate'),
|
||||
(SMILNS,u'begin'),
|
||||
(SMILNS,u'end'),
|
||||
(PRESENTATIONNS,u'group-id'),
|
||||
(SMILNS,u'accelerate'),
|
||||
(SMILNS,u'repeatDur'),
|
||||
(SMILNS,u'endsync'),
|
||||
(SMILNS,u'restartDefault'),
|
||||
(PRESENTATIONNS,u'preset-class'),
|
||||
(SMILNS,u'fillDefault'),
|
||||
(PRESENTATIONNS,u'preset-id'),
|
||||
(SMILNS,u'autoReverse'),
|
||||
(PRESENTATIONNS,u'preset-sub-type'),
|
||||
(SMILNS,u'repeatCount'),
|
||||
(SMILNS,u'dur'),
|
||||
(SMILNS,u'fill'),
|
||||
(ANIMNS,u'id'),
|
||||
(SMILNS,u'restart'),
|
||||
(PRESENTATIONNS,u'group-id'),
|
||||
(PRESENTATIONNS,u'master-element'),
|
||||
(PRESENTATIONNS,u'node-type'),
|
||||
(PRESENTATIONNS,u'preset-class'),
|
||||
(PRESENTATIONNS,u'preset-id'),
|
||||
(PRESENTATIONNS,u'preset-sub-type'),
|
||||
(SMILNS,u'accelerate'),
|
||||
(SMILNS,u'autoReverse'),
|
||||
(SMILNS,u'begin'),
|
||||
(SMILNS,u'decelerate'),
|
||||
(SMILNS,u'dur'),
|
||||
(SMILNS,u'end'),
|
||||
(SMILNS,u'endsync'),
|
||||
(SMILNS,u'fill'),
|
||||
(SMILNS,u'fillDefault'),
|
||||
(SMILNS,u'repeatCount'),
|
||||
(SMILNS,u'repeatDur'),
|
||||
(SMILNS,u'restart'),
|
||||
(SMILNS,u'restartDefault'),
|
||||
),
|
||||
(ANIMNS,u'set'):(
|
||||
(ANIMNS,u'sub-item'),
|
||||
(SMILNS,u'accelerate'),
|
||||
(SMILNS,u'accumulate'),
|
||||
(SMILNS,u'autoReverse'),
|
||||
(SMILNS,u'additive'),
|
||||
(SMILNS,u'attributeName'),
|
||||
(SMILNS,u'to'),
|
||||
(ANIMNS,u'sub-item'),
|
||||
(SMILNS,u'targetElement'),
|
||||
(SMILNS,u'accumulate'),
|
||||
(SMILNS,u'begin'),
|
||||
(SMILNS,u'decelerate'),
|
||||
(SMILNS,u'dur'),
|
||||
(SMILNS,u'end'),
|
||||
(SMILNS,u'fill'),
|
||||
(SMILNS,u'fillDefault'),
|
||||
(SMILNS,u'repeatCount'),
|
||||
(SMILNS,u'repeatDur'),
|
||||
(SMILNS,u'restart'),
|
||||
(SMILNS,u'restartDefault'),
|
||||
(SMILNS,u'targetElement'),
|
||||
(SMILNS,u'to'),
|
||||
|
||||
),
|
||||
(ANIMNS,u'transitionFilter'):(
|
||||
(SMILNS,u'direction'),
|
||||
@ -5789,6 +5815,8 @@ allowed_attributes = {
|
||||
(MANIFESTNS,'salt'),
|
||||
(MANIFESTNS,'iteration-count'),
|
||||
),
|
||||
(MANIFESTNS,u'manifest'):(
|
||||
),
|
||||
# allowed_attributes
|
||||
(METANS,u'auto-reload'):(
|
||||
(METANS,u'delay'),
|
||||
@ -6096,7 +6124,7 @@ allowed_attributes = {
|
||||
(CHARTNS,u'gap-width'),
|
||||
(CHARTNS,u'interpolation'),
|
||||
(CHARTNS,u'interval-major'),
|
||||
(CHARTNS,u'interval-minor'),
|
||||
(CHARTNS,u'interval-minor-divisor'),
|
||||
(CHARTNS,u'japanese-candle-stick'),
|
||||
(CHARTNS,u'label-arrangement'),
|
||||
(CHARTNS,u'lines'),
|
||||
@ -6117,6 +6145,7 @@ allowed_attributes = {
|
||||
(CHARTNS,u'spline-resolution'),
|
||||
(CHARTNS,u'stacked'),
|
||||
(CHARTNS,u'symbol-height'),
|
||||
(CHARTNS,u'symbol-name'),
|
||||
(CHARTNS,u'symbol-type'),
|
||||
(CHARTNS,u'symbol-width'),
|
||||
(CHARTNS,u'text-overlap'),
|
||||
@ -6236,11 +6265,9 @@ allowed_attributes = {
|
||||
),
|
||||
(STYLENS,u'footer'):(
|
||||
(STYLENS,u'display'),
|
||||
(STYLENS,u'dynamic-spacing'),
|
||||
),
|
||||
(STYLENS,u'footer-left'):(
|
||||
(STYLENS,u'display'),
|
||||
(STYLENS,u'dynamic-spacing'),
|
||||
),
|
||||
(STYLENS,u'footer-style'):(
|
||||
),
|
||||
@ -6437,7 +6464,6 @@ allowed_attributes = {
|
||||
),
|
||||
(STYLENS,u'header'):(
|
||||
(STYLENS,u'display'),
|
||||
(STYLENS,u'dynamic-spacing'),
|
||||
),
|
||||
(STYLENS,u'header-footer-properties'): (
|
||||
(FONS,u'background-color'),
|
||||
@ -6468,7 +6494,6 @@ allowed_attributes = {
|
||||
),
|
||||
(STYLENS,u'header-left'):(
|
||||
(STYLENS,u'display'),
|
||||
(STYLENS,u'dynamic-spacing'),
|
||||
),
|
||||
(STYLENS,u'header-style'):(
|
||||
),
|
||||
@ -6480,6 +6505,7 @@ allowed_attributes = {
|
||||
(STYLENS,u'font-name'),
|
||||
(STYLENS,u'vertical-pos'),
|
||||
(STYLENS,u'vertical-rel'),
|
||||
(SVGNS,u'y'),
|
||||
(TEXTNS,u'min-label-distance'),
|
||||
(TEXTNS,u'min-label-width'),
|
||||
(TEXTNS,u'space-before'),
|
||||
@ -6534,12 +6560,10 @@ allowed_attributes = {
|
||||
(STYLENS,u'layout-grid-print'),
|
||||
(STYLENS,u'layout-grid-ruby-below'),
|
||||
(STYLENS,u'layout-grid-ruby-height'),
|
||||
(STYLENS,u'name'),
|
||||
(STYLENS,u'num-format'),
|
||||
(STYLENS,u'num-letter-sync'),
|
||||
(STYLENS,u'num-prefix'),
|
||||
(STYLENS,u'num-suffix'),
|
||||
(STYLENS,u'page-usage'),
|
||||
(STYLENS,u'paper-tray-name'),
|
||||
(STYLENS,u'print'),
|
||||
(STYLENS,u'print-orientation'),
|
||||
@ -7156,7 +7180,6 @@ allowed_attributes = {
|
||||
(TABLENS,u'cell-range-address'),
|
||||
),
|
||||
(TABLENS,u'null-date'):(
|
||||
(TABLENS,u'date-value-type'),
|
||||
(TABLENS,u'value-type'),
|
||||
),
|
||||
(TABLENS,u'odd-columns'):(
|
||||
|
@ -39,15 +39,3 @@ def Algorithm(**args):
|
||||
def KeyDerivation(**args):
|
||||
return Element(qname = (MANIFESTNS,'key-derivation'), **args)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import cStringIO
|
||||
xml=cStringIO.StringIO()
|
||||
m = Manifest()
|
||||
f = FileEntry(mediatype="text/xml", fullpath="content.xml")
|
||||
m.addElement(f)
|
||||
|
||||
m.toXml(0,xml)
|
||||
print xml.getvalue()
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
TOOLSVERSION = u"ODFPY/0.8.1dev"
|
||||
TOOLSVERSION = u"ODFPY/0.8.2dev"
|
||||
|
||||
ANIMNS = u"urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
|
||||
DBNS = u"urn:oasis:names:tc:opendocument:xmlns:database:1.0"
|
||||
@ -49,7 +49,7 @@ TABLENS = u"urn:oasis:names:tc:opendocument:xmlns:table:1.0"
|
||||
TEXTNS = u"urn:oasis:names:tc:opendocument:xmlns:text:1.0"
|
||||
XFORMSNS = u"http://www.w3.org/2002/xforms"
|
||||
XLINKNS = u"http://www.w3.org/1999/xlink"
|
||||
XMLNS = "http://www.w3.org/XML/1998/namespace"
|
||||
XMLNS = u"http://www.w3.org/XML/1998/namespace"
|
||||
|
||||
|
||||
nsdict = {
|
||||
|
@ -64,6 +64,12 @@ odmimetypes = {
|
||||
'application/vnd.oasis.opendocument.text-web': '.oth',
|
||||
}
|
||||
|
||||
class OpaqueObject:
|
||||
def __init__(self, filename, mediatype, content=None):
|
||||
self.mediatype = mediatype
|
||||
self.filename = filename
|
||||
self.content = content
|
||||
|
||||
class OpenDocument:
|
||||
""" A class to hold the content of an OpenDocument document
|
||||
Use the xml method to write the XML
|
||||
@ -76,6 +82,7 @@ class OpenDocument:
|
||||
def __init__(self, mimetype, add_generator=True):
|
||||
self.mimetype = mimetype
|
||||
self.childobjects = []
|
||||
self._extra = []
|
||||
self.folder = "" # Always empty for toplevel documents
|
||||
self.topnode = Document(mimetype=self.mimetype)
|
||||
self.topnode.ownerDocument = self
|
||||
@ -303,12 +310,15 @@ class OpenDocument:
|
||||
else:
|
||||
self.thumbnail = filecontent
|
||||
|
||||
def addObject(self, document):
|
||||
def addObject(self, document, objectname=None):
|
||||
""" Add an object. The object must be an OpenDocument class
|
||||
The return value will be the folder in the zipfile the object is stored in
|
||||
"""
|
||||
self.childobjects.append(document)
|
||||
if objectname is None:
|
||||
document.folder = "%s/Object %d" % (self.folder, len(self.childobjects))
|
||||
else:
|
||||
document.folder = objectname
|
||||
return ".%s" % document.folder
|
||||
|
||||
def _savePictures(self, object, folder):
|
||||
@ -382,6 +392,14 @@ class OpenDocument:
|
||||
zi.external_attr = UNIXPERMS
|
||||
self._z.writestr(zi, self.thumbnail)
|
||||
|
||||
# Write any extra files
|
||||
for op in self._extra:
|
||||
self.manifest.addElement(manifest.FileEntry(fullpath=op.filename, mediatype=op.mediatype))
|
||||
zi = zipfile.ZipInfo(op.filename.encode('utf-8'), self._now)
|
||||
zi.compress_type = zipfile.ZIP_DEFLATED
|
||||
zi.external_attr = UNIXPERMS
|
||||
if op.content is not None:
|
||||
self._z.writestr(zi, op.content)
|
||||
# Write manifest
|
||||
zi = zipfile.ZipInfo("META-INF/manifest.xml", self._now)
|
||||
zi.compress_type = zipfile.ZIP_DEFLATED
|
||||
@ -528,15 +546,20 @@ def load(odffile):
|
||||
parser.parse(inpsrc)
|
||||
del doc._parsing
|
||||
except KeyError, v: pass
|
||||
# Add the thumbnail here
|
||||
# Add the images here
|
||||
# FIXME: Add subobjects correctly here
|
||||
for mentry,mvalue in manifest.items():
|
||||
if mentry[:9] == "Pictures/" and len(mentry) > 9:
|
||||
doc.addPicture(mvalue['full-path'], mvalue['media-type'], z.read(mentry))
|
||||
elif mentry == "Thumbnails/thumbnail.png":
|
||||
doc.addThumbnail(z.read(mentry))
|
||||
elif mentry in ('settings.xml', 'meta.xml', 'content.xml', 'styles.xml'):
|
||||
pass
|
||||
else:
|
||||
pass # Add the SUN junk here to the struct somewhere
|
||||
if mvalue['full-path'][-1] == '/':
|
||||
doc._extra.append(OpaqueObject(mvalue['full-path'], mvalue['media-type'], None))
|
||||
else:
|
||||
doc._extra.append(OpaqueObject(mvalue['full-path'], mvalue['media-type'], z.read(mentry)))
|
||||
# Add the SUN junk here to the struct somewhere
|
||||
# It is cached data, so it can be out-of-date
|
||||
z.close()
|
||||
b = doc.getElementsByType(Body)
|
||||
|
@ -231,6 +231,19 @@ class ODFContentParser(xml.sax.saxutils.XMLGenerator):
|
||||
self._callback_func = callback_func
|
||||
xml.sax.saxutils.XMLGenerator.__init__(self, out, encoding)
|
||||
|
||||
def _qname(self, name):
|
||||
"""Builds a qualified name from a (ns_url, localname) pair"""
|
||||
if name[0]:
|
||||
if name[0] == u'http://www.w3.org/XML/1998/namespace':
|
||||
return u'xml' + ":" + name[1]
|
||||
# The name is in a non-empty namespace
|
||||
prefix = self._current_context[name[0]]
|
||||
if prefix:
|
||||
# If it is not the default namespace, prepend the prefix
|
||||
return prefix + ":" + name[1]
|
||||
# Return the unqualified name
|
||||
return name[1]
|
||||
|
||||
def startElementNS(self, name, qname, attrs):
|
||||
if name == (TEXTNS, u'user-field-decl'):
|
||||
field_name = attrs.get((TEXTNS, u'name'))
|
||||
|
Loading…
x
Reference in New Issue
Block a user