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

Autocompletion: Fix issue #3723 -- ordering of completions for magic commands and variables with same name #3801

Closed
wants to merge 13 commits into from

Conversation

dpsanders
Copy link
Contributor

[ not for 1.0 ]

This PR fixes issue #3723.

The introduction of the %matplotlib magic broke the order of autocompletions in the sequence of commands described in #3723.

This PR fixes this by changing the order in which the completions are returned by the complete() function, by
introducing a custom key, called penalize_magics_key, which is passed to sorted to sort the various lists of completions assembled from different places.

penalize_magics_key moves the initial % or %% to the end of the key, so that the lexicographic string ordering gives "matplotlib" < "matplotlib%" < "matplotlib%%", but all of these are together in the completion list.

Added a test function test_magic_completion_order which tests that these orderings are correct.

pattern = re.compile("%+") # find %
m = pattern.match(word) # at the start of the string

print m
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgotten print.

@dpsanders
Copy link
Contributor Author

Requested changes have now been implemented.

Ready to merge.

@@ -177,6 +181,52 @@ def compress_user(path, tilde_expand, tilde_val):
return path


def uniquify(seq):
"""uniquify a list
i.e. remove duplicate elements, but preserving original order
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One blank line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uniquify function is not used in the current version, but it is an
alternative ordering method.
Should I just remove it?

On Fri, Jul 26, 2013 at 6:13 PM, Matthias Bussonnier <
notifications@github.com> wrote:

In IPython/core/completer.py:

@@ -177,6 +181,52 @@ def compress_user(path, tilde_expand, tilde_val):
return path

+def uniquify(seq):

  • """uniquify a list
  • i.e. remove duplicate elements, but preserving original order

One blank line.


Reply to this email directly or view it on GitHubhttps://github.com//pull/3801/files#r5436317
.

Dr. David P. Sanders

Profesor Titular "A" / Associate Professor
Departamento de Física, Facultad de Ciencias
Universidad Nacional Autónoma de México (UNAM)

dpsanders@gmail.com
http://sistemas.fciencias.unam.mx/~dsanders

Cubículo / office: #414, 4o. piso del Depto. de Física

Tel.: +52 55 5622 4965

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you can remove if it is not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@Carreau
Copy link
Member

Carreau commented Jul 29, 2013

I would be in favor of a more general way of "ordering" completions. And I am uncomfortable to have it for 1.0.
Also, this is also probably something that could be done totally in the frontend.

So even if it make sens, I'll stay neutral on this one for the time beeing.

@dpsanders
Copy link
Contributor Author

I believe this is ready to merge.

In my opinion, it should definitely go into 1.0 (despite @ivanov 's label) as a stop-gap measure until IPEP 11
is addressed. Otherwise people will be having problems completing on matplotlib for the next few months, which does not seem like a good idea!

@ivanov
Copy link
Member

ivanov commented Aug 5, 2013

it's not that big of a problem - most of the time we deal with plt when calling plots anyway.

The reason this is marked for 2.0 is because we already cut an alpha, and then a release candidate for 1.0, and are getting feedback from people who are testing this heavily so that we can release 1.0 that we're fairly confident doesn't have anything majorly broken, and whatever limitations there are should be documented. Completion is a pretty fundamental part of IPython, and delaying this until after 1.0 will actually give us more room to play with it, try new things and really get this right.

@dpsanders
Copy link
Contributor Author

OK, fair enough!

@Carreau
Copy link
Member

Carreau commented Aug 5, 2013

@fperez
Copy link
Member

fperez commented Aug 6, 2013

Yup, to reiterate @ivanov's comment above, there's absolutely no way this is 1.0 material. We're strictly in tiny-fixes and doc touch-up territory at this point.

@takluyver
Copy link
Member

@rmcgibbo, you were working on refactoring the tab completion stuff (IPEP 11). Have you already looked at anything like this? is there a clean way to work it into what you're doing?

@rmcgibbo
Copy link
Contributor

I really don't have the bandwidth to work on that proposal now. Sorry to leave you guys hanging.

@takluyver
Copy link
Member

Not to worry. Feel free to come back and pick it up whenever you're ready.

@ellisonbg
Copy link
Member

@takluyver and @dpsanders what do we want to do with this PR?

@takluyver
Copy link
Member

I'm reluctant to stick yet more complexity into the completer system when we know it's in need of a refactor, but on the other hand we don't know when IPEP 11 might get completed. I guess it depends on how much we want this feature.

@ellisonbg
Copy link
Member

I too am reluctant to add more complexity to the completer code. @fperez do you want to make the call on this one?

@ellisonbg
Copy link
Member

We talked to @fperez last week and we want to move forward with this PR, even without the larger completer refactor. But, @fperez thinks this can be done without using regular expressions (maybe just startswith?). @dpsanders do you want to see if you can simplify it a bit?

@dpsanders
Copy link
Contributor Author

@ellisonbg Apologies for the delay in replying. I'll give it a go when I have a free moment!

Basically all that it does is shift the initial % or %% of a magic to the end of the string, so this should indeed be pretty easy to do in a simple way.

@dpsanders
Copy link
Contributor Author

Have a look at the code in the very first commit of this PR. Is that the kind of thing you mean?:

 if word[0] == "%":  # if it's a magic command     
    return word[1:] + "%"   

@ellisonbg
Copy link
Member

Or:

if word.startswith('%'):
    return word.lstrip('%')

@dpsanders
Copy link
Contributor Author

Nice, thanks!

@fperez
Copy link
Member

fperez commented Sep 25, 2013

Quick note, the code suggested above by @ellisonbg won't quite do the correct penalization, as it will make %foo sort identical to foo, but we want it to sort after foo. We do need to put the % characters up at the end, as @dpsanders' original code did.

This alternative does the right thing:

def penalize_magics_key2(word):
    i = word.rfind('%')
    if i in (0,1):
        s = i+1
        return word[s:]+word[:s]
    else:
        return word

and in fact has better behavior than the one proposed here in some edge cases. I wrote up a quick analysis with checks and performance in a notebook so @dpsanders can check.

I would suggest using that code (appropriately commented explaining what's going on) instead. It has better behavior and is ~ 2x faster, in addition to being easier to understand for someone who's not a regular expression expert, since it only involves indexing into strings.

@fperez
Copy link
Member

fperez commented Sep 25, 2013

Ah, and one more thing: this PR needs a rebase.

@dpsanders
Copy link
Contributor Author

@fperez Great, thanks. I hope to get to it in the next couple of days, or otherwise at the weekend.

@dpsanders
Copy link
Contributor Author

@fperez Very nice notebook, thanks.
For some reason, your new version is not as fast on my machine.

I tried my original idea again -- just testing the first couple of characters and moving them to the end if necessary.
It's actually even faster, and arguably the code is clearer (though certainly less elegant!).
There are two versions, with and without testing for other % signs later in the string:

https://gist.github.com/6723952

(The final version of the code had a %timeit of 325 ns, which is in the notebook but for some reason does not seem to appear on nbviewer.)

Which version do you prefer?

@fperez
Copy link
Member

fperez commented Sep 27, 2013

Sure, we can go with that last one, it's actually easier to understand (clarity matters much more than performance here).

Note however that you must change w[0] to w[:1], otherwise it will throw an IndexError if the empty string is ever accessed for some reason (it shouldn't, but no point in leaving a crash path there waiting to be triggered).

Also keep in mind the need for a rebase.

@dpsanders
Copy link
Contributor Author

I have put the new code up but I am not understanding how/what to do for the rebase.
I am trying git rebase master,
but every commit from the branch seems to cause a conflict, and I don't understand how I should resolve them.
(I have looked at several tutorials, but without much success, sorry!)

dpsanders and others added 2 commits September 28, 2013 01:11
…laced the code with the simplest string-based version, removing the regex.
@dpsanders
Copy link
Contributor Author

I skipped all the commits except the last one for the rebase. (Is this legitimate...?)
This seems to have worked.
I have no idea why my username suddenly changed for the last commit...

@@ -499,6 +536,7 @@ def __init__(self, shell=None, namespace=None, global_namespace=None,
self.file_matches,
self.magic_matches,
self.python_func_kw_matches,
self.alias_matches,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dies not exist apparently. Due to @takluyver alias refactoring not so long ago ?

@Carreau
Copy link
Member

Carreau commented Sep 28, 2013

Your user name probably change because you did some commits on another machine where your git user name is not correctly set up. The user will match the email that is registered with $ git config user.email.

@dpsanders
Copy link
Contributor Author

I finally just reverted to the current master and reimplemented on top.

I seem to have made a mess with my github accounts though...

@Carreau
Copy link
Member

Carreau commented Sep 28, 2013

computo-fc seem to be dpsanders(at)ciencias.unam.mx
dpsanders is dpsanders(at)gmail.com

If it can helps you.

@dpsanders
Copy link
Contributor Author

Yes, thanks, I think that was the problem. And at some point I set the global user.name instead of the local one on the relevant repository.

@ellisonbg
Copy link
Member

@dpsanders is this PR ready for more review?

@dpsanders
Copy link
Contributor Author

Sorry for the delay in replying. From my point of view it's finished, so yes please go ahead and review.

@dpsanders
Copy link
Contributor Author

Of course, by now it probably needs rebasing again!

@Carreau
Copy link
Member

Carreau commented Oct 25, 2013

No need to rebase

@Carreau
Copy link
Member

Carreau commented Oct 26, 2013

Looks good to me.
From what I re-read all comment have been adressed.

@minrk minrk closed this in 689935c Oct 28, 2013
@minrk
Copy link
Member

minrk commented Oct 28, 2013

Merged, thanks!

@dpsanders
Copy link
Contributor Author

:) Thanks, Min!

@dpsanders
Copy link
Contributor Author

And thanks to everybody for comments and reviewing.

mattvonrocketstein pushed a commit to mattvonrocketstein/ipython that referenced this pull request Nov 3, 2014
Autocompletion: ordering of completions for magic commands and variables with same name

closes ipython#3723
closes ipython#3801
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants