Hello community,
here is the log from the commit of package python-openpyxl for openSUSE:Factory checked in at 2018-01-10 23:38:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-openpyxl (Old)
and /work/SRC/openSUSE:Factory/.python-openpyxl.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-openpyxl"
Wed Jan 10 23:38:14 2018 rev:7 rq:563264 version:2.4.9
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-openpyxl/python-openpyxl.changes 2017-08-28 15:15:00.918851304 +0200
+++ /work/SRC/openSUSE:Factory/.python-openpyxl.new/python-openpyxl.changes 2018-01-10 23:38:14.823355564 +0100
@@ -1,0 +2,22 @@
+Wed Jan 10 10:13:52 UTC 2018 - kbabioch@suse.com
+
+- update to 2.4.9:
+ + Bugfixes
+ * #809 Incomplete documentation of copy_worksheet method
+ * #811 Scoped definedNames not removed when worksheet is deleted
+ * #824 Raise an exception if a chart is used in multiple sheets
+ * #842 Non-ASCII table column headings cause an exception in Python 2
+ * #846 Conditional formats not supported in write-only mode
+ * #849 Conditional formats with no sqref cause an exception
+ * #859 Headers that start with a number conflict with font size
+ * #902 TableStyleElements don’t always have a condtional format
+ * #908 Read-only mode sometimes returns too many cells
+ + Pull requests
+ * #179 Cells kept in a set
+ * #180 Support for Workbook protection
+ * #182 Read support for page breaks
+ * #183 Improve documentation of copy_worksheet method
+ * #198 Fix for #908
+- updated summary
+
+-------------------------------------------------------------------
@@ -61 +83 @@
- * Potential XXE vulerability
+ * Potential XXE vulerability (CVE-2017-5992 boo#1025592)
Old:
----
openpyxl-2.4.8.tar.gz
New:
----
openpyxl-2.4.9.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-openpyxl.spec ++++++
--- /var/tmp/diff_new_pack.8CEmUm/_old 2018-01-10 23:38:15.347330982 +0100
+++ /var/tmp/diff_new_pack.8CEmUm/_new 2018-01-10 23:38:15.351330795 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-openpyxl
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 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
@@ -18,9 +18,9 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-openpyxl
-Version: 2.4.8
+Version: 2.4.9
Release: 0
-Summary: A Python library to read/write Excel 2007 xlsx/xlsm files
+Summary: A Python library to read/write Excel 2010 xlsx/xlsm files
License: MIT and Python-2.0
Group: Development/Languages/Python
Url: http://openpyxl.readthedocs.org
++++++ openpyxl-2.4.8.tar.gz -> openpyxl-2.4.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/AUTHORS.rst new/openpyxl-2.4.9/AUTHORS.rst
--- old/openpyxl-2.4.8/AUTHORS.rst 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/AUTHORS.rst 2017-10-19 14:24:20.000000000 +0200
@@ -61,6 +61,7 @@
* James Smagala
* Wolfgane Scherer
* Joseph Tate
+* Gar Thompson
* Dieter Vandenbussche
* Paul Van Der Linden
* Gerald Van Huffelen
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/PKG-INFO new/openpyxl-2.4.9/PKG-INFO
--- old/openpyxl-2.4.8/PKG-INFO 2017-05-30 19:33:09.000000000 +0200
+++ new/openpyxl-2.4.9/PKG-INFO 2017-10-19 14:24:46.000000000 +0200
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: openpyxl
-Version: 2.4.8
+Version: 2.4.9
Summary: A Python library to read/write Excel 2010 xlsx/xlsm files
Home-page: https://openpyxl.readthedocs.io
Author: See AUTHORS
Author-email: charlie.clark@clark-consulting.eu
License: MIT/Expat
+Description-Content-Type: UNKNOWN
Description: openpyxl
========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/.constants.json new/openpyxl-2.4.9/openpyxl/.constants.json
--- old/openpyxl-2.4.8/openpyxl/.constants.json 2017-05-30 19:32:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/.constants.json 2017-10-19 14:24:20.000000000 +0200
@@ -4,5 +4,5 @@
"__license__": "MIT/Expat",
"__maintainer_email__": "openpyxl-users@googlegroups.com",
"__url__": "https://openpyxl.readthedocs.io",
- "__version__": "2.4.8"
+ "__version__": "2.4.9"
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/cell/read_only.py new/openpyxl-2.4.9/openpyxl/cell/read_only.py
--- old/openpyxl-2.4.8/openpyxl/cell/read_only.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/cell/read_only.py 2017-10-19 14:24:20.000000000 +0200
@@ -45,6 +45,10 @@
def __ne__(self, other):
return not self.__eq__(other)
+
+ def __repr__(self):
+ return "".format(self.parent.title, self.coordinate)
+
@property
def shared_strings(self):
return self.parent.shared_strings
@@ -145,4 +149,7 @@
data_type = 'n'
+ def __repr__(self):
+ return "<EmptyCell>"
+
EMPTY_CELL = EmptyCell()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/formatting/formatting.py new/openpyxl-2.4.9/openpyxl/formatting/formatting.py
--- old/openpyxl-2.4.8/openpyxl/formatting/formatting.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/formatting/formatting.py 2017-10-19 14:24:20.000000000 +0200
@@ -18,7 +18,7 @@
tagname = "conditionalFormatting"
- sqref = String()
+ sqref = String(allow_none=True)
pivot = Bool(allow_none=True)
cfRule = Sequence(expected_type=Rule)
rules = Alias("cfRule")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/packaging/workbook.py new/openpyxl-2.4.9/openpyxl/packaging/workbook.py
--- old/openpyxl-2.4.8/openpyxl/packaging/workbook.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/packaging/workbook.py 2017-10-19 14:24:20.000000000 +0200
@@ -66,6 +66,8 @@
package.definedNames._cleanup()
self.wb.defined_names = package.definedNames
+ self.wb.security = package.workbookProtection
+
def find_sheets(self):
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/reader/worksheet.py new/openpyxl-2.4.9/openpyxl/reader/worksheet.py
--- old/openpyxl-2.4.8/openpyxl/reader/worksheet.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/reader/worksheet.py 2017-10-19 14:24:20.000000000 +0200
@@ -23,6 +23,7 @@
from openpyxl.worksheet.hyperlink import Hyperlink
from openpyxl.worksheet.merge import MergeCells
from openpyxl.worksheet.page import PageMargins, PrintOptions, PrintPageSetup
+from openpyxl.worksheet.pagebreak import PageBreak
from openpyxl.worksheet.protection import SheetProtection
from openpyxl.worksheet.views import SheetViewList
from openpyxl.worksheet.datavalidation import DataValidationList
@@ -112,7 +113,8 @@
#'{%s}sheet/{%s}sortState' % (SHEET_MAIN_NS, SHEET_MAIN_NS): ('sort_state', SortState),
'{%s}sheetPr' % SHEET_MAIN_NS: ('sheet_properties', WorksheetProperties),
'{%s}sheetViews' % SHEET_MAIN_NS: ('views', SheetViewList),
- '{%s}sheetFormatPr' % SHEET_MAIN_NS: ('sheet_format', SheetFormatProperties)
+ '{%s}sheetFormatPr' % SHEET_MAIN_NS: ('sheet_format', SheetFormatProperties),
+ '{%s}rowBreaks' % SHEET_MAIN_NS: ('page_breaks', PageBreak),
}
tags = dispatcher.keys()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/styles/table.py new/openpyxl-2.4.9/openpyxl/styles/table.py
--- old/openpyxl-2.4.8/openpyxl/styles/table.py 2017-05-30 19:14:29.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/styles/table.py 2017-10-19 14:24:20.000000000 +0200
@@ -15,6 +15,8 @@
class TableStyleElement(Serialisable):
+ tagname = "tableStyleElement"
+
type = Set(values=(['wholeTable', 'headerRow', 'totalRow', 'firstColumn',
'lastColumn', 'firstRowStripe', 'secondRowStripe', 'firstColumnStripe',
'secondColumnStripe', 'firstHeaderCell', 'lastHeaderCell',
@@ -25,7 +27,7 @@
'thirdColumnSubheading', 'firstRowSubheading', 'secondRowSubheading',
'thirdRowSubheading', 'pageFieldLabels', 'pageFieldValues']))
size = Integer(allow_none=True)
- dxfId = Integer()
+ dxfId = Integer(allow_none=True)
def __init__(self,
type=None,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/utils/cell.py new/openpyxl-2.4.9/openpyxl/utils/cell.py
--- old/openpyxl-2.4.8/openpyxl/utils/cell.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/utils/cell.py 2017-10-19 14:24:20.000000000 +0200
@@ -57,13 +57,19 @@
def absolute_coordinate(coord_string):
"""Convert a coordinate to an absolute coordinate string (B12 -> $B$12)"""
m = ABSOLUTE_RE.match(coord_string.upper())
- if m:
- if all(m.groups()[-2:]):
- fmt = "${0}${1}:${3}${4}"
- else:
- fmt = "${0}${1}"
- return fmt.format(*m.groups())
- raise ValueError("Value is not a valid coordinate range")
+ if not m:
+ raise ValueError("Value is not a valid coordinate range")
+
+ d = m.groupdict('')
+ for k, v in d.items():
+ if v:
+ d[k] = "${0}".format(v)
+
+ if d['max_col'] or d['max_row']:
+ fmt = "{min_col}{min_row}:{max_col}{max_row}"
+ else:
+ fmt = "{min_col}{min_row}"
+ return fmt.format(**d)
def _get_column_letter(col_idx):
@@ -198,7 +204,10 @@
"""
Add quotes around sheetnames if they contain spaces.
"""
+ if "'" in sheetname:
+ sheetname = sheetname.replace("'", "''")
if (" " in sheetname
- or "-" in sheetname):
+ or "-" in sheetname
+ or "'" in sheetname):
sheetname = u"'{0}'".format(sheetname)
return sheetname
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/utils/exceptions.py new/openpyxl-2.4.9/openpyxl/utils/exceptions.py
--- old/openpyxl-2.4.8/openpyxl/utils/exceptions.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/utils/exceptions.py 2017-10-19 14:24:20.000000000 +0200
@@ -8,25 +8,32 @@
class CellCoordinatesException(Exception):
"""Error for converting between numeric and A1-style cell references."""
+
class IllegalCharacterError(Exception):
"""The data submitted which cannot be used directly in Excel files. It
must be removed or escaped."""
+
class NamedRangeException(Exception):
"""Error for badly formatted named ranges."""
+
class SheetTitleException(Exception):
"""Error for bad sheet names."""
+
class InsufficientCoordinatesException(Exception):
"""Error for partially specified cell coordinates."""
+
class InvalidFileException(Exception):
"""Error for trying to open a non-ooxml file."""
+
class ReadOnlyWorkbookException(Exception):
"""Error for trying to modify a read-only workbook"""
+
class WorkbookAlreadySaved(Exception):
"""Error when attempting to perform operations on a dump workbook
while it has already been dumped once"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/utils/protection.py new/openpyxl-2.4.9/openpyxl/utils/protection.py
--- old/openpyxl-2.4.8/openpyxl/utils/protection.py 1970-01-01 01:00:00.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/utils/protection.py 2017-10-19 14:24:20.000000000 +0200
@@ -0,0 +1,23 @@
+from __future__ import absolute_import
+# Copyright (c) 2010-2017 openpyxl
+
+
+def hash_password(plaintext_password=''):
+ """
+ Create a password hash from a given string for protecting a worksheet
+ only. This will not work for encrypting a workbook.
+
+ This method is based on the algorithm provided by
+ Daniel Rentz of OpenOffice and the PEAR package
+ Spreadsheet_Excel_Writer by Xavier Noguer .
+ See also http://blogs.msdn.com/b/ericwhite/archive/2008/02/23/the-legacy-hashing-algo...
+ """
+ password = 0x0000
+ for idx, char in enumerate(plaintext_password, 1):
+ value = ord(char) << idx
+ rotated_bits = value >> 15
+ value &= 0x7fff
+ password ^= (value | rotated_bits)
+ password ^= len(plaintext_password)
+ password ^= 0xCE4B
+ return str(hex(password)).upper()[2:]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/workbook/defined_name.py new/openpyxl-2.4.9/openpyxl/workbook/defined_name.py
--- old/openpyxl-2.4.8/openpyxl/workbook/defined_name.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/workbook/defined_name.py 2017-10-19 14:24:20.000000000 +0200
@@ -252,3 +252,10 @@
if defn.name == name and defn.localSheetId == scope:
del self.definedName[idx]
return True
+
+
+ def localnames(self, scope):
+ """
+ Provide a list of all names for a particular worksheet
+ """
+ return [defn.name for defn in self.definedName if defn.localSheetId == scope]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/workbook/protection.py new/openpyxl-2.4.9/openpyxl/workbook/protection.py
--- old/openpyxl-2.4.8/openpyxl/workbook/protection.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/workbook/protection.py 2017-10-19 14:24:20.000000000 +0200
@@ -19,16 +19,17 @@
Relation,
Base64Binary,
)
+from openpyxl.utils.protection import hash_password
class WorkbookProtection(Serialisable):
+ _workbook_password, _revisions_password = None, None
+
tagname = "workbookPr"
- workbookPassword = HexBinary(allow_none=True)
workbook_password = Alias("workbookPassword")
workbookPasswordCharacterSet = String(allow_none=True)
- revisionsPassword = HexBinary(allow_none=True)
revision_password = Alias("revisionsPassword")
revisionsPasswordCharacterSet = String(allow_none=True)
lockStructure = Bool(allow_none=True)
@@ -46,6 +47,12 @@
workbookSaltValue = Base64Binary(allow_none=True)
workbookSpinCount = Integer(allow_none=True)
+ __attrs__ = ('workbookPassword', 'workbookPasswordCharacterSet', 'revisionsPassword',
+ 'revisionsPasswordCharacterSet', 'lockStructure', 'lockWindows', 'lockRevision',
+ 'revisionsAlgorithmName', 'revisionsHashValue', 'revisionsSaltValue',
+ 'revisionsSpinCount', 'workbookAlgorithmName', 'workbookHashValue',
+ 'workbookSaltValue', 'workbookSpinCount')
+
def __init__(self,
workbookPassword=None,
workbookPasswordCharacterSet=None,
@@ -63,9 +70,11 @@
workbookSaltValue=None,
workbookSpinCount=None,
):
- self.workbookPassword = workbookPassword
+ if workbookPassword is not None:
+ self.workbookPassword = workbookPassword
self.workbookPasswordCharacterSet = workbookPasswordCharacterSet
- self.revisionsPassword = revisionsPassword
+ if revisionsPassword is not None:
+ self.revisionsPassword = revisionsPassword
self.revisionsPasswordCharacterSet = revisionsPasswordCharacterSet
self.lockStructure = lockStructure
self.lockWindows = lockWindows
@@ -79,6 +88,47 @@
self.workbookSaltValue = workbookSaltValue
self.workbookSpinCount = workbookSpinCount
+ def set_workbook_password(self, value='', already_hashed=False):
+ """Set a password on this workbook."""
+ if not already_hashed:
+ value = hash_password(value)
+ self._workbook_password = value
+
+ @property
+ def workbookPassword(self):
+ """Return the workbook password value, regardless of hash."""
+ return self._workbook_password
+
+ @workbookPassword.setter
+ def workbookPassword(self, value):
+ """Set a workbook password directly, forcing a hash step."""
+ self.set_workbook_password(value)
+
+ def set_revisions_password(self, value='', already_hashed=False):
+ """Set a revision password on this workbook."""
+ if not already_hashed:
+ value = hash_password(value)
+ self._revisions_password = value
+
+ @property
+ def revisionsPassword(self):
+ """Return the revisions password value, regardless of hash."""
+ return self._revisions_password
+
+ @revisionsPassword.setter
+ def revisionsPassword(self, value):
+ """Set a revisions password directly, forcing a hash step."""
+ self.set_revisions_password(value)
+
+ @classmethod
+ def from_tree(cls, node):
+ """Don't hash passwords when deserialising from XML"""
+ self = super(WorkbookProtection, cls).from_tree(node)
+ if self.workbookPassword:
+ self.set_workbook_password(node.get('workbookPassword'), already_hashed=True)
+ if self.revisionsPassword:
+ self.set_revisions_password(node.get('revisionsPassword'), already_hashed=True)
+ return self
# Backwards compatibility
DocumentSecurity = WorkbookProtection
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/workbook/workbook.py new/openpyxl-2.4.9/openpyxl/workbook/workbook.py
--- old/openpyxl-2.4.8/openpyxl/workbook/workbook.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/workbook/workbook.py 2017-10-19 14:24:20.000000000 +0200
@@ -178,6 +178,10 @@
def remove(self, worksheet):
"""Remove a worksheet from this workbook."""
+ idx = self._sheets.index(worksheet)
+ localnames = self.defined_names.localnames(scope=idx)
+ for name in localnames:
+ self.defined_names.delete(name, scope=idx)
self._sheets.remove(worksheet)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/worksheet/datavalidation.py new/openpyxl-2.4.9/openpyxl/worksheet/datavalidation.py
--- old/openpyxl-2.4.8/openpyxl/worksheet/datavalidation.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/worksheet/datavalidation.py 2017-10-19 14:24:20.000000000 +0200
@@ -65,7 +65,7 @@
cells = []
for rs in range_string.split():
cells.extend(rows_from_range(rs))
- return list(chain.from_iterable(cells))
+ return set(chain.from_iterable(cells))
class DataValidation(Serialisable):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/worksheet/header_footer.py new/openpyxl-2.4.9/openpyxl/worksheet/header_footer.py
--- old/openpyxl-2.4.8/openpyxl/worksheet/header_footer.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/worksheet/header_footer.py 2017-10-19 14:24:20.000000000 +0200
@@ -24,7 +24,7 @@
FONT_PATTERN = '&"(?P<font>.+)"'
COLOR_PATTERN = "&K(?P<color>[A-F0-9]{6})"
-SIZE_REGEX = r"&(?P<size>\d+)"
+SIZE_REGEX = r"&(?P<size>\d+\s?)"
FORMAT_REGEX = re.compile("{0}|{1}|{2}".format(FONT_PATTERN, COLOR_PATTERN,
SIZE_REGEX)
)
@@ -106,7 +106,7 @@
if self.font:
fmt.append(u'&"{0}"'.format(self.font))
if self.size:
- fmt.append("&{0}".format(self.size))
+ fmt.append("&{0} ".format(self.size))
if self.color:
fmt.append("&K{0}".format(self.color))
return u"".join(fmt + [self.text])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/worksheet/protection.py new/openpyxl-2.4.9/openpyxl/worksheet/protection.py
--- old/openpyxl-2.4.8/openpyxl/worksheet/protection.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/worksheet/protection.py 2017-10-19 14:24:20.000000000 +0200
@@ -12,27 +12,7 @@
HexBinary,
Base64Binary,
)
-
-
-def hash_password(plaintext_password=''):
- """
- Create a password hash from a given string for protecting a worksheet
- only. This will not work for encrypting a workbook.
-
- This method is based on the algorithm provided by
- Daniel Rentz of OpenOffice and the PEAR package
- Spreadsheet_Excel_Writer by Xavier Noguer .
- See also http://blogs.msdn.com/b/ericwhite/archive/2008/02/23/the-legacy-hashing-algo...
- """
- password = 0x0000
- for idx, char in enumerate(plaintext_password, 1):
- value = ord(char) << idx
- rotated_bits = value >> 15
- value &= 0x7fff
- password ^= (value | rotated_bits)
- password ^= len(plaintext_password)
- password ^= 0xCE4B
- return str(hex(password)).upper()[2:]
+from openpyxl.utils.protection import hash_password
class _Protected(object):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/worksheet/read_only.py new/openpyxl-2.4.9/openpyxl/worksheet/read_only.py
--- old/openpyxl-2.4.8/openpyxl/worksheet/read_only.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/worksheet/read_only.py 2017-10-19 14:24:20.000000000 +0200
@@ -180,7 +180,7 @@
col_counter = column + 1
if max_col is not None:
- for _ in range(col_counter, max_col+1):
+ for _ in range(max(min_col, col_counter), max_col+1):
yield EMPTY_CELL
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/writer/excel.py new/openpyxl-2.4.9/openpyxl/writer/excel.py
--- old/openpyxl-2.4.8/openpyxl/writer/excel.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/writer/excel.py 2017-10-19 14:24:20.000000000 +0200
@@ -9,6 +9,7 @@
from zipfile import ZipFile, ZIP_DEFLATED
# package imports
+from openpyxl.utils.exceptions import InvalidFileException
from openpyxl.xml.constants import (
ARC_SHARED_STRINGS,
ARC_CONTENT_TYPES,
@@ -122,6 +123,8 @@
def _write_charts(self):
# delegate to object
+ if len(self._charts) != len(set(self._charts)):
+ raise InvalidFileException("The same chart cannot be used in more than one worksheet")
for chart in self._charts:
self._archive.writestr(chart.path[1:], tostring(chart._write()))
self.manifest.append(chart)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/writer/workbook.py new/openpyxl-2.4.9/openpyxl/writer/workbook.py
--- old/openpyxl-2.4.8/openpyxl/writer/workbook.py 2017-05-30 19:20:53.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl/writer/workbook.py 2017-10-19 14:24:20.000000000 +0200
@@ -87,6 +87,9 @@
props.date1904 = True
root.workbookPr = props
+ # workbook protection
+ root.workbookProtection = wb.security
+
# book views
active = get_active_sheet(wb)
view = BookView(activeTab=active)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/writer/worksheet.py new/openpyxl-2.4.9/openpyxl/writer/worksheet.py
--- old/openpyxl-2.4.8/openpyxl/writer/worksheet.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/writer/worksheet.py 2017-10-19 14:24:20.000000000 +0200
@@ -10,6 +10,7 @@
# package imports
from openpyxl.xml.functions import xmlfile
from openpyxl.xml.constants import SHEET_MAIN_NS
+from openpyxl.compat import unicode
from openpyxl.styles.differential import DifferentialStyle
from openpyxl.packaging.relationship import Relationship, RelationshipList
@@ -185,7 +186,7 @@
for cell, col in zip(row, table.tableColumns):
if cell.data_type != "s":
warn("File may not be readable: column headings must be strings.")
- col.name = str(cell.value)
+ col.name = unicode(cell.value)
rel = Relationship(type=table._rel_type, Target="")
ws._rels.append(rel)
table._rel_id = rel.Id
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl/writer/write_only.py new/openpyxl-2.4.9/openpyxl/writer/write_only.py
--- old/openpyxl-2.4.8/openpyxl/writer/write_only.py 2017-03-16 19:05:43.000000000 +0100
+++ new/openpyxl-2.4.9/openpyxl/writer/write_only.py 2017-10-19 14:24:20.000000000 +0200
@@ -21,7 +21,7 @@
from .etree_worksheet import write_cell
from .excel import ExcelWriter
-from .worksheet import write_drawing
+from .worksheet import write_drawing, write_conditional_formatting
from openpyxl.xml.constants import SHEET_MAIN_NS
from openpyxl.xml.functions import xmlfile, Element
@@ -191,6 +191,11 @@
if self.sort_state.ref:
xf.write(self.sort_state.to_tree())
+ if self.conditional_formatting:
+ cfs = write_conditional_formatting(self)
+ for cf in cfs:
+ xf.write(cf)
+
if self.data_validations.count:
xf.write(self.data_validations.to_tree())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl.egg-info/PKG-INFO new/openpyxl-2.4.9/openpyxl.egg-info/PKG-INFO
--- old/openpyxl-2.4.8/openpyxl.egg-info/PKG-INFO 2017-05-30 19:33:08.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl.egg-info/PKG-INFO 2017-10-19 14:24:45.000000000 +0200
@@ -1,11 +1,12 @@
Metadata-Version: 1.1
Name: openpyxl
-Version: 2.4.8
+Version: 2.4.9
Summary: A Python library to read/write Excel 2010 xlsx/xlsm files
Home-page: https://openpyxl.readthedocs.io
Author: See AUTHORS
Author-email: charlie.clark@clark-consulting.eu
License: MIT/Expat
+Description-Content-Type: UNKNOWN
Description: openpyxl
========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.4.8/openpyxl.egg-info/SOURCES.txt new/openpyxl-2.4.9/openpyxl.egg-info/SOURCES.txt
--- old/openpyxl-2.4.8/openpyxl.egg-info/SOURCES.txt 2017-05-30 19:33:08.000000000 +0200
+++ new/openpyxl-2.4.9/openpyxl.egg-info/SOURCES.txt 2017-10-19 14:24:45.000000000 +0200
@@ -131,6 +131,7 @@
openpyxl/utils/exceptions.py
openpyxl/utils/formulas.py
openpyxl/utils/indexed_list.py
+openpyxl/utils/protection.py
openpyxl/utils/units.py
openpyxl/workbook/__init__.py
openpyxl/workbook/child.py