Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3 - Take 2 #253

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ eval*
.pytest_cache
.tox
docs_api
.idea
venv
dump.txt.gz
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
language: python

python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- "3.7"
- "3.8"

install:
- pip install tox-travis
Expand Down
Binary file removed dump.txt.gz
Binary file not shown.
2 changes: 0 additions & 2 deletions examples/advanced.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import print_function

from koala.ExcelCompiler import ExcelCompiler
from koala.Spreadsheet import Spreadsheet
from koala.excellib import xsum
Expand Down
2 changes: 0 additions & 2 deletions examples/basic.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import print_function

from koala.ExcelCompiler import ExcelCompiler
from koala.Spreadsheet import Spreadsheet

Expand Down
10 changes: 1 addition & 9 deletions koala/Cell.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
# cython: profile=True

from __future__ import absolute_import, division

from koala.CellBase import CellBase
from koala.Range import RangeCore
from koala.utils import *

from openpyxl.compat import unicode


class Cell(CellBase):
ctr = 0
Expand Down Expand Up @@ -62,11 +58,7 @@ def __init__(
self.__row = None
self.__col_idx = None

# `unicode` != `str` in Python2. See `from openpyxl.compat import unicode`
if type(formula) == str and str != unicode:
self.__formula = unicode(formula, 'utf-8') if formula else None
else:
self.__formula = formula if formula else None
self.__formula = formula if formula else None

self.__value = value
self.python_expression = None
Expand Down
12 changes: 0 additions & 12 deletions koala/ExcelCompiler.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
from __future__ import print_function
# cython: profile=True

import os.path

import networkx

from koala.reader import read_archive, read_named_ranges, read_cells
from koala.utils import *
from koala.ast import graph_from_seeds, shunting_yard, build_ast, prepare_pointer
from koala.Cell import Cell
from koala.Range import RangeFactory
from koala.Spreadsheet import Spreadsheet
import warnings

Expand All @@ -20,8 +10,6 @@ class ExcelCompiler(object):
"""

def __init__(self, file, ignore_sheets = [], ignore_hidden = False, debug = False):
# print("___### Initializing Excel Compiler ###___")

warnings.warn(
"The ExcelCompiler class will disappear in a future version. Please use Spreadsheet instead.",
PendingDeprecationWarning
Expand Down
21 changes: 8 additions & 13 deletions koala/Range.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
from __future__ import absolute_import, division, print_function

import logging
from koala.CellBase import CellBase
from koala.ExcelError import ErrorCodes, ExcelError
from koala.utils import *

from openpyxl.compat import unicode


# WARNING: Range should never be imported directly. Import Range from excelutils instead.

### Range Utils ###
Expand Down Expand Up @@ -58,7 +54,7 @@ def check_value(a):
return ExcelError(a)

try: # This is to avoid None or Exception returned by Range operations
if isinstance(a, (unicode, str)):
if isinstance(a, str):
return a
elif float(a):
return a
Expand Down Expand Up @@ -122,7 +118,6 @@ def __build(
cells, nrows, ncols = resolve_range(
reference, should_flatten=True)
except Exception as e:
print('Pb with ref', reference, e)
return ValueError('Range ERROR') # Will still be considered as a Range object, since we are inside __init__...

origin = parse_cell_address(cells[0]) if len(cells) > 0 else None # origin of Range
Expand Down Expand Up @@ -170,7 +165,7 @@ def __build(
elif not self.is_pointer: # when building pointers, name shouldn't be updated, but in that case reference is not a dict
self.__name = reference
else:
print('Pb with Name', reference, name)
logging.debug('Pb with Name', reference, name)
self.__origin = origin
self.__addresses = cells
self.__order = order
Expand Down Expand Up @@ -570,7 +565,7 @@ def multiply(a, b):
@staticmethod
def divide(a, b):
try:
return old_div(float(check_value(a)), float(check_value(b)))
return float(check_value(a)) / float(check_value(b))
except Exception as e:
return ExcelError('#DIV/0!', e)

Expand All @@ -584,9 +579,9 @@ def power(a, b):
@staticmethod
def is_equal(a, b):
try:
if not isinstance(a, (str, unicode)):
if not isinstance(a, str):
a = check_value(a)
if not isinstance(b, (str, unicode)):
if not isinstance(b, str):
b = check_value(b)

return is_almost_equal(a, b, precision=0.00001)
Expand All @@ -596,9 +591,9 @@ def is_equal(a, b):
@staticmethod
def is_not_equal(a, b):
try:
if not isinstance(a, (str, unicode)):
if not isinstance(a, str):
a = check_value(a)
if not isinstance(a, (str, unicode)):
if not isinstance(a, str):
b = check_value(b)

return a != b
Expand Down
46 changes: 15 additions & 31 deletions koala/Spreadsheet.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from __future__ import absolute_import, print_function
# cython: profile=True

from koala.Range import get_cell_address, parse_cell_address
Expand All @@ -13,17 +12,13 @@
from koala.utils import *

import warnings
import logging
import os.path
import networkx
from networkx.readwrite import json_graph

from openpyxl.compat import unicode


class Spreadsheet(object):
def __init__(self, file=None, ignore_sheets=[], ignore_hidden=False, debug=False):
# print("___### Initializing Excel Compiler ###___")

def __init__(self, file=None, ignore_sheets=[], ignore_hidden=False, include_only_sheets=None, debug=False):
if file is None:
# create empty version of this object
self.cells = None # precursor for cellmap: dict that link addresses (str) to Cell objects.
Expand Down Expand Up @@ -56,7 +51,7 @@ def __init__(self, file=None, ignore_sheets=[], ignore_hidden=False, debug=False
else: # assume file path
archive = read_archive(os.path.abspath(file))
# Parse cells
self.cells = read_cells(archive, ignore_sheets, ignore_hidden)
self.cells, self.sheets = read_cells(archive, ignore_sheets, ignore_hidden, include_only_sheets)
# Parse named_range { name (ExampleName) -> address (Sheet!A1:A10)}
self.named_ranges = read_named_ranges(archive)
self.range = RangeFactory(self.cells)
Expand All @@ -83,8 +78,6 @@ def gen_graph(self, outputs=[], inputs=[]):
:param outputs: can be used to specify the outputs. All not affected cells are removed from the graph.
:param inputs: can be used to specify the inputs. All not affected cells are removed from the graph.
"""
# print('___### Generating Graph ###___')

if len(outputs) == 0:
preseeds = set(list(flatten(self.cells.keys())) + list(self.named_ranges.keys())) # to have unicity
else:
Expand Down Expand Up @@ -128,7 +121,6 @@ def gen_graph(self, outputs=[], inputs=[]):
seeds.append(self.cells[o])

seeds = set(seeds)
# print("Seeds %s cells" % len(seeds))
outputs = set(preseeds) if len(outputs) > 0 else [] # seeds and outputs are the same when you don't specify outputs

cellmap, G = graph_from_seeds(seeds, self)
Expand Down Expand Up @@ -169,12 +161,6 @@ def gen_graph(self, outputs=[], inputs=[]):

inputs = set(inputs)


# print("Graph construction done, %s nodes, %s edges, %s cellmap entries" % (len(G.nodes()),len(G.edges()),len(cellmap)))

# undirected = networkx.Graph(G)
# print "Number of connected components %s", str(number_connected_components(undirected))

if inputs == [] and outputs == []:
self.build_spreadsheet(G, cellmap, self.named_ranges, pointers = self.pointers, outputs = outputs, inputs = inputs, debug = self.debug)
else:
Expand Down Expand Up @@ -277,7 +263,7 @@ def cell_add(self, address=None, cell=None, value=None, formula=None):
self.cellmap = cellmap
self.G = G

print("Graph construction updated, %s nodes, %s edges, %s cellmap entries" % (len(G.nodes()),len(G.edges()),len(cellmap)))
logging.debug("Graph construction updated, %s nodes, %s edges, %s cellmap entries" % (len(G.nodes()),len(G.edges()),len(cellmap)))

def set_formula(self, addr, formula):
# previously set_formula was used. Capture this behaviour.
Expand Down Expand Up @@ -306,7 +292,7 @@ def cell_set_formula(self, address, formula):
for index, c in enumerate(cell.range.cells): # for each cell of the range, translate the formula
if index == 0:
c.formula = formula
translator = Translator(unicode('=' + formula), c.address().split('!')[1]) # the Translator needs a reference without sheet
translator = Translator('=' + formula, c.address().split('!')[1]) # the Translator needs a reference without sheet
else:
translated = translator.translate_formula(c.address().split('!')[1]) # the Translator needs a reference without sheet
c.formula = translated[1:] # to get rid of the '='
Expand All @@ -325,11 +311,11 @@ def cell_set_formula(self, address, formula):
self.evaluate(address)
self.cellmap[address].should_eval = should_eval

print("Graph construction updated, %s nodes, %s edges, %s cellmap entries" % (len(G.nodes()),len(G.edges()),len(cellmap)))
logging.debug("Graph construction updated, %s nodes, %s edges, %s cellmap entries" % (len(G.nodes()),len(G.edges()),len(cellmap)))


def prune_graph(self, *args):
print('___### Pruning Graph ###___')
logging.debug('___### Pruning Graph ###___')

G = self.G

Expand All @@ -338,7 +324,6 @@ def prune_graph(self, *args):
for input_address in self.inputs:
child = self.cellmap[input_address]
if child == None:
print("Not found ", input_address)
continue
g = make_subgraph(G, child, "descending")
dependencies = dependencies.union(g.nodes())
Expand Down Expand Up @@ -393,7 +378,6 @@ def prune_graph(self, *args):
subgraph.add_edge(const_node, current)


print("Graph pruning done, %s nodes, %s edges, %s cellmap entries" % (len(subgraph.nodes()),len(subgraph.edges()),len(new_cellmap)))
undirected = networkx.Graph(subgraph)
# print "Number of connected components %s", str(number_connected_components(undirected))
# print map(lambda x: x.address(), subgraph.nodes())
Expand Down Expand Up @@ -430,7 +414,7 @@ def prune_graph(self, *args):
return spreadsheet.build_spreadsheet(subgraph, new_cellmap, self.named_ranges, self.pointers, self.outputs, self.inputs, debug = self.debug)

def clean_pointer(self):
print('___### Cleaning Pointers ###___')
logging.debug('___### Cleaning Pointers ###___')

new_named_ranges = self.named_ranges.copy()
new_cells = self.cellmap.copy()
Expand Down Expand Up @@ -484,7 +468,7 @@ def clean_pointer(self):
for repl in replacements:
if type(repl["value"]) == ExcelError:
if self.debug:
print('WARNING: Excel error found => replacing with #N/A')
logging.debug('WARNING: Excel error found => replacing with #N/A')
repl["value"] = "#N/A"

if repl["expression_type"] == "value":
Expand All @@ -503,7 +487,7 @@ def clean_pointer(self):
return new_cells, new_named_ranges

def print_value_ast(self, ast,node,indent):
print("%s %s %s %s" % (" "*indent, str(node.token.tvalue), str(node.token.ttype), str(node.token.tsubtype)))
logging.debug("%s %s %s %s" % (" "*indent, str(node.token.tvalue), str(node.token.ttype), str(node.token.tsubtype)))
for c in node.children(ast):
self.print_value_ast(ast, c, indent+1)

Expand All @@ -525,7 +509,7 @@ def eval_pointers_from_ast(self, ast, node, cell):

except Exception as e:
if self.debug:
print('EXCEPTION raised in eval_pointers: EXPR', expression, cell["address"])
logging.debug('EXCEPTION raised in eval_pointers: EXPR', expression, cell["address"])
raise Exception("Problem evalling: %s for %s, %s" % (e, cell["address"], expression))

return {"formula":pointer_string, "value": pointer_value, "expression_type": expression_type}
Expand Down Expand Up @@ -701,7 +685,7 @@ def cell_set_value(self, address, value):
cell = self.cellmap[address]

# when you set a value on cell, its should_eval flag is set to 'never' so its formula is not used until set free again => sp.activate_formula()
self.fix_cell(address)
self.cell_fix(address)

# case where the address refers to a range
if cell.is_range:
Expand Down Expand Up @@ -854,7 +838,7 @@ def cell_free(self, address=None):

def print_value_tree(self,addr,indent):
cell = self.cellmap[addr]
print("%s %s = %s" % (" "*indent,addr,cell.value))
logging.debug("%s %s = %s" % (" "*indent,addr,cell.value))
for c in self.G.predecessors_iter(cell):
self.print_value_tree(c.address(), indent+1)

Expand Down Expand Up @@ -892,7 +876,7 @@ def eval_ref(self, addr1, addr2 = None, ref = None):
cell1 = self.cellmap[addr1]
else:
if self.debug:
print('WARNING in eval_ref: address %s not found in cellmap, returning #NULL' % addr1)
logging.warning('WARNING in eval_ref: address %s not found in cellmap, returning #NULL' % addr1)
return ExcelError('#NULL', 'Cell %s is empty' % addr1)
if addr2 == None:
if cell1.is_range:
Expand Down Expand Up @@ -976,7 +960,7 @@ def cell_evaluate(self, address):
cell = self.cellmap[address]
except:
if self.debug:
print('WARNING: Empty cell at ' + address)
logging.warning('WARNING: Empty cell at ' + address)
return ExcelError('#NULL', 'Cell %s is empty' % address)

# no formula, fixed value
Expand Down
2 changes: 0 additions & 2 deletions koala/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import absolute_import

from openpyxl import *
from .ast import *
from .Cell import *
Expand Down
Loading