<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>Hey,</div><div><br></div><div><b>[tl;dr (1) Prototype working<span class="Apple-tab-span" style="white-space:pre">        </span>(2) Dynamic language = limited potential<span class="Apple-tab-span" style="white-space:pre">        </span>(3) Function annotations and</b></div><div><b>getting the ball rolling on annotation interoperability schemes]</b></div><div><br></div><div>I have a working prototype of the system at&nbsp;<a href="https://github.com/rmcgibbo/ipython/tree/functab">https://github.com/rmcgibbo/ipython/tree/functab</a>.</div><div>Currently, the only type of matches that are supported are for enumerated string literals.</div><div>I will be adding more soon, and making the interface such that it is easy to extend the code with</div><div>new argument specific tab completion logic. The heavy lifting is done I think.</div><div><br></div><div>Here's what you can do currently:</div><div><br></div><div><div>In [1]: from IPython.extensions.customtab import tab_completion</div><div><br></div><div>In [2]: @tab_completion(mode=['read', 'write'])</div><div>&nbsp; &nbsp;...: def my_io(fname, mode):</div><div>&nbsp; &nbsp;...: &nbsp; &nbsp; print 'lets go now!'</div><div>&nbsp; &nbsp;...: &nbsp; &nbsp;&nbsp;</div><div><br></div><div>In [3]: my_io('f.tgz', &lt;TAB&gt;</div><div>'read' &nbsp; 'write' &nbsp;</div></div><div><br></div><div>(or if there's only one matching completion, it'll obviously just fill in)</div><div><br></div><div>So when your cursor is in place to be adding the second argument, it will do tab completions based on</div><div>two static strings read from the decorator. It pretty much as you'd expect, supporting keyword args, etc.</div><div><br></div><div>The one thing that's tricky is dealing with quotation mark literals (' and ") in readline. This was my first</div><div>time coding against readline, so maybe I was making some rookie mistakes, but it seems to me like if</div><div>you don't play any tricks, the quotation marks are not treated correctly. When the current token is <font class="Apple-style-span" face="Courier">'"rea'</font>,</div><div>as if you've just started typing "read", and you hit tab, readline seems to tokenize the line and associate</div><div>the opening quotation mark with the previous token, not the current one. This means that if you include it</div><div>in the completion that you give, and you hit tab, the line will end up with TWO opening quotation marks,</div><div>ala <font class="Apple-style-span" face="Courier">'""read'.&nbsp;</font>(And it'll keep going if you keep hitting tab). I had to hack my way around this, but if</div><div>anyone has any suggestions I'm all ears.</div><div><br></div><div>---</div><div><br></div><div>As Tom said, there's a lot you could do with this -- enumerated string literals are just the tip of the</div></div><div>iceberg. Some other ones include glob-completed string literals for filenames, type-based&nbsp;</div><div>matching of python&nbsp;objects in the current namespace (i.e. only show tab completions for ndarray</div><div>objects in your session, etc).</div><div><br></div><div>You obviously can't do as much as you could in a statically typed language -- if you have type-based tab</div><div>completion looking for ndarray objects, you're not going to be able to infer that since the return value of&nbsp;</div><div>some random function like&nbsp;np.random.randn is going to be an ndarray, you could tab complete that too.</div><div>While things like type checking can be done with decorators / annotations, this isn't really the place. In particular,</div><div>the code for tab completion gets evaluated before you as a user ever hit enter and execute your line of</div><div>code -- and itsnot appropriate to actually exec anything -- so there's no way to know the type of the first</div><div>argument to a function like&nbsp;foo(bar(x), 1&lt;TAB&gt; at the time that the tab is executed.</div><div><br></div><div>----</div><div><br></div><div>As to the decorator vs function annotation syntax, I am hesitant to use annotations for a few reasons. First, selfishly,</div><div>I don't&nbsp;use python3. (I would, but I depend on PyTabes for everything, and it isn't py3k ready). Without the</div><div>syntactical support, manually&nbsp;attaching __annotations__ to functions seems like a lame api.</div><div><br></div><div>Second, in order to do annotations "right" in such a way that two independent project don't have annotation semantics</div><div>that fail to interoperate, everyone needs to agree on some system. If one library expects the annotations to be strings</div><div>(or to mean a &nbsp;specific thing, like a type for typechecking) and another library expects something different, then everyone is</div><div>in a bad spot.&nbsp;<a href="http://www.python.org/dev/peps/pep-3107/">PEP3107</a>&nbsp;seems to want some convention to&nbsp;"develop organically". As the author of the PEP said on</div><div>Python-ideas:</div><div><br></div><div><pre style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div></div></pre></div><blockquote type="cite"><div><pre style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div>When the first big project like Zope or Twisted announces that "we will do
annotation interop like so...", everyone else will be pressured to
line up behind them.</div></pre></div><div><pre style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;"><div>I don't want to pick a mechanism,  only to have to roll
another release when Zope or Twisted or some other big project pushes
out their own solution.</div></pre></div></blockquote><div>But, on the other hand, maybe there's no time like the present to start, and although the PEP was finalized in 2010,&nbsp;</div><div>and it doesn't seem like Django or any other big package is using annotations, so maybe we should lead the way?</div><div><br></div><div>In that spirit, I propose two possible schemes for annotation interoperability:</div><div><br></div><div>(1) All the annotations should be dicts. That way we can put tab-complete specific stuff under the 'tab' key and other</div><div>libraries/features can put their stuff under a different key, like <font class="Apple-style-span" face="Courier">'type'</font> or &nbsp;what have you. One advantage are that it's</div><div>simple. On the other hand, its kind of verbose, and IMO ugly.</div><div><br></div><div><font class="Apple-style-span" face="Courier">def my_io(fname, mode : {'tab': ['read', 'write']}):</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; pass</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier"><div style="font-family: Helvetica; "><font class="Apple-style-span" face="Courier">def my_io(fname, mode : {'tab': ['read', 'write'], 'foo':'bar'}):</font></div><div style="font-family: Helvetica; "><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; pass</font></div></font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div>(2). Inspired by&nbsp;<a href="https://en.wikipedia.org/wiki/Ggplot2">ggplot</a>, where you compose plots by <u>summing</u> components, the annotations could be the sum of</div><div>objects that overload <font class="Apple-style-span" face="Courier">__add__</font>, like:</div><div><br></div><div><font class="Apple-style-span" face="Courier">def my_io(fname, mode : tab('read', 'write'))</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp;pass</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div>or&nbsp;</div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">def my_io(fname, mode : tab('read', 'write') + typecheck(str)):</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; pass</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div>Where <font class="Apple-style-span" face="Courier">tab</font> and <font class="Apple-style-span" face="Courier">typecheck</font> are something&nbsp;like:</div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">class tab(object):</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; def __init__(self, *args, **kwargs):</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; self.args = args</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; self.kwargs = kwargs</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; self.next = None</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; self.prev = None</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; def __add__(self, other):</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; if not hasattr(other, '__add__'):</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise ValueError('"{}" must also be composable'.format(other))</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; self.next = other</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; other.prev = self</font></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; &nbsp; &nbsp; return other</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div>Then you could basically recover something analogous to the dictionary in&nbsp;proposal one</div><div>by walking through the next/prev pointers. The advantages of this are chiefly visual.&nbsp;</div><div><br></div><div>Obviously other things like lists or tuples or generic iterables could be done too.</div><div><br></div><div><div><font class="Apple-style-span" face="Courier">def my_io(fname, mode : (tab('read', 'write'), typecheck(str))):</font></div></div><div><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; pass</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">or</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier"><div style="font-family: Helvetica; "><div><font class="Apple-style-span" face="Courier">def my_io(fname, mode : [tab('read', 'write'), typecheck(str)]):</font></div></div><div style="font-family: Helvetica; "><font class="Apple-style-span" face="Courier">&nbsp; &nbsp; pass</font></div></font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div>With some cleverness, it might be possible to add an <font class="Apple-style-span" face="Courier">__iter__</font> method to the tab&nbsp;class that</div><div>would let you turn the sum into a list via list(iterable), such&nbsp;that via polymorphism the ggplot</div><div>style and the tuple/list style could exist side-by-side.</div><div><br></div><div>Basically, IMHO, using function annotation system requires some serious thought -- probably</div><div>above my pay grade -- to do right.</div><div><br></div><div>(Sorry this email was so long)</div><div><br></div><div>-Robert</div><div><br></div><div><div><div><div><div>On Nov 29, 2012, at 6:38 AM, Tom Dimiduk wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">
  
    <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
  
  <div text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">That looks pretty great.&nbsp; I would use
      something like that.&nbsp; <br>
      <br>
      For the filename('.txt'), it could be handy to be able to pass
      arbitrary globs (as in for glob.glob).&nbsp; You could still default to
      matching against the end of the string for extensions, but adding
      the glob support costs little (since you probably want to use glob
      internally anyway.&nbsp; <br>
      <br>
      For extra (and unnecessary) fancyness, I could also see use cases
      for <br>
      from from tablib import tabcompletion, instance<br>
      class bar:<br>
      &nbsp;&nbsp;&nbsp; pass<br>
      @tabcompletion(foo=instance(bar))<br>
      to be able to only complete for specific types of objects for
      other parameters (it would do an isinstance test).&nbsp; <br>
      <br>
      Even more bonus points if the decorator could parse numpy styled
      docstrings to grab that kind of information about parameters.&nbsp; I
      guess at this point you could do type checking, file existence
      checking, and a variety of other fun stuff there as well once you
      have that information, but that is almost certainly going out of
      the scope of your proposal.&nbsp; <br>
      <br>
      Sorry if I am growing your proposal too much, the basic thing you
      proposed would still be very useful.&nbsp; If I can grab some spare
      mental cycles, I would collaborate with you on it if you end up
      writing it.&nbsp; <br>
      <br>
      Tom<br>
      <br>
      On 11/29/2012 05:28 AM, Robert McGibbon wrote:<br>
    </div>
    <blockquote cite="mid:669615BA-66DA-4CA6-8848-ED64BC4E3710@gmail.com" type="cite">
      <div>Hi,</div>
      <div><br>
      </div>
      Good spot,&nbsp;Matthias.&nbsp;I didn't see that method was already exposed
      -- I was just looking at IPCompleter.matchers, which what that
      method inserts into.
      <div>
        <div><br>
        </div>
        <div>Annotations are cool, but they're not obviously composable.
          I worry that if I use them for this and then fix one syntax of
          how the annotation is parsed, and somebody else</div>
        <div>is using annotations in their lib for something else, the
          two schemes won't be able to interoperate. Also they're py3k
          only.</div>
        <div><br>
        </div>
        <div>My preferred syntax would be</div>
        <div><br>
        </div>
        <div>from tablib import tabcompletion, filename,</div>
        <div><br>
        </div>
        <div>@tabcompletion(fname=filename, mode=['r', 'w'])</div>
        <div>def load(fname, mode, other_argument):</div>
        <div>&nbsp; &nbsp; pass</div>
        <div><br>
        </div>
        <div>or maybe with a parameterized filename to get specific
          extensions</div>
        <div><br>
        </div>
        <div>@tabcompletion(fname=filename('.txt'))</div>
        <div>def f(fname, other_argument):</div>
        <div>&nbsp; &nbsp; pass</div>
        <div><br>
        </div>
        <div>Is this something that other people would be interested in?</div>
        <div><br>
        </div>
        <div>-Robert</div>
        <div><br>
        </div>
        <div>
          <div>
            <div>On Nov 29, 2012, at 2:02 AM, Matthias BUSSONNIER wrote:</div>
            <br class="Apple-interchange-newline">
            <blockquote type="cite">
              <div style="word-wrap: break-word; -webkit-nbsp-mode:
                space; -webkit-line-break: after-white-space; ">Hi,&nbsp;
                <div><br>
                </div>
                <div>I may be wrong, but IIRC you can insert your own
                  completer in the IPython &nbsp;completer chain and decide
                  to filter the previous completion.</div>
                <div><br>
                </div>
                <div>You should be able to have a custom completer that
                  just forward the previous completion in most cases,&nbsp;</div>
                <div>And just do a dir completion if the object
                  is&nbsp;np.loadtxt in your case (or look at __annotations__
                  if you wish).</div>
                <div><br>
                </div>
                <div>I've found one reference to inserting custom
                  completer here</div>
                <div><a moz-do-not-send="true" href="http://ipython.org/ipython-doc/dev/api/generated/IPython.core.interactiveshell.html?highlight=interactiveshell#IPython.core.interactiveshell.InteractiveShell.set_custom_completer">http://ipython.org/ipython-doc/dev/api/generated/IPython.core.interactiveshell.html?highlight=interactiveshell#IPython.core.interactiveshell.InteractiveShell.set_custom_completer</a></div>
                <div><br>
                </div>
                <div><br>
                </div>
                <div>--&nbsp;</div>
                <div>Matthias</div>
                <div><br>
                  <div>
                    <div>Le 29 nov. 2012 à 10:27, Aaron Meurer a écrit :</div>
                    <br class="Apple-interchange-newline">
                    <blockquote type="cite">
                      <div>I've often thought this as well. &nbsp;Probably a
                        full-blown IPEP is in<br>
                        order here. &nbsp;Perhaps __annotations__ would be
                        the correct way to go<br>
                        here.<br>
                        <br>
                        Aaron Meurer<br>
                        <br>
                        On Thu, Nov 29, 2012 at 12:58 AM, Robert
                        McGibbon &lt;<a moz-do-not-send="true" href="mailto:rmcgibbo@gmail.com">rmcgibbo@gmail.com</a>&gt;
                        wrote:<br>
                        <blockquote type="cite">Hey,<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">Tab completion in
                          IPython is one of the things that makes it so
                          useful,<br>
                        </blockquote>
                        <blockquote type="cite">especially the context
                          specific tab completion for things like "from
                          ..."<br>
                        </blockquote>
                        <blockquote type="cite">where only packages, or
                          obviously the special completion for
                          attributes when<br>
                        </blockquote>
                        <blockquote type="cite">the line contains a dot.<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">I use IPython for
                          interactive data analysis a lot, and one of
                          the most<br>
                        </blockquote>
                        <blockquote type="cite">frequent operations is
                          loading up data with something like
                          numpy.loadtxt()<br>
                        </blockquote>
                        <blockquote type="cite">or various related
                          functions.<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">It would be really
                          awesome if we could annotate functions to
                          interact with<br>
                        </blockquote>
                        <blockquote type="cite">the tab completion
                          system, perhaps for instance saying that
                          argument 0 to<br>
                        </blockquote>
                        <blockquote type="cite">numpy.loadtxt() is
                          supposed to be a filename, so let's give
                          tab-complete<br>
                        </blockquote>
                        <blockquote type="cite">suggestions that try to
                          look for directories/files. Some functions
                          only<br>
                        </blockquote>
                        <blockquote type="cite">files with specific
                          extensions, so you could filter based on that
                          or<br>
                        </blockquote>
                        <blockquote type="cite">whatever.<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">By hacking on the code
                          for completerlib.py:cd_completer, I sketched
                          out a<br>
                        </blockquote>
                        <blockquote type="cite">little demo of what you
                          could do with this: <a moz-do-not-send="true" href="https://gist.github.com/4167151">https://gist.github.com/4167151</a>.<br>
                        </blockquote>
                        <blockquote type="cite">The architecture is
                          totally wrong, but it lets you get behavior
                          like:<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">```<br>
                        </blockquote>
                        <blockquote type="cite">In [1]: ls<br>
                        </blockquote>
                        <blockquote type="cite">datfile.dat &nbsp;dir1/
                          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir2/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.gz &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;random_junk
                          &nbsp;test.py<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">In [2]:
                          directory_as_a_variable = 'sdfsfsd'<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">In [3]: f =
                          np.loadtxt(&lt;TAB&gt;<br>
                        </blockquote>
                        <blockquote type="cite">datfile.dat &nbsp;dir1/
                          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir2/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file.gz<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">In [4]:
                          normal_function(&lt;TAB&gt;<br>
                        </blockquote>
                        <blockquote type="cite">Display all 330
                          possibilities? (y or n)<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">In [5]: g =
                          np.loadtxt(di&lt;TAB&gt;<br>
                        </blockquote>
                        <blockquote type="cite">dict
                          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir1/
                          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;directory_as_a_variable<br>
                        </blockquote>
                        <blockquote type="cite">divmod<br>
                        </blockquote>
                        <blockquote type="cite">dir
                          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir2/
                          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;directory_of_my_choosing<br>
                        </blockquote>
                        <blockquote type="cite">```<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">Basically hitting the
                          tab completion, when np.loadtxt is on the
                          input line,<br>
                        </blockquote>
                        <blockquote type="cite">only shows directories
                          and files that end with a certain extension.
                          If you<br>
                        </blockquote>
                        <blockquote type="cite">start to type in the
                          name of an object in your namespace, it'll
                          show up too,<br>
                        </blockquote>
                        <blockquote type="cite">but only once you've
                          typed in more than 1 matching character.<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">The implementation in my
                          gist is pretty lame. The way I've coded it up,
                          the<br>
                        </blockquote>
                        <blockquote type="cite">special behavior is
                          based on simply finding the string
                          "np.loadtxt" on the<br>
                        </blockquote>
                        <blockquote type="cite">input line, not on the
                          actual function. This means you can't really
                          make the<br>
                        </blockquote>
                        <blockquote type="cite">behavior specific to
                          your position in the argument list (i.e. I
                          know that<br>
                        </blockquote>
                        <blockquote type="cite">the first arg is a
                          filename, and so should be tab completed like
                          this, but<br>
                        </blockquote>
                        <blockquote type="cite">the other ones are not).
                          I suspect the right way to do the
                          implementation is<br>
                        </blockquote>
                        <blockquote type="cite">via function decorators
                          to specify the behavior and then adding to<br>
                        </blockquote>
                        <blockquote type="cite">IPCompleter instead.<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">I think I'm up for
                          giving this a shot.<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">Thoughts? Is this a
                          feature anyone else would find interesting?<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">-Robert<br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        <blockquote type="cite">_______________________________________________<br>
                        </blockquote>
                        <blockquote type="cite">IPython-dev mailing list<br>
                        </blockquote>
                        <blockquote type="cite"><a moz-do-not-send="true" href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a><br>
                        </blockquote>
                        <blockquote type="cite"><a moz-do-not-send="true" href="http://mail.scipy.org/mailman/listinfo/ipython-dev">http://mail.scipy.org/mailman/listinfo/ipython-dev</a><br>
                        </blockquote>
                        <blockquote type="cite"><br>
                        </blockquote>
                        _______________________________________________<br>
                        IPython-dev mailing list<br>
                        <a moz-do-not-send="true" href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a><br>
                        <a moz-do-not-send="true" href="http://mail.scipy.org/mailman/listinfo/ipython-dev">http://mail.scipy.org/mailman/listinfo/ipython-dev</a><br>
                      </div>
                    </blockquote>
                  </div>
                  <br>
                </div>
              </div>
              _______________________________________________<br>
              IPython-dev mailing list<br>
              <a moz-do-not-send="true" href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a><br>
              <a class="moz-txt-link-freetext" href="http://mail.scipy.org/mailman/listinfo/ipython-dev">http://mail.scipy.org/mailman/listinfo/ipython-dev</a><br>
            </blockquote>
          </div>
          <br>
        </div>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
IPython-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a>
<a class="moz-txt-link-freetext" href="http://mail.scipy.org/mailman/listinfo/ipython-dev">http://mail.scipy.org/mailman/listinfo/ipython-dev</a>
</pre>
    </blockquote>
    <br>
  </div>

_______________________________________________<br>IPython-dev mailing list<br><a href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a><br>http://mail.scipy.org/mailman/listinfo/ipython-dev<br></blockquote></div><br></div></div></div></body></html>