Skip to content

Commit

Permalink
Temporarily fix openpyxl read_worksheets issue
Browse files Browse the repository at this point in the history
  • Loading branch information
PrimozGodec committed Feb 29, 2024
1 parent 194572b commit 23b5fee
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
105 changes: 105 additions & 0 deletions Orange/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# This module is a mixture of imports and code, so we allow import anywhere
# pylint: disable=wrong-import-position,wrong-import-order
import warnings

from openpyxl.cell import MergedCell
from openpyxl.comments.comment_sheet import CommentSheet
from openpyxl.drawing.spreadsheet_drawing import SpreadsheetDrawing
from openpyxl.packaging.relationship import (
get_rels_path,
RelationshipList,
get_dependents,
)
from openpyxl.pivot.table import TableDefinition
from openpyxl.reader.drawings import find_images
from openpyxl.reader.excel import ExcelReader
from openpyxl.worksheet._read_only import ReadOnlyWorksheet
from openpyxl.worksheet._reader import WorksheetReader
from openpyxl.xml.constants import COMMENTS_NS
from openpyxl.xml.functions import fromstring
from openpyxl.worksheet.table import Table

from Orange import data

Expand Down Expand Up @@ -46,3 +64,90 @@
pass
finally:
del ctypes


# temporary fix for file not closed issue until openpyxl prepare release
# https://foss.heptapod.net/openpyxl/openpyxl/-/merge_requests/
# 436#7922bd5f66e11e4ca4539f093b2680a25c1f80db
def read_worksheets(self):
# pylint: too-many-branches
comment_warning = (
"Cell '{0}':{1} is part of a merged range but has a comment which will "
"be removed because merged cells cannot contain any data."
)
for sheet, rel in self.parser.find_sheets():
if rel.target not in self.valid_files:
continue

if "chartsheet" in rel.Type:
self.read_chartsheet(sheet, rel)
continue

rels_path = get_rels_path(rel.target)
rels = RelationshipList()
if rels_path in self.valid_files:
rels = get_dependents(self.archive, rels_path)

if self.read_only:
ws = ReadOnlyWorksheet(self.wb, sheet.name, rel.target, self.shared_strings)
ws.sheet_state = sheet.state
self.wb._sheets.append(ws) # pylint: disable=protected-access
continue # pylint: disable=no-else-continue
else:
fh = self.archive.open(rel.target)
ws = self.wb.create_sheet(sheet.name)
ws._rels = rels # pylint: disable=protected-access
ws_parser = WorksheetReader(
ws, fh, self.shared_strings, self.data_only, self.rich_text
)
ws_parser.bind_all()
fh.close()

# assign any comments to cells
for r in rels.find(COMMENTS_NS):
src = self.archive.read(r.target)
comment_sheet = CommentSheet.from_tree(fromstring(src))
for ref, comment in comment_sheet.comments:
try:
ws[ref].comment = comment
except AttributeError:
c = ws[ref]
if isinstance(c, MergedCell):
warnings.warn(comment_warning.format(ws.title, c.coordinate))
continue

# preserve link to VML file if VBA
if self.wb.vba_archive and ws.legacy_drawing:
ws.legacy_drawing = rels.get(ws.legacy_drawing).target
else:
ws.legacy_drawing = None

for t in ws_parser.tables:
src = self.archive.read(t)
xml = fromstring(src)
table = Table.from_tree(xml)
ws.add_table(table)

#pylint: disable=protected-access
drawings = rels.find(SpreadsheetDrawing._rel_type)
for rel in drawings:
charts, images = find_images(self.archive, rel.target)
for c in charts:
ws.add_chart(c, c.anchor)
for im in images:
ws.add_image(im, im.anchor)

pivot_rel = rels.find(TableDefinition.rel_type)
pivot_caches = self.parser.pivot_caches
for r in pivot_rel:
pivot_path = r.Target
src = self.archive.read(pivot_path)
tree = fromstring(src)
pivot = TableDefinition.from_tree(tree)
pivot.cache = pivot_caches[pivot.cacheId]
ws.add_pivot(pivot)

ws.sheet_state = sheet.state


ExcelReader.read_worksheets = read_worksheets
12 changes: 12 additions & 0 deletions Orange/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import unittest
from distutils.version import LooseVersion

import openpyxl

import Orange

from Orange.base import SklLearner, Learner, Model
Expand Down Expand Up @@ -155,5 +157,15 @@ def test_pickle(self):
self.assertEqual(model2.original_data, None)


class TestRemoveTemporarySolution(unittest.TestCase):
def test_remove_openpyxl_temp_solution(self):
"""
When this test starts to fail revert https://github.com/biolab/orange3/pull/6737
"""
self.assertLessEqual(
[int(x) for x in openpyxl.__version__.split(".")], [3, 1, 2]
)


if __name__ == "__main__":
unittest.main()

0 comments on commit 23b5fee

Please sign in to comment.