Hello community,
here is the log from the commit of package python-xlrd for openSUSE:Factory checked in at 2015-11-04 15:32:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-xlrd (Old)
and /work/SRC/openSUSE:Factory/.python-xlrd.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-xlrd"
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-xlrd/python-xlrd.changes 2013-05-02 11:45:27.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-xlrd.new/python-xlrd.changes 2015-11-04 15:32:54.000000000 +0100
@@ -1,0 +2,6 @@
+Thu Oct 29 17:54:20 UTC 2015 - scorot@free.fr
+
+- Update to 0.9.4
+ * No changelog available
+
+-------------------------------------------------------------------
Old:
----
xlrd-0.9.2.tar.gz
New:
----
xlrd-0.9.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-xlrd.spec ++++++
--- /var/tmp/diff_new_pack.4sdQlS/_old 2015-11-04 15:32:55.000000000 +0100
+++ /var/tmp/diff_new_pack.4sdQlS/_new 2015-11-04 15:32:55.000000000 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-xlrd
#
-# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
Name: python-xlrd
-Version: 0.9.2
+Version: 0.9.4
Release: 0
Url: http://www.lexicon.net/sjmachin/xlrd.htm
Summary: Library for Developers to Extract Data From Microsoft Excel Spreadsheet Files
++++++ xlrd-0.9.2.tar.gz -> xlrd-0.9.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/PKG-INFO new/xlrd-0.9.4/PKG-INFO
--- old/xlrd-0.9.2/PKG-INFO 2013-04-09 21:36:10.000000000 +0200
+++ new/xlrd-0.9.4/PKG-INFO 2015-07-15 08:21:41.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: xlrd
-Version: 0.9.2
+Version: 0.9.4
Summary: Library for developers to extract data from Microsoft Excel (tm) spreadsheet files
Home-page: http://www.python-excel.org/
Author: John Machin
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/scripts/runxlrd.py new/xlrd-0.9.4/scripts/runxlrd.py
--- old/xlrd-0.9.2/scripts/runxlrd.py 2013-04-05 00:36:57.000000000 +0200
+++ new/xlrd-0.9.4/scripts/runxlrd.py 2015-07-15 08:12:19.000000000 +0200
@@ -89,9 +89,8 @@
if cty == xlrd.XL_CELL_DATE:
try:
showval = xlrd.xldate_as_tuple(cval, dmode)
- except xlrd.XLDateError:
- e1, e2 = sys.exc_info()[:2]
- showval = "%s:%s" % (e1.__name__, e2)
+ except xlrd.XLDateError as e:
+ showval = "%s:%s" % (type(e).__name__, e)
cty = xlrd.XL_CELL_ERROR
elif cty == xlrd.XL_CELL_ERROR:
showval = xlrd.error_text_from_code.get(cval, '' % cval)
@@ -335,17 +334,15 @@
t1 = time.time()
if not options.suppress_timing:
print("Open took %.2f seconds" % (t1-t0,))
- except xlrd.XLRDError:
- e0, e1 = sys.exc_info()[:2]
- print("*** Open failed: %s: %s" % (e0.__name__, e1))
+ except xlrd.XLRDError as e:
+ print("*** Open failed: %s: %s" % (type(e).__name__, e))
continue
except KeyboardInterrupt:
print("*** KeyboardInterrupt ***")
traceback.print_exc(file=sys.stdout)
sys.exit(1)
- except:
- e0, e1 = sys.exc_info()[:2]
- print("*** Open failed: %s: %s" % (e0.__name__, e1))
+ except BaseException as e:
+ print("*** Open failed: %s: %s" % (type(e).__name__, e))
traceback.print_exc(file=sys.stdout)
continue
t0 = time.time()
Files old/xlrd-0.9.2/tests/apachepoi_49609.xlsx and new/xlrd-0.9.4/tests/apachepoi_49609.xlsx differ
Files old/xlrd-0.9.2/tests/merged_cells.xlsx and new/xlrd-0.9.4/tests/merged_cells.xlsx differ
Files old/xlrd-0.9.2/tests/reveng1.xlsx and new/xlrd-0.9.4/tests/reveng1.xlsx differ
Files old/xlrd-0.9.2/tests/self_evaluation_report_2014-05-19.xlsx and new/xlrd-0.9.4/tests/self_evaluation_report_2014-05-19.xlsx differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/tests/test_cell.py new/xlrd-0.9.4/tests/test_cell.py
--- old/xlrd-0.9.2/tests/test_cell.py 2013-04-05 00:36:57.000000000 +0200
+++ new/xlrd-0.9.4/tests/test_cell.py 2014-01-25 10:49:12.000000000 +0100
@@ -39,3 +39,26 @@
row_lo, row_hi, col_lo, col_hi = sheet3.merged_cells[0]
self.assertEqual(sheet3.cell(row_lo, col_lo).value, 'MERGED')
self.assertEqual((row_lo, row_hi, col_lo, col_hi), (3, 7, 2, 5))
+
+ def test_merged_cells_xlsx(self):
+ book = xlrd.open_workbook(from_this_dir('merged_cells.xlsx'))
+
+ sheet1 = book.sheet_by_name('Sheet1')
+ expected = []
+ got = sheet1.merged_cells
+ self.assertEqual(expected, got)
+
+ sheet2 = book.sheet_by_name('Sheet2')
+ expected = [(0, 1, 0, 2)]
+ got = sheet2.merged_cells
+ self.assertEqual(expected, got)
+
+ sheet3 = book.sheet_by_name('Sheet3')
+ expected = [(0, 1, 0, 2), (0, 1, 2, 4), (1, 4, 0, 2), (1, 9, 2, 4)]
+ got = sheet3.merged_cells
+ self.assertEqual(expected, got)
+
+ sheet4 = book.sheet_by_name('Sheet4')
+ expected = [(0, 1, 0, 2), (2, 20, 0, 1), (1, 6, 2, 5)]
+ got = sheet4.merged_cells
+ self.assertEqual(expected, got)
Files old/xlrd-0.9.2/tests/test_comments_excel.xlsx and new/xlrd-0.9.4/tests/test_comments_excel.xlsx differ
Files old/xlrd-0.9.2/tests/test_comments_gdocs.xlsx and new/xlrd-0.9.4/tests/test_comments_gdocs.xlsx differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/tests/test_sheet.py new/xlrd-0.9.4/tests/test_sheet.py
--- old/xlrd-0.9.2/tests/test_sheet.py 2013-04-05 00:36:57.000000000 +0200
+++ new/xlrd-0.9.4/tests/test_sheet.py 2015-07-15 08:11:03.000000000 +0200
@@ -2,8 +2,9 @@
from unittest import TestCase
-import sys
import os
+import sys
+import types
import unittest
import xlrd
@@ -92,6 +93,12 @@
row = sheet.row(0)
self.assertEqual(len(row), NCOLS)
+ def test_get_rows(self):
+ sheet = self.book.sheet_by_index(SHEETINDEX)
+ rows = sheet.get_rows()
+ self.assertTrue(isinstance(rows, types.GeneratorType), True)
+ self.assertEqual(len(list(rows)), sheet.nrows)
+
def test_col_slice(self):
sheet = self.book.sheet_by_index(SHEETINDEX)
self.check_col_slice(sheet.col_slice)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/tests/test_xldate_to_datetime.py new/xlrd-0.9.4/tests/test_xldate_to_datetime.py
--- old/xlrd-0.9.2/tests/test_xldate_to_datetime.py 1970-01-01 01:00:00.000000000 +0100
+++ new/xlrd-0.9.4/tests/test_xldate_to_datetime.py 2014-04-07 16:40:04.000000000 +0200
@@ -0,0 +1,164 @@
+###############################################################################
+#
+# Tests for the xlrd xldate.xldate_as_datetime() function.
+#
+
+import unittest
+from datetime import datetime
+from xlrd import xldate
+
+not_1904 = False
+is_1904 = True
+
+
+class TestConvertToDateTime(unittest.TestCase):
+ """
+ Testcases to test the _xldate_to_datetime() function against dates
+ extracted from Excel files, with 1900/1904 epochs.
+
+ """
+
+ def test_dates_and_times_1900_epoch(self):
+ """
+ Test the _xldate_to_datetime() function for dates and times in
+ the Excel standard 1900 epoch.
+
+ """
+ # Test Excel dates strings and corresponding serial date numbers taken
+ # from an Excel file.
+ excel_dates = [
+ # Excel's 0.0 date in the 1900 epoch is 1 day before 1900.
+ ('1899-12-31T00:00:00.000', 0),
+
+ # Date/time before the false Excel 1900 leapday.
+ ('1900-02-28T02:11:11.986', 59.09111094906),
+
+ # Date/time after the false Excel 1900 leapday.
+ ('1900-03-01T05:46:44.068', 61.24078782403),
+
+ # Random date/times in Excel's 0-9999.9999+ range.
+ ('1982-08-25T00:15:20.213', 30188.010650613425),
+ ('2065-04-19T00:16:48.290', 60376.011670023145),
+ ('3222-06-11T03:08:08.251', 483014.13065105322),
+ ('4379-08-03T06:14:48.580', 905652.26028449077),
+ ('5949-12-30T12:59:54.263', 1479232.5416002662),
+
+ # End of Excel's date range.
+ ('9999-12-31T23:59:59.000', 2958465.999988426),
+ ]
+
+ # Convert the Excel date strings to datetime objects and compare
+ # against the dateitme return value of xldate.xldate_as_datetime().
+ for excel_date in excel_dates:
+ exp = datetime.strptime(excel_date[0], "%Y-%m-%dT%H:%M:%S.%f")
+ got = xldate.xldate_as_datetime(excel_date[1], not_1904)
+
+ self.assertEqual(got, exp)
+
+ def test_dates_only_1900_epoch(self):
+ """
+ Test the _xldate_to_datetime() function for dates in the Excel
+ standard 1900 epoch.
+
+ """
+ # Test Excel dates strings and corresponding serial date numbers taken
+ # from an Excel file.
+ excel_dates = [
+ # Excel's day 0 in the 1900 epoch is 1 day before 1900.
+ ('1899-12-31', 0),
+
+ # Excel's day 1 in the 1900 epoch.
+ ('1900-01-01', 1),
+
+ # Date/time before the false Excel 1900 leapday.
+ ('1900-02-28', 59),
+
+ # Date/time after the false Excel 1900 leapday.
+ ('1900-03-01', 61),
+
+ # Random date/times in Excel's 0-9999.9999+ range.
+ ('1902-09-27', 1001),
+ ('1999-12-31', 36525),
+ ('2000-01-01', 36526),
+ ('4000-12-31', 767376),
+ ('4321-01-01', 884254),
+ ('9999-01-01', 2958101),
+
+ # End of Excel's date range.
+ ('9999-12-31', 2958465),
+ ]
+
+ # Convert the Excel date strings to datetime objects and compare
+ # against the dateitme return value of xldate.xldate_as_datetime().
+ for excel_date in excel_dates:
+ exp = datetime.strptime(excel_date[0], "%Y-%m-%d")
+ got = xldate.xldate_as_datetime(excel_date[1], not_1904)
+
+ self.assertEqual(got, exp)
+
+ def test_dates_only_1904_epoch(self):
+ """
+ Test the _xldate_to_datetime() function for dates in the Excel
+ Mac/1904 epoch.
+
+ """
+ # Test Excel dates strings and corresponding serial date numbers taken
+ # from an Excel file.
+ excel_dates = [
+ # Excel's day 0 in the 1904 epoch.
+ ('1904-01-01', 0),
+
+ # Random date/times in Excel's 0-9999.9999+ range.
+ ('1904-01-31', 30),
+ ('1904-08-31', 243),
+ ('1999-02-28', 34757),
+ ('1999-12-31', 35063),
+ ('2000-01-01', 35064),
+ ('2400-12-31', 181526),
+ ('4000-01-01', 765549),
+ ('9999-01-01', 2956639),
+
+ # End of Excel's date range.
+ ('9999-12-31', 2957003),
+ ]
+
+ # Convert the Excel date strings to datetime objects and compare
+ # against the dateitme return value of xldate.xldate_as_datetime().
+ for excel_date in excel_dates:
+ exp = datetime.strptime(excel_date[0], "%Y-%m-%d")
+ got = xldate.xldate_as_datetime(excel_date[1], is_1904)
+
+ self.assertEqual(got, exp)
+
+ def test_times_only(self):
+ """
+ Test the _xldate_to_datetime() function for times only, i.e, the
+ fractional part of the Excel date when the serial date is 0.
+
+ """
+ # Test Excel dates strings and corresponding serial date numbers taken
+ # from an Excel file. The 1899-12-31 date is Excel's day 0.
+ excel_dates = [
+ # Random times in Excel's 0-0.9999+ range for 1 day.
+ ('1899-12-31T00:00:00.000', 0),
+ ('1899-12-31T00:15:20.213', 1.0650613425925924E-2),
+ ('1899-12-31T02:24:37.095', 0.10042934027777778),
+ ('1899-12-31T04:56:35.792', 0.2059698148148148),
+ ('1899-12-31T07:31:20.407', 0.31343063657407405),
+ ('1899-12-31T09:37:23.945', 0.40097158564814817),
+ ('1899-12-31T12:09:48.602', 0.50681252314814818),
+ ('1899-12-31T14:37:57.451', 0.60969271990740748),
+ ('1899-12-31T17:04:02.415', 0.71113906250000003),
+ ('1899-12-31T19:14:24.673', 0.80167445601851861),
+ ('1899-12-31T21:39:05.944', 0.90215212962962965),
+ ('1899-12-31T23:17:12.632', 0.97028509259259266),
+ ('1899-12-31T23:59:59.999', 0.99999998842592586),
+ ]
+
+ # Convert the Excel date strings to datetime objects and compare
+ # against the dateitme return value of xldate.xldate_as_datetime().
+ for excel_date in excel_dates:
+ exp = datetime.strptime(excel_date[0], "%Y-%m-%dT%H:%M:%S.%f")
+ got = xldate.xldate_as_datetime(excel_date[1], not_1904)
+
+ self.assertEqual(got, exp)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/tests/test_xlsx_comments.py new/xlrd-0.9.4/tests/test_xlsx_comments.py
--- old/xlrd-0.9.2/tests/test_xlsx_comments.py 1970-01-01 01:00:00.000000000 +0100
+++ new/xlrd-0.9.4/tests/test_xlsx_comments.py 2014-01-25 10:49:12.000000000 +0100
@@ -0,0 +1,46 @@
+from unittest import TestCase
+
+import os
+
+from xlrd import open_workbook
+
+from .base import from_this_dir
+
+class TestXlsxComments(TestCase):
+
+ def test_excel_comments(self):
+ book = open_workbook(from_this_dir('test_comments_excel.xlsx'))
+ sheet = book.sheet_by_index(0)
+
+ note_map = sheet.cell_note_map
+ self.assertEqual(len(note_map), 1)
+ self.assertEqual(note_map[(0, 1)].text, 'hello')
+
+ def test_excel_comments_multiline(self):
+ book = open_workbook(from_this_dir('test_comments_excel.xlsx'))
+ sheet = book.sheet_by_index(1)
+
+ note_map = sheet.cell_note_map
+ self.assertEqual(note_map[(1, 2)].text, '1st line\n2nd line')
+
+ def test_excel_comments_two_t_elements(self):
+ book = open_workbook(from_this_dir('test_comments_excel.xlsx'))
+ sheet = book.sheet_by_index(2)
+
+ note_map = sheet.cell_note_map
+ self.assertEqual(note_map[(0, 0)].text, 'Author:\nTwo t elements')
+
+ def test_excel_comments_no_t_elements(self):
+ book = open_workbook(from_this_dir('test_comments_excel.xlsx'))
+ sheet = book.sheet_by_index(3)
+
+ note_map = sheet.cell_note_map
+ self.assertEqual(note_map[(0,0)].text, '')
+
+ def test_gdocs_comments(self):
+ book = open_workbook(from_this_dir('test_comments_gdocs.xlsx'))
+ sheet = book.sheet_by_index(0)
+
+ note_map = sheet.cell_note_map
+ self.assertEqual(len(note_map), 1)
+ self.assertEqual(note_map[(0, 1)].text, 'Just a test')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/tests/test_xlsx_parse.py new/xlrd-0.9.4/tests/test_xlsx_parse.py
--- old/xlrd-0.9.2/tests/test_xlsx_parse.py 1970-01-01 01:00:00.000000000 +0100
+++ new/xlrd-0.9.4/tests/test_xlsx_parse.py 2015-07-15 08:11:03.000000000 +0200
@@ -0,0 +1,39 @@
+###############################################################################
+#
+# Test the parsing of problematic xlsx files from bug reports.
+#
+
+import unittest
+import xlrd
+from .base import from_this_dir
+
+
+class TestXlsxParse(unittest.TestCase):
+ # Test parsing of problematic xlsx files. These are usually submitted
+ # as part of bug reports as noted below.
+
+ def test_for_github_issue_96(self):
+ # Test for non-Excel file with forward slash file separator and
+ # lowercase names. https://github.com/python-excel/xlrd/issues/96
+ workbook = xlrd.open_workbook(from_this_dir('apachepoi_49609.xlsx'))
+ worksheet = workbook.sheet_by_index(0)
+
+ # Test reading sample data from the worksheet.
+ cell = worksheet.cell(0, 1)
+ self.assertEqual(cell.value, 'Cycle')
+ self.assertEqual(cell.ctype, xlrd.book.XL_CELL_TEXT)
+
+ cell = worksheet.cell(1, 1)
+ self.assertEqual(cell.value, 1)
+ self.assertEqual(cell.ctype, xlrd.book.XL_CELL_NUMBER)
+
+ def test_for_github_issue_101(self):
+ # Test for non-Excel file with forward slash file separator
+ # https://github.com/python-excel/xlrd/issues/101
+ workbook = xlrd.open_workbook(from_this_dir('self_evaluation_report_2014-05-19.xlsx'))
+ worksheet = workbook.sheet_by_index(0)
+
+ # Test reading sample data from the worksheet.
+ cell = worksheet.cell(0, 0)
+ self.assertEqual(cell.value, 'one')
+ self.assertEqual(cell.ctype, xlrd.book.XL_CELL_TEXT)
Files old/xlrd-0.9.2/tests/text_bar.xlsx and new/xlrd-0.9.4/tests/text_bar.xlsx differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/__init__.py new/xlrd-0.9.4/xlrd/__init__.py
--- old/xlrd-0.9.2/xlrd/__init__.py 2013-04-05 00:36:57.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/__init__.py 2015-07-15 08:11:03.000000000 +0200
@@ -399,7 +399,13 @@
zf = zipfile.ZipFile(timemachine.BYTES_IO(file_contents))
else:
zf = zipfile.ZipFile(filename)
- component_names = zf.namelist()
+
+ # Workaround for some third party files that use forward slashes and
+ # lower case names. We map the expected name in lowercase to the
+ # actual filename in the zip container.
+ component_names = dict([(name.replace('\\', '/').lower(), name)
+ for name in zf.namelist()])
+
if verbosity:
logfile.write('ZIP component_names:\n')
pprint.pprint(component_names, logfile)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/book.py new/xlrd-0.9.4/xlrd/book.py
--- old/xlrd-0.9.2/xlrd/book.py 2013-04-05 00:36:57.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/book.py 2014-01-25 10:49:12.000000000 +0100
@@ -452,22 +452,20 @@
# @return true if sheet is loaded, false otherwise
# <br /> -- New in version 0.7.1
def sheet_loaded(self, sheet_name_or_index):
- # using type(1) because int won't work with Python 2.1
- if isinstance(sheet_name_or_index, type(1)):
+ if isinstance(sheet_name_or_index, int):
sheetx = sheet_name_or_index
else:
try:
sheetx = self._sheet_names.index(sheet_name_or_index)
except ValueError:
raise XLRDError('No sheet named <%r>' % sheet_name_or_index)
- return self._sheet_list[sheetx] and True or False # Python 2.1 again
+ return bool(self._sheet_list[sheetx])
##
# @param sheet_name_or_index Name or index of sheet to be unloaded.
# <br /> -- New in version 0.7.1
def unload_sheet(self, sheet_name_or_index):
- # using type(1) because int won't work with Python 2.1
- if isinstance(sheet_name_or_index, type(1)):
+ if isinstance(sheet_name_or_index, int):
sheetx = sheet_name_or_index
else:
try:
@@ -566,43 +564,18 @@
self.ragged_rows = ragged_rows
if not file_contents:
- if python_version < (2, 2) and self.use_mmap:
- # need to open for update
- open_mode = "r+b"
- else:
- open_mode = "rb"
- retry = False
- f = None
- try:
- try:
- f = open(filename, open_mode)
- except IOError:
- e, v = sys.exc_info()[:2]
- if open_mode == "r+b" \
- and (v.errno == 13 or v.strerror == "Permission denied"):
- # Maybe the file is read-only
- retry = True
- self.use_mmap = False
- else:
- raise
- if retry:
- f = open(filename, "rb")
+ with open(filename, "rb") as f:
f.seek(0, 2) # EOF
size = f.tell()
f.seek(0, 0) # BOF
if size == 0:
raise XLRDError("File size is 0 bytes")
if self.use_mmap:
- if python_version < (2, 2):
- self.filestr = mmap.mmap(f.fileno(), size)
- else:
- self.filestr = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
+ self.filestr = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
self.stream_len = size
else:
self.filestr = f.read()
self.stream_len = len(self.filestr)
- finally:
- if f: f.close()
else:
self.filestr = file_contents
self.stream_len = len(file_contents)
@@ -800,11 +773,10 @@
# we're well & truly stuffed -- let the punter know ASAP.
try:
_unused = unicode(b'trial', self.encoding)
- except:
- ei = sys.exc_info()[:2]
+ except BaseException as e:
fprintf(self.logfile,
"ERROR *** codepage %r -> encoding %r -> %s: %s\n",
- self.codepage, self.encoding, ei[0].__name__.split(".")[-1], ei[1])
+ self.codepage, self.encoding, type(e).__name__.split(".")[-1], e)
raise
if self.raw_user_name:
strg = unpack_string(self.user_name, 0, self.encoding, lenlen=1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/compdoc.py new/xlrd-0.9.4/xlrd/compdoc.py
--- old/xlrd-0.9.2/xlrd/compdoc.py 2013-04-05 00:37:01.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/compdoc.py 2014-01-25 10:49:12.000000000 +0100
@@ -15,7 +15,7 @@
# 2007-05-07 SJM Meaningful exception instead of IndexError if a SAT (sector allocation table) is corrupted.
# 2007-04-22 SJM Missing "<" in a struct.unpack call => can't open files on bigendian platforms.
-from __future__ import nested_scopes, print_function
+from __future__ import print_function
import sys
from struct import unpack
from .timemachine import *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/examples/xlrdnameAPIdemo.py new/xlrd-0.9.4/xlrd/examples/xlrdnameAPIdemo.py
--- old/xlrd-0.9.2/xlrd/examples/xlrdnameAPIdemo.py 2013-04-05 00:36:57.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/examples/xlrdnameAPIdemo.py 2014-01-25 10:49:12.000000000 +0100
@@ -77,9 +77,8 @@
if celltype == xlrd.XL_CELL_DATE:
try:
showval = xlrd.xldate_as_tuple(cellvalue, datemode)
- except xlrd.XLDateError:
- e1, e2 = sys.exc_info()[:2]
- showval = "%s:%s" % (e1.__name__, e2)
+ except xlrd.XLDateError as e:
+ showval = "%s:%s" % (type(e).__name__, e)
elif celltype == xlrd.XL_CELL_ERROR:
showval = xlrd.error_text_from_code.get(
cellvalue, '' % cellvalue)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/formatting.py new/xlrd-0.9.4/xlrd/formatting.py
--- old/xlrd-0.9.2/xlrd/formatting.py 2013-04-05 00:36:57.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/formatting.py 2014-04-07 16:40:09.000000000 +0200
@@ -10,22 +10,10 @@
# No part of the content of this file was derived from the works of David Giffin.
-# 2010-10-30 SJM Added space after colon in "# coding" line to work around IBM iSeries Python bug
-# 2009-05-31 SJM Fixed problem with non-zero reserved bits in some STYLE records in Mac Excel files
-# 2008-08-03 SJM Ignore PALETTE record when Book.formatting_info is false
-# 2008-08-03 SJM Tolerate up to 4 bytes trailing junk on PALETTE record
-# 2008-05-10 SJM Do some XF checks only when Book.formatting_info is true
-# 2008-02-08 SJM Preparation for Excel 2.0 support
-# 2008-02-03 SJM Another tweak to is_date_format_string()
-# 2007-12-04 SJM Added support for Excel 2.x (BIFF2) files.
-# 2007-10-13 SJM Warning: style XF whose parent XF index != 0xFFF
-# 2007-09-08 SJM Work around corrupt STYLE record
-# 2007-07-11 SJM Allow for BIFF2/3-style FORMAT record in BIFF4/8 file
-
from __future__ import print_function
DEBUG = 0
-import copy, re
+import re
from struct import unpack
from .timemachine import *
from .biffh import BaseObject, unpack_unicode, unpack_string, \
@@ -279,7 +267,7 @@
if bv >= 50:
(
f.height, option_flags, f.colour_index, f.weight,
- f.escapement_type, f.underline_type, f.family,
+ f.escapement, f.underline_type, f.family,
f.character_set,
) = unpack('= 1:
used = sorted(book.colour_indexes_used.keys())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/info.py new/xlrd-0.9.4/xlrd/info.py
--- old/xlrd-0.9.2/xlrd/info.py 2013-04-09 21:29:41.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/info.py 2015-07-15 08:20:47.000000000 +0200
@@ -1 +1 @@
-__VERSION__ = "0.9.2"
+__VERSION__ = "0.9.4"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/sheet.py new/xlrd-0.9.4/xlrd/sheet.py
--- old/xlrd-0.9.2/xlrd/sheet.py 2013-04-05 00:37:29.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/sheet.py 2015-07-15 08:11:03.000000000 +0200
@@ -458,6 +458,11 @@
]
##
+ # Returns a generator for iterating through each row.
+ def get_rows(self):
+ return (self.row(index) for index in range(self.nrows))
+
+ ##
# Returns a slice of the types
# of the cells in the given row.
def row_types(self, rowx, start_colx=0, end_colx=None):
@@ -1046,6 +1051,9 @@
self_put_cell(rowx, colx, XL_CELL_BLANK, '', result[pos])
pos += 1
elif rc == XL_DIMENSION or rc == XL_DIMENSION2:
+ if data_len == 0:
+ # Four zero bytes after some other record. See github issue 64.
+ continue
# if data_len == 10:
# Was crashing on BIFF 4.0 file w/o the two trailing unused bytes.
# Reported by Ralph Heimburger.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/xldate.py new/xlrd-0.9.4/xlrd/xldate.py
--- old/xlrd-0.9.2/xlrd/xldate.py 2013-04-05 00:37:01.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/xldate.py 2014-04-07 16:40:04.000000000 +0200
@@ -17,10 +17,16 @@
# More importantly:
# Noon on Gregorian 1900-03-01 (day 61 in the 1900-based system) is JDN 2415080.0
# Noon on Gregorian 1904-01-02 (day 1 in the 1904-based system) is JDN 2416482.0
+import datetime
_JDN_delta = (2415080 - 61, 2416482 - 1)
assert _JDN_delta[1] - _JDN_delta[0] == 1462
+# Pre-calculate the datetime epochs for efficiency.
+epoch_1904 = datetime.datetime(1904, 1, 1)
+epoch_1900 = datetime.datetime(1899, 12, 31)
+epoch_1900_minus_1 = datetime.datetime(1899, 12, 30)
+
class XLDateError(ValueError): pass
class XLDateNegative(XLDateError): pass
@@ -90,6 +96,40 @@
else:
return ((yreg // 1461) - 4716, mp + 3, d, hour, minute, second)
+
+##
+# Convert an Excel date/time number into a datetime.datetime object.
+#
+# @param xldate The Excel number
+# @param datemode 0: 1900-based, 1: 1904-based.
+#
+# @return a datetime.datetime() object.
+#
+def xldate_as_datetime(xldate, datemode):
+ """Convert an Excel date/time number into a datetime.datetime object."""
+
+ # Set the epoch based on the 1900/1904 datemode.
+ if datemode:
+ epoch = epoch_1904
+ else:
+ if xldate < 60:
+ epoch = epoch_1900
+ else:
+ # Workaround Excel 1900 leap year bug by adjusting the epoch.
+ epoch = epoch_1900_minus_1
+
+ # The integer part of the Excel date stores the number of days since
+ # the epoch and the fractional part stores the percentage of the day.
+ days = int(xldate)
+ fraction = xldate - days
+
+ # Get the the integer and decimal seconds in Excel's millisecond resolution.
+ seconds = int(round(fraction * 86400000.0))
+ seconds, milliseconds = divmod(seconds, 1000)
+
+ return epoch + datetime.timedelta(days, seconds, 0, milliseconds)
+
+
# === conversions from date/time to xl numbers
def _leap(y):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xlrd-0.9.2/xlrd/xlsx.py new/xlrd-0.9.4/xlrd/xlsx.py
--- old/xlrd-0.9.2/xlrd/xlsx.py 2013-04-09 20:58:44.000000000 +0200
+++ new/xlrd-0.9.4/xlrd/xlsx.py 2015-07-15 08:11:03.000000000 +0200
@@ -19,9 +19,10 @@
ET = None
ET_has_iterparse = False
+Element_has_iter = False
def ensure_elementtree_imported(verbosity, logfile):
- global ET, ET_has_iterparse
+ global ET, ET_has_iterparse, Element_has_iter
if ET is not None:
return
if "IronPython" in sys.version:
@@ -47,6 +48,7 @@
ET_has_iterparse = True
except NotImplementedError:
pass
+ Element_has_iter = hasattr(ET.ElementTree, 'iter')
if verbosity:
etree_version = repr([
(item, getattr(ET, item))
@@ -225,14 +227,15 @@
if bk.verbosity:
print(msg, file=bk.logfile)
name_and_scope_map[key] = nobj
+ sort_data = (nobj.scope, namex, nobj)
if name_lcase in name_map:
- name_map[name_lcase].append((nobj.scope, nobj))
+ name_map[name_lcase].append(sort_data)
else:
- name_map[name_lcase] = [(nobj.scope, nobj)]
+ name_map[name_lcase] = [sort_data]
for key in name_map.keys():
alist = name_map[key]
alist.sort()
- name_map[key] = [x[1] for x in alist]
+ name_map[key] = [x[2] for x in alist]
bk.name_and_scope_map = name_and_scope_map
bk.name_map = name_map
@@ -243,7 +246,7 @@
fprintf(self.logfile, "\n=== %s ===\n", heading)
self.tree = ET.parse(stream)
getmethod = self.tag2meth.get
- for elem in self.tree.getiterator():
+ for elem in self.tree.iter() if Element_has_iter else self.tree.getiterator():
if self.verbosity >= 3:
self.dump_elem(elem)
meth = getmethod(elem.tag)
@@ -289,7 +292,7 @@
self.tree = ET.parse(stream)
getmenu = self.core_props_menu.get
props = {}
- for elem in self.tree.getiterator():
+ for elem in self.tree.iter() if Element_has_iter else self.tree.getiterator():
if self.verbosity >= 3:
self.dump_elem(elem)
menu = getmenu(elem.tag)
@@ -363,7 +366,14 @@
if self.verbosity >= 2:
self.dumpout('Ignoring sheet of type %r (name=%r)', reltype, name)
return
- bk._sheet_visibility.append(True)
+ state = elem.get('state')
+ visibility_map = {
+ None: 0,
+ 'visible': 0,
+ 'hidden': 1,
+ 'veryHidden': 2
+ }
+ bk._sheet_visibility.append(visibility_map[state])
sheet = Sheet(bk, position=None, name=name, number=sheetx)
sheet.utter_max_rows = X12_MAX_ROWS
sheet.utter_max_cols = X12_MAX_COLS
@@ -504,6 +514,7 @@
self.rowx = -1 # We may need to count them.
self.bk = sheet.book
self.sst = self.bk._sharedstrings
+ self.merged_cells = sheet.merged_cells
self.warned_no_cell_name = 0
self.warned_no_row_num = 0
if ET_has_iterparse:
@@ -521,8 +532,34 @@
elem.clear() # destroy all child elements (cells)
elif elem.tag == U_SSML12 + "dimension":
self.do_dimension(elem)
+ elif elem.tag == U_SSML12 + "mergeCell":
+ self.do_merge_cell(elem)
self.finish_off()
-
+
+ def process_comments_stream(self, stream):
+ root = ET.parse(stream).getroot()
+ author_list = root[0]
+ assert author_list.tag == U_SSML12 + 'authors'
+ authors = [elem.text for elem in author_list]
+ comment_list = root[1]
+ assert comment_list.tag == U_SSML12 + 'commentList'
+ cell_note_map = self.sheet.cell_note_map
+ from .sheet import Note
+ text_tag = U_SSML12 + 'text'
+ r_tag = U_SSML12 + 'r'
+ t_tag = U_SSML12 + 't'
+ for elem in comment_list.findall(U_SSML12 + 'comment'):
+ ts = elem.findall('./' + text_tag + '/' + t_tag)
+ ts += elem.findall('./' + text_tag + '/' + r_tag + '/' + t_tag)
+ ref = elem.get('ref')
+ note = Note()
+ note.author = authors[int(elem.get('authorId'))]
+ note.rowx, note.colx = coords = cell_name_to_rowx_colx(ref)
+ note.text = ''
+ for t in ts:
+ note.text += cooked_text(self, t)
+ cell_note_map[coords] = note
+
def do_dimension(self, elem):
ref = elem.get('ref') # example: "A1:Z99" or just "A1"
if ref:
@@ -532,6 +569,16 @@
self.sheet._dimnrows = rowx + 1
self.sheet._dimncols = colx + 1
+ def do_merge_cell(self, elem):
+ # The ref attribute should be a cell range like "B1:D5".
+ ref = elem.get('ref')
+ if ref:
+ first_cell_ref, last_cell_ref = ref.split(':')
+ first_rowx, first_colx = cell_name_to_rowx_colx(first_cell_ref)
+ last_rowx, last_colx = cell_name_to_rowx_colx(last_cell_ref)
+ self.merged_cells.append((first_rowx, last_rowx + 1,
+ first_colx, last_colx + 1))
+
def do_row(self, row_elem):
def bad_child_tag(child_tag):
@@ -569,6 +616,8 @@
try:
for c in cell_name:
charx += 1
+ if c == '$':
+ continue
lv = letter_value[c]
if lv:
colx = colx * 26 + lv
@@ -683,15 +732,6 @@
}
augment_keys(tag2meth, U_SSML12)
-def getzflo(zipfile, member_path):
- # GET a Zipfile File-Like Object for passing to
- # an XML parser
- try:
- return zipfile.open(member_path) # CPython 2.6 onwards
- except AttributeError:
- # old way
- return BYTES_IO(zipfile.read(member_path))
-
def open_workbook_2007_xml(
zf,
component_names,
@@ -718,41 +758,47 @@
bk.ragged_rows = ragged_rows
x12book = X12Book(bk, logfile, verbosity)
- zflo = getzflo(zf, 'xl/_rels/workbook.xml.rels')
+ zflo = zf.open(component_names['xl/_rels/workbook.xml.rels'])
x12book.process_rels(zflo)
del zflo
- zflo = getzflo(zf, 'xl/workbook.xml')
+ zflo = zf.open(component_names['xl/workbook.xml'])
x12book.process_stream(zflo, 'Workbook')
del zflo
- props_name = 'docProps/core.xml'
+ props_name = 'docprops/core.xml'
if props_name in component_names:
- zflo = getzflo(zf, props_name)
+ zflo = zf.open(component_names[props_name])
x12book.process_coreprops(zflo)
x12sty = X12Styles(bk, logfile, verbosity)
if 'xl/styles.xml' in component_names:
- zflo = getzflo(zf, 'xl/styles.xml')
+ zflo = zf.open(component_names['xl/styles.xml'])
x12sty.process_stream(zflo, 'styles')
del zflo
else:
# seen in MS sample file MergedCells.xlsx
pass
- sst_fname = 'xl/sharedStrings.xml'
+ sst_fname = 'xl/sharedstrings.xml'
x12sst = X12SST(bk, logfile, verbosity)
if sst_fname in component_names:
- zflo = getzflo(zf, sst_fname)
+ zflo = zf.open(component_names[sst_fname])
x12sst.process_stream(zflo, 'SST')
del zflo
for sheetx in range(bk.nsheets):
fname = x12book.sheet_targets[sheetx]
- zflo = getzflo(zf, fname)
+ zflo = zf.open(component_names[fname])
sheet = bk._sheet_list[sheetx]
x12sheet = X12Sheet(sheet, logfile, verbosity)
heading = "Sheet %r (sheetx=%d) from %r" % (sheet.name, sheetx, fname)
x12sheet.process_stream(zflo, heading)
del zflo
+ comments_fname = 'xl/comments%d.xml' % (sheetx + 1)
+ if comments_fname in component_names:
+ comments_stream = zf.open(component_names[comments_fname])
+ x12sheet.process_comments_stream(comments_stream)
+ del comments_stream
+
sheet.tidy_dimensions()
return bk