diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index e5e284fb5b..0742e60229 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -378,10 +378,11 @@ def strftime(fmt, t=None): t = time.localtime() early_year = t[0] < 1900 if early_year: + replacement = 1900 if t[0]%4 == 0 else 1901 fmt = fmt.replace('%Y', '_early year hack##') t = list(t) orig_year = t[0] - t[0] = 1900 + t[0] = replacement ans = None if iswindows: if isinstance(fmt, unicode): diff --git a/src/calibre/library/catalog.py b/src/calibre/library/catalog.py index 857b56216a..c0065c24c9 100644 --- a/src/calibre/library/catalog.py +++ b/src/calibre/library/catalog.py @@ -2235,7 +2235,7 @@ class EPUB_MOBI(CatalogPlugin): cmTag['name'] = "author" navStr = '%s | %s' % (self.formatNCXText(book['author'], dest='author'), book['date'].split()[1]) - if 'tags' in book: + if 'tags' in book and len(book['tags']): navStr = self.formatNCXText(navStr + ' | ' + ' · '.join(sorted(book['tags'])), dest='author') cmTag.insert(0, NavigableString(navStr)) navPointVolumeTag.insert(2, cmTag) @@ -3298,10 +3298,10 @@ class EPUB_MOBI(CatalogPlugin): Deprecated HTML returns as HTML via BeautifulSoup() ''' - - # Explode lost CRs to \n\n # Hackish - ignoring sentences ending or beginning in numbers to avoid # confusion with decimal points. + + # Explode lost CRs to \n\n for lost_cr in re.finditer('([a-z])([\.\?!])([A-Z])',comments): comments = comments.replace(lost_cr.group(), '%s%s\n\n%s' % (lost_cr.group(1), @@ -3323,6 +3323,8 @@ class EPUB_MOBI(CatalogPlugin): # Convert solo returns to
comments = re.sub('[\r\n]','
', comments) + # Convert two hypens to emdash + comments = re.sub('--','—',comments) soup = BeautifulSoup(comments) result = BeautifulSoup() diff --git a/src/calibre/utils/date.py b/src/calibre/utils/date.py index 8b26ab02bc..9a433e3a6d 100644 --- a/src/calibre/utils/date.py +++ b/src/calibre/utils/date.py @@ -11,8 +11,21 @@ from datetime import datetime from dateutil.parser import parse from dateutil.tz import tzlocal, tzutc +class SafeLocalTimeZone(tzlocal): + ''' + Assume DST was not in effect for historical dates, if DST + data for the local timezone is not present in the operating system. + ''' + + def _isdst(self, dt): + try: + return tzlocal._isdst(self, dt) + except ValueError: + pass + return False + utc_tz = _utc_tz = tzutc() -local_tz = _local_tz = tzlocal() +local_tz = _local_tz = SafeLocalTimeZone() def parse_date(date_string, assume_utc=False, as_utc=True, default=None): ''' diff --git a/src/odf/element.py b/src/odf/element.py index 9754c251b0..f0938ba53e 100644 --- a/src/odf/element.py +++ b/src/odf/element.py @@ -165,6 +165,18 @@ class Node(xml.dom.Node): oldChild.parentNode = None return oldChild + def __str__(self): + val = [] + for c in self.childNodes: + val.append(str(c)) + return ''.join(val) + + def __unicode__(self): + val = [] + for c in self.childNodes: + val.append(unicode(c)) + return u''.join(val) + defproperty(Node, "firstChild", doc="First child node, or None.") defproperty(Node, "lastChild", doc="Last child node, or None.") @@ -221,6 +233,9 @@ class Text(Childless, Node): self.data = data def __str__(self): + return self.data.encode() + + def __unicode__(self): return self.data def toXml(self,level,f): @@ -452,3 +467,9 @@ class Element(Node): obj = element(check_grammar=False) return self._getElementsByObj(obj,[]) + def isInstanceOf(self, element): + """ This is a check to see if the object is an instance of a type """ + obj = element(check_grammar=False) + return self.qname == obj.qname + + diff --git a/src/odf/grammar.py b/src/odf/grammar.py index f71d72cca3..09ec02cbaa 100644 --- a/src/odf/grammar.py +++ b/src/odf/grammar.py @@ -4670,6 +4670,7 @@ allowed_attributes = { (NUMBERNS,u'boolean-style'):( (NUMBERNS,u'transliteration-language'), (STYLENS,u'name'), + (STYLENS,u'display-name'), (NUMBERNS,u'language'), (NUMBERNS,u'title'), (NUMBERNS,u'country'), @@ -4681,6 +4682,7 @@ allowed_attributes = { (NUMBERNS,u'currency-style'):( (NUMBERNS,u'transliteration-language'), (STYLENS,u'name'), + (STYLENS,u'display-name'), (NUMBERNS,u'language'), (NUMBERNS,u'title'), (NUMBERNS,u'country'), @@ -4698,6 +4700,7 @@ allowed_attributes = { (NUMBERNS,u'date-style'):( (NUMBERNS,u'transliteration-language'), (STYLENS,u'name'), + (STYLENS,u'display-name'), (NUMBERNS,u'language'), (NUMBERNS,u'title'), (NUMBERNS,u'country'), @@ -4753,6 +4756,7 @@ allowed_attributes = { (NUMBERNS,u'number-style'):( (NUMBERNS,u'transliteration-language'), (STYLENS,u'name'), + (STYLENS,u'display-name'), (NUMBERNS,u'language'), (NUMBERNS,u'title'), (NUMBERNS,u'country'), @@ -4765,6 +4769,7 @@ allowed_attributes = { (NUMBERNS,u'percentage-style'):( (NUMBERNS,u'transliteration-language'), (STYLENS,u'name'), + (STYLENS,u'display-name'), (NUMBERNS,u'language'), (NUMBERNS,u'title'), (NUMBERNS,u'country'), @@ -4794,6 +4799,7 @@ allowed_attributes = { (NUMBERNS,u'text-style'):( (NUMBERNS,u'transliteration-language'), (STYLENS,u'name'), + (STYLENS,u'display-name'), (NUMBERNS,u'language'), (NUMBERNS,u'title'), (NUMBERNS,u'country'), @@ -4806,6 +4812,7 @@ allowed_attributes = { (NUMBERNS,u'transliteration-language'), (NUMBERNS,u'transliteration-format'), (STYLENS,u'name'), + (STYLENS,u'display-name'), (NUMBERNS,u'language'), (NUMBERNS,u'title'), (NUMBERNS,u'country'), diff --git a/src/odf/odf2xhtml.py b/src/odf/odf2xhtml.py index b5df80f5d6..912e79cf3c 100644 --- a/src/odf/odf2xhtml.py +++ b/src/odf/odf2xhtml.py @@ -1,17 +1,17 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # Copyright (C) 2006-2007 Søren Roug, European Environment Agency -# +# # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. -# +# # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. -# +# # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -47,7 +47,7 @@ from namespaces import ANIMNS, CHARTNS, CONFIGNS, DCNS, DR3DNS, DRAWNS, FONS, \ # # The real styles are declared in the element. They have a # family referring to the default-styles, and may have a parent style. -# +# # Styles have scope. The same name can be used for both paragraph and # character etc. styles Since CSS2 has no scope we use a prefix. (Not elegant) # In ODF a style can have a parent, these parents can be chained. @@ -376,6 +376,8 @@ class ODF2XHTML(handler.ContentHandler): (OFFICENS, "text"):(self.s_office_text, self.e_office_text), (OFFICENS, "scripts"):(self.s_ignorexml, None), (PRESENTATIONNS, "notes"):(self.s_ignorexml, None), +# (STYLENS, "default-page-layout"):(self.s_style_default_page_layout, self.e_style_page_layout), + (STYLENS, "default-page-layout"):(self.s_ignorexml, None), (STYLENS, "default-style"):(self.s_style_default_style, self.e_style_default_style), (STYLENS, "drawing-page-properties"):(self.s_style_handle_properties, None), (STYLENS, "font-face"):(self.s_style_font_face, None), @@ -834,8 +836,17 @@ class ODF2XHTML(handler.ContentHandler): self.stylestack.append(self.currentstyle) self.styledict[self.currentstyle] = {} + def s_style_default_page_layout(self, tag, attrs): + """ Collect the formatting for the default page layout style. + """ + self.currentstyle = "@page" + self.stylestack.append(self.currentstyle) + self.styledict[self.currentstyle] = {} + def s_style_page_layout(self, tag, attrs): """ Collect the formatting for the page layout style. + This won't work in CSS 2.1, as page identifiers are not allowed. + It is legal in CSS3, but the rest of the application doesn't specify when to use what page layout """ name = attrs[(STYLENS,'name')] name = name.replace(".","_")