Hello community, here is the log from the commit of package python3-openpyxl for openSUSE:Factory checked in at 2015-04-05 02:03:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python3-openpyxl (Old) and /work/SRC/openSUSE:Factory/.python3-openpyxl.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-openpyxl" Changes: -------- --- /work/SRC/openSUSE:Factory/python3-openpyxl/python3-openpyxl.changes 2015-03-16 07:01:09.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python3-openpyxl.new/python3-openpyxl.changes 2015-04-05 02:04:09.000000000 +0200 @@ -1,0 +2,17 @@ +Fri Apr 3 00:19:48 UTC 2015 - a...@gmx.de + +- update to version 2.2.1: + * PR54 Improved precision on times near midnight. + * PR55 Preserve macro buttons + * #429 Workbook fails to load because header and footers cannot be + parsed. + * #433 File-like object with encoding=None + * #434 SyntaxError when writing page breaks. + * #436 Read-only mode duplicates empty rows. + * #437 Cell.offset raises an exception + * #438 Cells with pivotButton and quotePrefix styles cannot be read + * #440 Error when customised versions of builtin formats + * #442 Exception raised when a fill element contains no children + * #444 Styles cannot be copied + +------------------------------------------------------------------- Old: ---- openpyxl-2.2.0.tar.gz New: ---- openpyxl-2.2.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python3-openpyxl.spec ++++++ --- /var/tmp/diff_new_pack.QLPM4W/_old 2015-04-05 02:04:10.000000000 +0200 +++ /var/tmp/diff_new_pack.QLPM4W/_new 2015-04-05 02:04:10.000000000 +0200 @@ -17,7 +17,7 @@ Name: python3-openpyxl -Version: 2.2.0 +Version: 2.2.1 Release: 0 Summary: A Python library to read/write Excel 2007 xlsx/xlsm files License: MIT and Python-2.0 ++++++ openpyxl-2.2.0.tar.gz -> openpyxl-2.2.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/PKG-INFO new/openpyxl-2.2.1/PKG-INFO --- old/openpyxl-2.2.0/PKG-INFO 2015-03-11 17:14:43.000000000 +0100 +++ new/openpyxl-2.2.1/PKG-INFO 2015-03-31 11:14:50.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: openpyxl -Version: 2.2.0 +Version: 2.2.1 Summary: A Python library to read/write Excel 2007 xlsx/xlsm files Home-page: http://openpyxl.readthedocs.org Author: See AUTHORS @@ -59,7 +59,6 @@ Release notes: http://openpyxl.readthedocs.org/en/latest/changes.html Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta Classifier: Development Status :: 5 - Production/Stable Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/__init__.py new/openpyxl-2.2.1/openpyxl/__init__.py --- old/openpyxl-2.2.0/openpyxl/__init__.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/__init__.py 2015-03-20 16:18:11.000000000 +0100 @@ -11,7 +11,7 @@ # constants -__version__ = '2.2.0' +__version__ = '2.2.1' __author__ = 'Eric Gazoni' __license__ = 'MIT/Expat' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/cell/cell.py new/openpyxl-2.2.1/openpyxl/cell/cell.py --- old/openpyxl-2.2.0/openpyxl/cell/cell.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/cell/cell.py 2015-03-31 11:12:52.000000000 +0200 @@ -71,6 +71,9 @@ NUMBER_REGEX = re.compile(r'^-?([\d]|[\d]+\.[\d]*|\.[\d]+|[1-9][\d]+\.?[\d]*)((E|e)[-+]?[\d]+)?$') ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]') +ERROR_CODES = ('#NULL!', '#DIV/0!', '#VALUE!', '#REF!', '#NAME?', '#NUM!', + '#N/A') + class Cell(StyleableObject): """Describes cell associated properties. @@ -90,13 +93,7 @@ '_comment', ) - ERROR_CODES = ('#NULL!', - '#DIV/0!', - '#VALUE!', - '#REF!', - '#NAME?', - '#NUM!', - '#N/A') + ERROR_CODES = ERROR_CODES TYPE_STRING = 's' TYPE_FORMULA = 'f' @@ -111,14 +108,17 @@ TYPE_NULL, TYPE_INLINE, TYPE_ERROR, TYPE_FORMULA_CACHE_STRING) - def __init__(self, worksheet, column, row, value=None, fontId=0, fillId=0, - borderId=0, alignmentId=0, protectionId=0, numFmtId=0, xfId=None): + def __init__(self, worksheet, column, row, value=None, fontId=0, + fillId=0, borderId=0, alignmentId=0, protectionId=0, numFmtId=0, + pivotButton=None, quotePrefix=None, xfId=None): self._font_id = fontId self._fill_id = fillId self._border_id = borderId self._alignment_id = alignmentId self._protection_id = protectionId self._number_format_id = numFmtId + self.quotePrefix = quotePrefix + self.pivotButton = pivotButton self.parent = worksheet self.column = column self.row = row @@ -363,8 +363,7 @@ :rtype: :class:`openpyxl.cell.Cell` """ - offset_column = get_column_letter( - column_index_from_string(self.column) + column) + offset_column = column_index_from_string(self.column) + column offset_row = self.row + row return self.parent.cell(column=offset_column, row=offset_row) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/profiling.py new/openpyxl-2.2.1/openpyxl/profiling.py --- old/openpyxl-2.2.0/openpyxl/profiling.py 2015-02-09 23:50:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/profiling.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,130 +0,0 @@ -from io import BytesIO -import os -from random import randint - -from openpyxl import Workbook -from openpyxl.xml.functions import XMLGenerator - -def make_worksheet(): - wb = Workbook() - ws = wb.active - for i in range(1000): - ws.append(list(range(100))) - return ws - - - - -def make_dump_worksheet(): - wb = Workbook(write_only=True) - ws = wb.create_sheet() - return ws - -def dump_writer(ws=None): - if ws is None: - ws = make_dump_worksheet() - for i in range(1000): - ws.append(list(range(100))) - - -COLUMNS = 100 -ROWS = 1000 -BOLD = 1 -ITALIC = 2 -UNDERLINE = 4 -RED_BG = 8 -formatData = [[None] * COLUMNS for _ in range(ROWS)] - -def generate_format_data(): - for row in range(ROWS): - for col in range(COLUMNS): - formatData[row][col] = randint(1, 15) - - -def styled_sheet(): - from openpyxl import Workbook - from openpyxl.styles import Font, Style, PatternFill, Color, colors - - wb = Workbook() - ws = wb.active - ws.title = 'Test 1' - - red_fill = PatternFill(fill_type='solid', fgColor=Color(colors.RED), bgColor=Color(colors.RED)) - empty_fill = PatternFill() - styles = [] - # pregenerate relevant styles - for row in range(ROWS): - _row = [] - for col in range(COLUMNS): - cell = ws.cell(row=row+1, column=col+1) - cell.value = 1 - font = {} - fill = PatternFill() - if formatData[row][col] & BOLD: - font['bold'] = True - if formatData[row][col] & ITALIC: - font['italic'] = True - if formatData[row][col] & UNDERLINE: - font['underline'] = 'single' - if formatData[row][col] & RED_BG: - fill = red_fill - cell.style = Style(font=Font(**font), fill=fill) - - #wb.save(get_output_path('test_openpyxl_style_std_pregen.xlsx')) - - -def read_workbook(): - from openpyxl import load_workbook - folder = os.path.split(__file__)[0] - src = os.path.join(folder, "files", "very_large.xlsx") - wb = load_workbook(src, read_only=True) - return wb - - -def rows_without_values(wb): - ws = wb.active - rows = ws.iter_rows() - for r, row in enumerate(rows): - for c, col in enumerate(row): - pass - print((r+1)* (c+1), "cells") - - -def rows_with_values(wb): - ws = wb.active - rows = ws.iter_rows() - for r, row in enumerate(rows): - for c, col in enumerate(row): - col.value - print((r+1)* (c+1), "cells") - -def col_index1(): - from openpyxl.cell import get_column_letter - for i in range(1, 18279): - c = get_column_letter(i) - - - -""" -Sample use -import cProfile -ws = make_worksheet() -cProfile.run("profiling.lxml_writer(ws)", sort="tottime") -""" - - -if __name__ == '__main__': - import cProfile - # ws = make_worksheet() - wb = read_workbook() - print("Looping without values") - cProfile.run("rows_without_values(wb)", sort="tottime") - print("Looping with values") - cProfile.run("rows_with_values(wb)", sort="tottime") - cProfile.run("make_worksheet()", sort="tottime") - #cProfile.run("lxml_writer(ws)", sort="tottime") - generate_format_data() - cProfile.run("styled_sheet()", sort="tottime") - ws = make_dump_worksheet() - cProfile.run("dump_writer(ws)", sort="tottime") - cProfile.run("col_index1()", sort="tottime") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/reader/excel.py new/openpyxl-2.2.1/openpyxl/reader/excel.py --- old/openpyxl-2.2.0/openpyxl/reader/excel.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/reader/excel.py 2015-03-31 11:12:52.000000000 +0200 @@ -131,7 +131,7 @@ if is_file_like: # fileobject must have been opened with 'rb' flag # it is required by zipfile - if hasattr(filename, 'encoding'): + if getattr(filename, 'encoding', None) is not None: raise IOError("File-object must be opened in binary mode") try: @@ -233,8 +233,7 @@ else: new_ws = read_worksheet(archive.read(worksheet_path), wb, sheet_name, shared_strings, wb.shared_styles, - color_index=wb._colors, - keep_vba=keep_vba) + color_index=wb._colors) new_ws.sheet_state = sheet.get('state') or 'visible' wb._add_sheet(new_ws) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/reader/style.py new/openpyxl-2.2.1/openpyxl/reader/style.py --- old/openpyxl-2.2.0/openpyxl/reader/style.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/reader/style.py 2015-03-31 11:12:52.000000000 +0200 @@ -42,6 +42,7 @@ self.border_list = IndexedList() self.alignments = IndexedList([Alignment()]) self.protections = IndexedList([Protection()]) + self.custom_number_formats = {} self.number_formats = IndexedList() def parse(self): @@ -58,9 +59,10 @@ """Read in custom numeric formatting rules from the shared style table""" custom_formats = {} num_fmts = self.root.findall('{%s}numFmts/{%s}numFmt' % (SHEET_MAIN_NS, SHEET_MAIN_NS)) - for num_fmt_node in num_fmts: - fmt_code = num_fmt_node.get('formatCode').lower() - self.number_formats.append(fmt_code) + for node in num_fmts: + idx = int(node.get('numFmtId')) + self.custom_number_formats[idx] = node.get('formatCode') + self.number_formats.append(node.get('formatCode')) def parse_color_index(self): @@ -154,10 +156,13 @@ fillId = int(xf.get("fillId", 0)) borderId = int(xf.get("borderId", 0)) - if numFmtId < 164: - format_code = builtin_formats.get(numFmtId, 'General') + # check for custom formats and normalise indices + + if numFmtId in self.custom_number_formats: + format_code = self.custom_number_formats[numFmtId] + attrs["numFmtId"] = self.number_formats.add(format_code) + 164 else: - format_code = self.number_formats[numFmtId-165] + format_code = builtin_formats[numFmtId] _style['number_format'] = format_code if bool_attrib(xf, 'applyAlignment'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/reader/worksheet.py new/openpyxl-2.2.1/openpyxl/reader/worksheet.py --- old/openpyxl-2.2.0/openpyxl/reader/worksheet.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/reader/worksheet.py 2015-03-31 11:12:52.000000000 +0200 @@ -65,6 +65,7 @@ self.guess_types = ws.parent._guess_types self.data_only = ws.parent.data_only self.styles = [dict(style) for style in self.ws.parent._cell_styles] + self.keep_vba = ws.parent.vba_archive is not None def parse(self): dispatcher = { @@ -129,7 +130,6 @@ style_id = int(style_id) style = self.styles[style_id] - column, row = coordinate_from_string(coordinate) cell = Cell(self.ws, column, row, **style) self.ws._add_cell(cell) @@ -297,7 +297,10 @@ def parse_legacy_drawing(self, element): - self.ws.vba_controls = element.get("r:id") + if self.keep_vba: + # Create an id that will not clash with any other ids that will + # be generated. + self.ws.vba_controls = 'vbaControlId' def parse_sheet_views(self, element): @@ -307,14 +310,14 @@ self.ws.sheet_view = SheetView.from_tree(el) -def fast_parse(ws, xml_source, shared_strings, style_table, color_index=None): +def fast_parse(ws, xml_source, shared_strings, style_table, color_index=None, keep_vba=False): parser = WorkSheetParser(ws, xml_source, shared_strings, style_table, color_index) parser.parse() del parser def read_worksheet(xml_source, parent, preset_title, shared_strings, - style_table, color_index=None, worksheet_path=None, keep_vba=False): + style_table, color_index=None, worksheet_path=None): """Read an xml worksheet""" if worksheet_path: ws = IterableWorksheet(parent, preset_title, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/styles/__init__.py new/openpyxl-2.2.1/openpyxl/styles/__init__.py --- old/openpyxl-2.2.0/openpyxl/styles/__init__.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/styles/__init__.py 2015-03-31 11:12:52.000000000 +0200 @@ -2,6 +2,7 @@ # Copyright (c) 2010-2015 openpyxl from openpyxl.descriptors import Typed +from openpyxl.compat import deprecated from .alignment import Alignment from .borders import Border, Side @@ -24,12 +25,12 @@ 'protection') __base__ = True - _font = Typed(expected_type=Font) - _fill = Typed(expected_type=Fill) - _border = Typed(expected_type=Border) - _alignment = Typed(expected_type=Alignment) + font = Typed(expected_type=Font) + fill = Typed(expected_type=Fill, allow_none=True) + border = Typed(expected_type=Border) + alignment = Typed(expected_type=Alignment) number_format = NumberFormatDescriptor() - _protection = Typed(expected_type=Protection) + protection = Typed(expected_type=Protection) def __init__(self, font=Font(), @@ -39,33 +40,24 @@ number_format=None, protection=Protection() ): - self._font = font - self._fill = fill - self._border = border - self._alignment = alignment + self.font = font + self.fill = fill + self.border = border + self.alignment = alignment self.number_format = number_format - self._protection = protection + self.protection = protection - @property - def font(self): - return StyleProxy(self._font) - - @property - def fill(self): - return StyleProxy(self._fill) - - @property - def border(self): - return StyleProxy(self._border) - - @property - def alignment(self): - return StyleProxy(self._alignment) - - @property - def protection(self): - return StyleProxy(self._protection) + @deprecated("Copy formatting objects like font directly") + def copy(self): + cls = self.__class__ + return cls(font=self.font.copy(), + fill=self.fill.copy(), + border=self.border.copy(), + alignment=self.alignment.copy(), + number_format=self.number_format, + protection=self.protection.copy() + ) DEFAULTS = Style() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/styles/fills.py new/openpyxl-2.2.1/openpyxl/styles/fills.py --- old/openpyxl-2.2.0/openpyxl/styles/fills.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/styles/fills.py 2015-03-31 11:12:52.000000000 +0200 @@ -48,7 +48,10 @@ @classmethod def from_tree(cls, el): - child = [c for c in el][0] + children = [c for c in el] + if not children: + return + child = children[0] if "patternFill" in child.tag: return PatternFill._from_tree(child) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/styles/styleable.py new/openpyxl-2.2.1/openpyxl/styles/styleable.py --- old/openpyxl-2.2.0/openpyxl/styles/styleable.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/styles/styleable.py 2015-03-31 11:12:52.000000000 +0200 @@ -1,7 +1,7 @@ from __future__ import absolute_import # Copyright (c) 2010-2015 openpyxl -from collections import namedtuple +from warnings import warn from openpyxl.utils.indexed_list import IndexedList from .numbers import BUILTIN_FORMATS, BUILTIN_FORMATS_REVERSE @@ -62,9 +62,11 @@ alignment = StyleDescriptor('_alignments', '_alignment_id') __slots__ = ('parent', '_font_id', '_border_id', '_fill_id', - '_alignment_id', '_protection_id', '_number_format_id') + '_alignment_id', '_protection_id', '_number_format_id', 'pivotButton', + 'quotePrefix') - def __init__(self, sheet, fontId=0, fillId=0, borderId=0, alignmentId=0, protectionId=0, numFmtId=0): + def __init__(self, sheet, fontId=0, fillId=0, borderId=0, alignmentId=0, + protectionId=0, numFmtId=0, pivotButton=None, quotePrefix=None): self._font_id = fontId self._fill_id = fillId self._border_id = borderId @@ -72,6 +74,8 @@ self._protection_id = protectionId self._number_format_id = numFmtId self.parent = sheet + self.pivotButton = pivotButton + self.quotePrefix = quotePrefix @property @@ -82,7 +86,10 @@ fillId=self._fill_id, fontId=self._font_id, numFmtId=self._number_format_id, - protectionId=self._protection_id) + protectionId=self._protection_id, + pivotButton=self.pivotButton, + quotePrefix=self.quotePrefix + ) return self.parent.parent._cell_styles.add(style) @@ -93,26 +100,30 @@ or self._fill_id or self._font_id or self._number_format_id - or self._protection_id) + or self._protection_id + or self.pivotButton + or self.quotePrefix + ) #legacy @property def style(self): + warn("Use formatting objects such as font directly") return Style( - font=self.font, - fill=self.fill, - border=self.border, - alignment=self.alignment, + font=self.font.copy(), + fill=self.fill.copy(), + border=self.border.copy(), + alignment=self.alignment.copy(), number_format=self.number_format, - protection=self.protection + protection=self.protection.copy() ) #legacy @style.setter def style(self, value): - self.font = value.font._StyleProxy__target - self.fill = value.fill._StyleProxy__target - self.border = value.border._StyleProxy__target - self.protection = value.protection._StyleProxy__target - self.alignment = value.alignment._StyleProxy__target + self.font = value.font.copy() + self.fill = value.fill.copy() + self.border = value.border.copy() + self.protection = value.protection.copy() + self.alignment = value.alignment.copy() self.number_format = value.number_format diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/utils/datetime.py new/openpyxl-2.2.1/openpyxl/utils/datetime.py --- old/openpyxl-2.2.0/openpyxl/utils/datetime.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/utils/datetime.py 2015-03-31 11:12:52.000000000 +0200 @@ -58,10 +58,15 @@ value += 1 parts = list(jd2gcal(MJD_0, value + offset - MJD_0)) _, fraction = divmod(value, 1) + jumped = (parts[-1] == 0 and fraction > 0) diff = datetime.timedelta(days=fraction) + if 0 < abs(value) < 1: return days_to_time(diff) - return datetime.datetime(*parts[:3]) + diff + if not jumped: + return datetime.datetime(*parts[:3]) + diff + else: + return datetime.datetime(*parts[:3] + [0]) @lru_cache() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/workbook/workbook.py new/openpyxl-2.2.1/openpyxl/workbook/workbook.py --- old/openpyxl-2.2.0/openpyxl/workbook/workbook.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/workbook/workbook.py 2015-03-20 16:18:11.000000000 +0100 @@ -290,6 +290,8 @@ you will only be able to call this function once. Subsequents attempts to modify or save the file will raise an :class:`openpyxl.shared.exc.WorkbookAlreadySaved` exception. """ + if self.read_only: + raise TypeError("""Workbook is read-only""") if self.write_only: save_dump(self, filename) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/worksheet/header_footer.py new/openpyxl-2.2.1/openpyxl/worksheet/header_footer.py --- old/openpyxl-2.2.0/openpyxl/worksheet/header_footer.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/worksheet/header_footer.py 2015-03-20 16:18:11.000000000 +0100 @@ -109,7 +109,7 @@ m = SIZE_REGEX.search(text) if m: - self.font_size = m.group(0) + self.font_size = int(m.group('size')) text = SIZE_REGEX.sub('', text) m = COLOR_REGEX.search(text) @@ -194,14 +194,23 @@ (&L(?P<left>.+?))? (&C(?P<center>.+?))? (&R(?P<right>.+?))? -$""", re.VERBOSE) +$""", re.VERBOSE | re.DOTALL) + +# add support for multiline strings (how do re.flags combine?) + +from warnings import warn def _split_string(text): """Split the combined (decoded) string into left, center and right parts""" m = ITEM_REGEX.match(text) - return m.groupdict() + try: + parts = m.groupdict() + except AttributeError: + warn("""Cannot parse header or footer so it will be ignored""") + parts = {'left':'', 'right':'', 'center':''} + return parts HEADER_REGEX = re.compile(r"(&[ABDEGHINOPSTUXYZ\+\-])") # split part into commands FONT_REGEX = re.compile('&"(?P<font>.+)"') COLOR_REGEX = re.compile("&K(?P<color>[A-F0-9]{6})") -SIZE_REGEX = re.compile(r"&\d+") +SIZE_REGEX = re.compile(r"&(?P<size>\d+)") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/worksheet/iter_worksheet.py new/openpyxl-2.2.1/openpyxl/worksheet/iter_worksheet.py --- old/openpyxl-2.2.0/openpyxl/worksheet/iter_worksheet.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/worksheet/iter_worksheet.py 2015-03-31 11:12:52.000000000 +0200 @@ -96,7 +96,7 @@ if max_col is not None: empty_row = tuple(EMPTY_CELL for column in range(min_col, max_col + 1)) else: - expected_columns = [] + empty_row = [] row_counter = min_row p = iterparse(self.xml_source, tag=[ROW_TAG], remove_blank_text=True) @@ -110,6 +110,7 @@ # some rows are missing for row_counter in range(row_counter, row_id): + row_counter += 1 yield empty_row # return cells from a row diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/writer/excel.py new/openpyxl-2.2.1/openpyxl/writer/excel.py --- old/openpyxl-2.2.0/openpyxl/writer/excel.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/writer/excel.py 2015-03-31 11:12:52.000000000 +0200 @@ -105,6 +105,7 @@ image_id = 1 shape_id = 1 comments_id = 1 + vba_controls_id = 1 for i, sheet in enumerate(self.workbook.worksheets): archive.writestr(PACKAGE_WORKSHEETS + '/sheet%d.xml' % (i + 1), @@ -112,8 +113,9 @@ )) if (sheet._charts or sheet._images or sheet.relationships - or sheet._comment_count > 0): - rels = write_rels(sheet, drawing_id, comments_id) + or sheet._comment_count > 0 + or sheet.vba_controls is not None): + rels = write_rels(sheet, drawing_id, comments_id, vba_controls_id) archive.writestr( PACKAGE_WORKSHEETS + '/_rels/sheet%d.xml.rels' % (i + 1), tostring(rels) @@ -152,6 +154,9 @@ cw.write_comments_vml()) comments_id += 1 + if sheet.vba_controls is not None: + vba_controls_id += 1 + def _write_external_links(self, archive): """Write links to external workbooks""" wb = self.workbook diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/writer/relations.py new/openpyxl-2.2.1/openpyxl/writer/relations.py --- old/openpyxl-2.2.0/openpyxl/writer/relations.py 2015-02-09 16:59:20.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/writer/relations.py 2015-03-31 11:12:52.000000000 +0200 @@ -11,7 +11,7 @@ ) -def write_rels(worksheet, drawing_id, comments_id): +def write_rels(worksheet, drawing_id, comments_id, vba_controls_id): """Write relationships for the worksheet to xml.""" root = Element('{%s}Relationships' % PKG_REL_NS) for rel in worksheet.relationships: @@ -35,5 +35,9 @@ 'Type': VML_NS, 'Target': '../drawings/commentsDrawing%s.vml' % comments_id} SubElement(root, '{%s}Relationship' % PKG_REL_NS, attrs) + if worksheet.vba_controls is not None: + attrs = {'Id': worksheet.vba_controls, + 'Type': VML_NS, + 'Target': '../drawings/vmlDrawing%s.vml' % vba_controls_id} + SubElement(root, '{%s}Relationship' % PKG_REL_NS, attrs) return root - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/writer/worksheet.py new/openpyxl-2.2.1/openpyxl/writer/worksheet.py --- old/openpyxl-2.2.0/openpyxl/writer/worksheet.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/writer/worksheet.py 2015-03-31 11:12:52.000000000 +0200 @@ -199,7 +199,7 @@ tag = Element('rowBreaks', {'count': str(len(breaks)), 'manualBreakCount': str(len(breaks))}) for b in breaks: - tag.append(Element('brk', id=str(b), man=true, max='16383', + tag.append(Element('brk', id=str(b), man="true", max='16383', min='0')) return tag @@ -295,7 +295,8 @@ # add a legacyDrawing so that excel can draw comments if worksheet._comment_count > 0: - comments = Element('legacyDrawing', {'{%s}id' % REL_NS: 'commentsvml'}) + comments = Element('{%s}legacyDrawing' % SHEET_MAIN_NS, + {'{%s}id' % REL_NS: 'commentsvml'}) xf.write(comments) xml = out.getvalue() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl/xml/constants.py new/openpyxl-2.2.1/openpyxl/xml/constants.py --- old/openpyxl-2.2.0/openpyxl/xml/constants.py 2015-03-11 16:10:31.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl/xml/constants.py 2015-03-31 11:12:52.000000000 +0200 @@ -31,7 +31,7 @@ ARC_SHARED_STRINGS = PACKAGE_XL + '/sharedStrings.xml' ARC_CUSTOM_UI = 'customUI/customUI.xml' ARC_VBA = ('xl/vba', 'xl/activeX', 'xl/drawings', 'xl/media', 'xl/ctrlProps', - 'xl/worksheets/_rels', 'customUI', 'xl/printerSettings') + 'customUI', 'xl/printerSettings') ## namespaces # Dublin Core diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl.egg-info/PKG-INFO new/openpyxl-2.2.1/openpyxl.egg-info/PKG-INFO --- old/openpyxl-2.2.0/openpyxl.egg-info/PKG-INFO 2015-03-11 17:14:43.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl.egg-info/PKG-INFO 2015-03-31 11:14:50.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: openpyxl -Version: 2.2.0 +Version: 2.2.1 Summary: A Python library to read/write Excel 2007 xlsx/xlsm files Home-page: http://openpyxl.readthedocs.org Author: See AUTHORS @@ -59,7 +59,6 @@ Release notes: http://openpyxl.readthedocs.org/en/latest/changes.html Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta Classifier: Development Status :: 5 - Production/Stable Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/openpyxl.egg-info/SOURCES.txt new/openpyxl-2.2.1/openpyxl.egg-info/SOURCES.txt --- old/openpyxl-2.2.0/openpyxl.egg-info/SOURCES.txt 2015-03-11 17:14:43.000000000 +0100 +++ new/openpyxl-2.2.1/openpyxl.egg-info/SOURCES.txt 2015-03-31 11:14:50.000000000 +0200 @@ -11,7 +11,6 @@ et_xmfile/xmlfile.py openpyxl/__init__.py openpyxl/conftest.py -openpyxl/profiling.py openpyxl.egg-info/PKG-INFO openpyxl.egg-info/SOURCES.txt openpyxl.egg-info/dependency_links.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openpyxl-2.2.0/setup.py new/openpyxl-2.2.1/setup.py --- old/openpyxl-2.2.0/setup.py 2015-03-11 17:14:11.000000000 +0100 +++ new/openpyxl-2.2.1/setup.py 2015-03-20 16:18:11.000000000 +0100 @@ -72,7 +72,6 @@ 'jdcal', ], classifiers=[ - 'Development Status :: 4 - Beta', 'Development Status :: 5 - Production/Stable', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows',