Skip to content

Commit

Permalink
pep8 fixes and add copy interface
Browse files Browse the repository at this point in the history
  • Loading branch information
skyreflectedinmirrors committed Apr 20, 2017
1 parent a045f1f commit bc0b52a
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 38 deletions.
56 changes: 33 additions & 23 deletions optionloop/optionloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@
"""

from collections import namedtuple
from collections import defaultdict

class OptionLoop(object):

class OptionLoop(object):
class optionloopconcat(object):

def __init__(self, oploop_list):
self.oplooplist = oploop_list
self.master_index = 0
Expand All @@ -95,7 +95,7 @@ def check_all(self):
Checks to see that all option loops are unstarted
"""
return all(oploop.index == 0 for oploop in self.oplooplist) \
and self.master_index == 0
and self.master_index == 0

def __next__(self):
if self.master_index < len(self.oplooplist):
Expand All @@ -107,6 +107,12 @@ def __next__(self):
else:
raise StopIteration()

def copy(self):
newlist = []
for oploop in self.oplooplist:
newlist.append(oploop.copy())
return OptionLoop.optionloopconcat(newlist)

def __iter__(self):
return self

Expand All @@ -123,16 +129,14 @@ def __add__(self, other):
elif isinstance(other, OptionLoop):
return OptionLoop.optionloopconcat(self.oplooplist[:] + [other])

next = __next__ #python 2 compatiblity


next = __next__ # python 2 compatiblity

