-
Notifications
You must be signed in to change notification settings - Fork 51
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
Expand cycler() signature. #14
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,8 +7,8 @@ | |
You can add cyclers:: | ||
|
||
from cycler import cycler | ||
cc = (cycler('color', list('rgb')) + | ||
cycler('linestyle', ['-', '--', '-.'])) | ||
cc = (cycler(color=list('rgb')) + | ||
cycler(linestyle=['-', '--', '-.'])) | ||
for d in cc: | ||
print(d) | ||
|
||
|
@@ -22,8 +22,8 @@ | |
You can multiply cyclers:: | ||
|
||
from cycler import cycler | ||
cc = (cycler('color', list('rgb')) * | ||
cycler('linestyle', ['-', '--', '-.'])) | ||
cc = (cycler(color=list('rgb')) * | ||
cycler(linestyle=['-', '--', '-.'])) | ||
for d in cc: | ||
print(d) | ||
|
||
|
@@ -164,8 +164,8 @@ def __getitem__(self, key): | |
# TODO : maybe add numpy style fancy slicing | ||
if isinstance(key, slice): | ||
trans = self._transpose() | ||
return reduce(add, (cycler(k, v[key]) | ||
for k, v in six.iteritems(trans))) | ||
return cycler(**dict((k, v[key]) | ||
for k, v in six.iteritems(trans))) | ||
else: | ||
raise ValueError("Can only use slices with Cycler.__getitem__") | ||
|
||
|
@@ -203,8 +203,8 @@ def __mul__(self, other): | |
return Cycler(self, other, product) | ||
elif isinstance(other, int): | ||
trans = self._transpose() | ||
return reduce(add, (cycler(k, v*other) | ||
for k, v in six.iteritems(trans))) | ||
return cycler(**dict((k, v*other) | ||
for k, v in six.iteritems(trans))) | ||
else: | ||
return NotImplemented | ||
|
||
|
@@ -268,7 +268,7 @@ def __repr__(self): | |
if self._right is None: | ||
lab = self.keys.pop() | ||
itr = list(v[lab] for v in self) | ||
return "cycler({lab!r}, {itr!r})".format(lab=lab, itr=itr) | ||
return "cycler({lab}={itr!r})".format(lab=lab, itr=itr) | ||
else: | ||
op = op_map.get(self._op, '?') | ||
msg = "({left!r} {op} {right!r})" | ||
|
@@ -329,10 +329,55 @@ def simplify(self): | |
# I would believe that there is some performance implications | ||
|
||
trans = self._transpose() | ||
return reduce(add, (cycler(k, v) for k, v in six.iteritems(trans))) | ||
return cycler(**dict((k, v) for k, v in six.iteritems(trans))) | ||
|
||
|
||
def cycler(label, itr): | ||
def cycler(*args, **kwargs): | ||
""" | ||
Create a new `Cycler` object from the combination of | ||
positional arguments or keyword arguments. | ||
|
||
cycler(arg) | ||
cycler(label1=itr1[, label2=iter2[, ...]]) | ||
|
||
Form 1 simply copies a given `Cycler` object. | ||
Form 2 composes a `Cycler` as an inner product of the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "inner product" might not mean much to many docstring readers here. Maybe add something like, "All iterables are cycled simultaneously." |
||
pairs of keyword arguments. | ||
|
||
Parameters | ||
---------- | ||
label : str | ||
The property key. | ||
|
||
itr : iterable | ||
Finite length iterable of the property values. | ||
|
||
Returns | ||
------- | ||
cycler : Cycler | ||
New `Cycler` for the given property | ||
|
||
""" | ||
if args and kwargs: | ||
raise TypeError("cyl() can only accept positional OR keyword " | ||
"arguments -- not both.") | ||
|
||
if len(args) == 1: | ||
if not isinstance(args[0], Cycler): | ||
raise TypeError("If only one positional argument given, it must " | ||
" be a Cycler instance.") | ||
return copy.copy(args[0]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably want to do a keep copy, I can in to some really weird bugs earlier due to underlying dict objects getting shared. I think this will play badly with the re-labeling functionality. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want me to use |
||
elif len(args) > 1: | ||
raise TypeError("Only a single Cycler can be accepted as the lone " | ||
"positional argument. Use keyword arguments instead.") | ||
|
||
if kwargs: | ||
return reduce(add, (_cycler(k, v) for k, v in six.iteritems(kwargs))) | ||
|
||
raise TypeError("Must have at least a positional OR keyword arguments") | ||
|
||
|
||
def _cycler(label, itr): | ||
""" | ||
Create a new `Cycler` object from a property name and | ||
iterable of values. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,16 +24,18 @@ def _cycles_equal(c1, c2): | |
|
||
|
||
def test_creation(): | ||
c = cycler('c', 'rgb') | ||
c = cycler(c='rgb') | ||
yield _cycler_helper, c, 3, ['c'], [['r', 'g', 'b']] | ||
c = cycler('c', list('rgb')) | ||
c = cycler(c=list('rgb')) | ||
yield _cycler_helper, c, 3, ['c'], [['r', 'g', 'b']] | ||
c = cycler(cycler(c='rgb')) | ||
yield _cycler_helper, c, 3, ['c'], [['r', 'g', 'b']] | ||
|
||
|
||
def test_compose(): | ||
c1 = cycler('c', 'rgb') | ||
c2 = cycler('lw', range(3)) | ||
c3 = cycler('lw', range(15)) | ||
c1 = cycler(c='rgb') | ||
c2 = cycler(lw=range(3)) | ||
c3 = cycler(lw=range(15)) | ||
# addition | ||
yield _cycler_helper, c1+c2, 3, ['c', 'lw'], [list('rgb'), range(3)] | ||
yield _cycler_helper, c2+c1, 3, ['c', 'lw'], [list('rgb'), range(3)] | ||
|
@@ -54,75 +56,84 @@ def test_compose(): | |
|
||
|
||
def test_inplace(): | ||
c1 = cycler('c', 'rgb') | ||
c2 = cycler('lw', range(3)) | ||
c1 = cycler(c='rgb') | ||
c2 = cycler(lw=range(3)) | ||
c2 += c1 | ||
yield _cycler_helper, c2, 3, ['c', 'lw'], [list('rgb'), range(3)] | ||
|
||
c3 = cycler('c', 'rgb') | ||
c4 = cycler('lw', range(3)) | ||
c3 = cycler(c='rgb') | ||
c4 = cycler(lw=range(3)) | ||
c3 *= c4 | ||
target = zip(*product(list('rgb'), range(3))) | ||
yield (_cycler_helper, c3, 9, ['c', 'lw'], target) | ||
|
||
|
||
def test_constructor(): | ||
c1 = cycler('c', 'rgb') | ||
c2 = cycler('ec', c1) | ||
c1 = cycler(c='rgb') | ||
c2 = cycler(ec=c1) | ||
yield _cycler_helper, c1+c2, 3, ['c', 'ec'], [['r', 'g', 'b']]*2 | ||
c3 = cycler('c', c1) | ||
c3 = cycler(c=c1) | ||
yield _cycler_helper, c3+c2, 3, ['c', 'ec'], [['r', 'g', 'b']]*2 | ||
|
||
# addition using cycler() | ||
yield (_cycler_helper, cycler(c='rgb', lw=range(3)), | ||
3, ['c', 'lw'], [list('rgb'), range(3)]) | ||
yield (_cycler_helper, cycler(lw=range(3), c='rgb'), | ||
3, ['c', 'lw'], [list('rgb'), range(3)]) | ||
# Purposely mixing them | ||
yield (_cycler_helper, cycler(c=range(3), lw=c1), | ||
3, ['c', 'lw'], [range(3), list('rgb')]) | ||
|
||
|
||
def test_failures(): | ||
c1 = cycler('c', 'rgb') | ||
c2 = cycler('c', c1) | ||
c1 = cycler(c='rgb') | ||
c2 = cycler(c=c1) | ||
assert_raises(ValueError, add, c1, c2) | ||
assert_raises(ValueError, iadd, c1, c2) | ||
assert_raises(ValueError, mul, c1, c2) | ||
assert_raises(ValueError, imul, c1, c2) | ||
|
||
c3 = cycler('ec', c1) | ||
c3 = cycler(ec=c1) | ||
|
||
assert_raises(ValueError, cycler, 'c', c2 + c3) | ||
assert_raises(ValueError, cycler, c=c2+c3) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. never mind |
||
|
||
|
||
def test_simplify(): | ||
c1 = cycler('c', 'rgb') | ||
c2 = cycler('ec', c1) | ||
c1 = cycler(c='rgb') | ||
c2 = cycler(ec=c1) | ||
for c in [c1 * c2, c2 * c1, c1 + c2]: | ||
yield _cycles_equal, c, c.simplify() | ||
|
||
|
||
def test_multiply(): | ||
c1 = cycler('c', 'rgb') | ||
c1 = cycler(c='rgb') | ||
yield _cycler_helper, 2*c1, 6, ['c'], ['rgb'*2] | ||
|
||
c2 = cycler('ec', c1) | ||
c2 = cycler(ec=c1) | ||
c3 = c1 * c2 | ||
|
||
yield _cycles_equal, 2*c3, c3*2 | ||
|
||
|
||
def test_mul_fails(): | ||
c1 = cycler('c', 'rgb') | ||
c1 = cycler(c='rgb') | ||
assert_raises(TypeError, mul, c1, 2.0) | ||
assert_raises(TypeError, mul, c1, 'a') | ||
assert_raises(TypeError, mul, c1, []) | ||
|
||
|
||
def test_getitem(): | ||
c1 = cycler('lw', range(15)) | ||
c1 = cycler(lw=range(15)) | ||
widths = list(range(15)) | ||
for slc in (slice(None, None, None), | ||
slice(None, None, -1), | ||
slice(1, 5, None), | ||
slice(0, 5, 2)): | ||
yield _cycles_equal, c1[slc], cycler('lw', widths[slc]) | ||
yield _cycles_equal, c1[slc], cycler(lw=widths[slc]) | ||
|
||
|
||
def test_fail_getime(): | ||
c1 = cycler('lw', range(15)) | ||
c1 = cycler(lw=range(15)) | ||
assert_raises(ValueError, Cycler.__getitem__, c1, 0) | ||
assert_raises(ValueError, Cycler.__getitem__, c1, [0, 1]) | ||
|
||
|
@@ -135,11 +146,11 @@ def _repr_tester_helper(rpr_func, cyc, target_repr): | |
|
||
|
||
def test_repr(): | ||
c = cycler('c', 'rgb') | ||
c2 = cycler('lw', range(3)) | ||
c = cycler(c='rgb') | ||
c2 = cycler(lw=range(3)) | ||
|
||
c_sum_rpr = "(cycler('c', ['r', 'g', 'b']) + cycler('lw', [0, 1, 2]))" | ||
c_prod_rpr = "(cycler('c', ['r', 'g', 'b']) * cycler('lw', [0, 1, 2]))" | ||
c_sum_rpr = "(cycler(c=['r', 'g', 'b']) + cycler(lw=[0, 1, 2]))" | ||
c_prod_rpr = "(cycler(c=['r', 'g', 'b']) * cycler(lw=[0, 1, 2]))" | ||
|
||
yield _repr_tester_helper, '__repr__', c + c2, c_sum_rpr | ||
yield _repr_tester_helper, '__repr__', c * c2, c_prod_rpr | ||
|
@@ -152,7 +163,7 @@ def test_repr(): | |
|
||
|
||
def test_call(): | ||
c = cycler('c', 'rgb') | ||
c = cycler(c='rgb') | ||
c_cycle = c() | ||
assert_true(isinstance(c_cycle, cycle)) | ||
j = 0 | ||
|
@@ -171,14 +182,14 @@ def _eq_test_helper(a, b, res): | |
|
||
|
||
def test_eq(): | ||
a = cycler('c', 'rgb') | ||
b = cycler('c', 'rgb') | ||
a = cycler(c='rgb') | ||
b = cycler(c='rgb') | ||
yield _eq_test_helper, a, b, True | ||
yield _eq_test_helper, a, b[::-1], False | ||
c = cycler('lw', range(3)) | ||
c = cycler(lw=range(3)) | ||
yield _eq_test_helper, a+c, c+a, True | ||
yield _eq_test_helper, a+c, c+b, True | ||
yield _eq_test_helper, a*c, c*a, False | ||
yield _eq_test_helper, a, c, False | ||
d = cycler('c', 'ymk') | ||
d = cycler(c='ymk') | ||
yield _eq_test_helper, b, d, False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-> "from a single positional argument or from one or more keyword arguments."