On 27 February 2012 19:27, Mark Janssen
<dreamingforward@gmail.com> wrote:
On Fri, Feb 17, 2012 at 10:08 PM, Steven D'Aprano <
steve@pearwood.info> wrote:
> Mark Janssen wrote:
>> 1. Execution context determined by outer-scope doctest defintions.
>
> Can you give an example of how you would like this to work?
>
Sure, I wish I had a good example off the top of my head, but perhaps
this will convey the idea:
class MyClass():
"""Yadda Yadda: foo's bars.
>>> m = MyClass({some, sufficiently, interesting, initialization}) #tPOINT1: this variable (m) now accessible by all methods.
"foobar check" #POINT2: possible output here is a useful test case
not well-definable elsewhere without losing context.
"""
def method1(self, other):
"""Method method method method.
>>> m.method("foo") #Now we see m is already defined and useable.
"bar"
"""
def meth2(self, other):
"""Method to foo all bars
>>> m.method("bar") #would have to decide whether a fresh m is
redefined with each innerscope doctest (if we want side-effects to
carry across inner doctests).
(END)
This is a basic example, sorry it's rather crude. There's probably a
better example. (Think establishing a network socket connection or
something in the class' doc which is then used by all the methods, for
example.)
>> 2. Smart Comparisons that will detect output of a non-ordered type
>> (dict/set), lift and recast it and do a real comparison.>
>
> I would love to see a doctest directive that accepted differences in output
> order, e.g. would match {1, 2, 3} and {3, 1, 2}. But I think that's a hard
> problem to solve in the general case.
I think this would be as simple as lifting the (string) output and
doing an eval("{1,2,3}")=={3,2,1}, or (for security) using
ast.literal_eval like Devin suggested.
How will that handle not-particularly-obscure code like this:
>>> class Foo(object):
... def __init__(self, a):
... self.a = a
... def __repr__(self):
... return '<Foo a=%r>' % self.a
...
>>> a = {Foo(1), Foo(2), Foo(3)}
>>> b = {Foo(4), Foo(5), Foo(6)}
>>> {'first': a, 'second': b}
{'second': set([<Foo a=4>, <Foo a=6>, <Foo a=5>]), 'first': set([<Foo a=3>, <Foo a=2>, <Foo a=1>])}
I don't think a *general* solution for unordered types is even possible because you can't parse arbitrary reprs.
All the best,
Michael
> I'd like a #3 as well: an abbreviated way to spell doctest directives,
> because they invariably push my tests well past the 80 character mark.
Hmm, seem like an alias could be defined easily enough, but I'll try
to think about this when I have more time.
mark