def __init__(self, initializing_dictionary, default_dict_factory=None):
"""
Initializes the OptionLoop.
@param initializing_dictionary :
The basis of the option loop.
The basis of the option loop.
The various options to iterate are the keys of the dictionary,
while the value(s) associated with the key are iterated over
Expand All @@ -142,10 +146,10 @@ def __init__(self, initializing_dictionary, default_dict_factory=None):

assert isinstance(initializing_dictionary, dict)

self.mydict = initializing_dictionary
self.mydict = initializing_dictionary.copy()
self.index = 0
self.index_index = None
for key, value in self.mydict.items():
self.end_index = None
for key, value in self.mydict.iteritems():
if isinstance(value, (str, bytes)):
self.mydict[key] = [value]
size = 1
Expand All @@ -155,48 +159,54 @@ def __init__(self, initializing_dictionary, default_dict_factory=None):
except TypeError:
self.mydict[key] = [value]
size = len([value])
if self.index_index is None:
self.index_index = 1

if self.end_index is None:
self.end_index = 1
# the maximum index is the multiplicative sum
# of the length of all interior arrays
self.index_index *= size
self.end_index *= size
self.default_dict_factory = default_dict_factory
self.use_dd = default_dict_factory is not None

def copy(self):
return OptionLoop(self.mydict,
self.default_dict_factory)

def __next__(self):
if self.use_dd:
value_list = defaultdict(self.default_dict_factory)
else:
value_list = {}
startlen = 1
if self.index_index is not None and self.index < self.index_index:
for key, value in self.mydict.items():
value_list[key] = value[int((self.index / startlen) % len(value))]
if self.index < self.end_index:
for key, value in self.mydict.iteritems():
value_list[key] = value[(self.index / startlen) % len(value)]
startlen *= len(value)

self.index += 1
else:
raise StopIteration()
raise StopIteration()

return value_list

def __add__(self, other):
assert isinstance(other, OptionLoop) or isinstance(other, self.optionloopconcat), \
"Adding object of type {} to option loop undefined".format(type(other))
"Adding object of type {} to option loop undefined".format(
type(other))

if isinstance(other, self.optionloopconcat):
if self.index > 0 or not other.check_all():
raise Exception('Cannot add option loops once iteration has begun...')
raise Exception(
'Cannot add option loops once iteration has begun...')
return self.optionloopconcat([self] + other.oplooplist)

if self.index > 0 or other.index > 0:
raise Exception('Cannot add option loops once iteration has begun...')
raise Exception(
'Cannot add option loops once iteration has begun...')

return self.optionloopconcat([self, other])

def __iter__(self):
return self

next = __next__ #python 2 compatiblity

next = __next__ # python 2 compatiblity
78 changes: 63 additions & 15 deletions optionloop/tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

from ..optionloop import OptionLoop


class TestOptionLoop(unittest.TestCase):

def test_empty(self):
d = {}
op = OptionLoop(d)
Expand All @@ -16,7 +18,7 @@ def test_empty(self):
self.assertTrue(i is None)

def test_default_dict(self):
d = {'test' : [True]}
d = {'test': [True]}
op = OptionLoop(d, lambda: False)
for i in op:
self.assertTrue(i['notakey'] == False)
Expand All @@ -25,19 +27,19 @@ def test_default_dict(self):
self.assertTrue(i['notakey'] == True)

def test_string1(self):
d = {'a' : 'a'}
d = {'a': 'a'}
op = OptionLoop(d)
for i in op:
self.assertTrue(i['a'] == 'a')

def test_string2(self):
d = {'a' : 'abc'}
d = {'a': 'abc'}
op = OptionLoop(d)
for i in op:
self.assertTrue(i['a'] == 'abc')

def test_multiple_values1(self):
d = {'a' : [False, True]}
d = {'a': [False, True]}
op = OptionLoop(d)
for i, state in enumerate(op):
self.assertTrue(state['a'] == i)
Expand All @@ -63,15 +65,15 @@ def test_multiple_values3(self):
self.assertTrue(state['c'] == int(i / 2) + 1)

def test_no_len(self):
d = {'a' : None}
d = {'a': None}
op = OptionLoop(d)
for i in op:
self.assertTrue(i['a'] is None)

def test_add_oploops(self):
d = {'a' : [False, True]}
d = {'a': [False, True]}
op1 = OptionLoop(d)
d = {'a' : [1, 2]}
d = {'a': [1, 2]}
op2 = OptionLoop(d)
op = op1 + op2
for i, state in enumerate(op):
Expand All @@ -81,12 +83,12 @@ def test_add_oploops(self):
self.assertTrue(state['a'] == i - 1)

def test_add_oploops2(self):
d = {'a' : [False]}
d = {'a': [False]}
op1 = OptionLoop(d)
d = {'a' : [True]}
d = {'a': [True]}
op2 = OptionLoop(d)
op = op1 + op2
d = {'a' : [1, 2]}
d = {'a': [1, 2]}
op3 = OptionLoop(d)
op = op + op3
for i, state in enumerate(op):
Expand All @@ -96,12 +98,12 @@ def test_add_oploops2(self):
self.assertTrue(state['a'] == i - 1)

def test_add_oploops2(self):
d = {'a' : [False]}
d = {'a': [False]}
op1 = OptionLoop(d)
d = {'a' : [True]}
d = {'a': [True]}
op2 = OptionLoop(d)
op = op1 + op2
d = {'a' : [1, 2]}
d = {'a': [1, 2]}
op3 = OptionLoop(d)
op = op3 + op
for i, state in enumerate(op):
Expand All @@ -110,9 +112,8 @@ def test_add_oploops2(self):
else:
self.assertTrue(state['a'] == i + 1)


def test_add_oploops_bad(self):
d = {'a' : [False, True]}
d = {'a': [False, True]}
op1 = OptionLoop(d)
for i, state in enumerate(op1):
op2 = OptionLoop(d)
Expand All @@ -122,6 +123,53 @@ def test_add_oploops_bad(self):
except Exception:
self.assertTrue(True)

def test_copy(self):
d = {'a': [False, True]}
# test copy interface of oploop
op1 = OptionLoop(d, lambda: False)

# run out loop
for i, state in enumerate(op1):
pass

op2 = op1.copy()

# copy should have same dictionary properties
self.assertTrue(op2.mydict ==
op1.mydict)
self.assertTrue(op2.default_dict_factory ==
op1.default_dict_factory)
# and a reset index
self.assertTrue(op2.index == 0)
# but a same end index
self.assertTrue(op2.end_index == op1.end_index)

def test_copy_concat(self):
d = {'a': [False, True]}
d2 = {'b': ['a', 'b']}
# test copy interface of oploop
op1 = OptionLoop(d, lambda: False)
op2 = OptionLoop(d2, lambda: False)

op = op1 + op2

# run out loop
for i, state in enumerate(op):
pass

op_copy = op.copy()

# copy should have same dictionary properties
self.assertTrue(len(op_copy.oplooplist) == len(op.oplooplist))
for i in range(len(op.oplooplist)):
# check that the dicts of each oploop in list are same
self.assertTrue(op.oplooplist[i].mydict ==
op_copy.oplooplist[i].mydict)
self.assertTrue(op.oplooplist[i].default_dict_factory ==
op_copy.oplooplist[i].default_dict_factory)
# and a reset index
self.assertTrue(op_copy.master_index == 0)


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

0 comments on commit bc0b52a

Please sign in to comment.