Skip to content

Show single underscore attributes before double underscore ones #528 #561

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

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add function to sort single underscore attributes before double under…
…score ones"
  • Loading branch information
wevial committed Sep 8, 2015
commit 599c8b31357e6ee79423847b07b005f7e414d37f
25 changes: 23 additions & 2 deletions bpython/autocomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ def matches(self, cursor_offset, line, **kwargs):
if not r.word.split('.')[-1].startswith('_'):
matches = set(match for match in matches
if not match.split('.')[-1].startswith('_'))
# MAYBE HERE 2 ??
Copy link
Member

Choose a reason for hiding this comment

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

Looks like a few comments made it in by accident

return matches

def locate(self, current_offset, line):
Expand Down Expand Up @@ -311,6 +312,8 @@ def attr_lookup(self, obj, expr, attr):
for word in words:
if self.method_match(word, n, attr) and word != "__builtins__":
matches.append("%s.%s" % (expr, word))
# print 'matches', matches
# ORGANIZE THE THINGS HERE MAYBE 1??
return matches

if py3:
Expand Down Expand Up @@ -543,13 +546,31 @@ def get_completer(completers, cursor_offset, line, **kwargs):
complete_magic_methods is a bool of whether we ought to complete
double underscore methods like __len__ in method signatures
"""

for completer in completers:
matches = completer.matches(cursor_offset, line, **kwargs)
if matches is not None:
return sorted(matches), (completer if matches else None)
if len(matches) > 0:
matches = sort_by_underscore(matches)
return matches, (completer if matches else None)
return [], None

def sort_by_underscore(matches):
"""Sort single underscore attributes before double underscore ones.
"""
matches = sorted(matches)
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't really matter, but I'd prefer matches.sort() instead of reassigning to the variables - I guess this keeps the matches list being passed in safe from modifications, but if we're doing this we should change the docstring from "sort asdfasdf" to "Returns a sorted list" because sort implies mutating the list imo.

if len(matches) == 0 or len(matches) == 1:
return matches
one_underscore = None
for i in xrange(1, len(matches)+1):
Copy link
Member

Choose a reason for hiding this comment

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

I bet we could do this with a single [].sort(key=lambda sug: (sug.startswith('_'), sug.startswith('__'), sug)) or similar

Copy link
Member

Choose a reason for hiding this comment

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

Or return sorted([m for m in matches if not m.startswith('_')]) + sorted([m for m in matches if m.startswith('_')]) + sorted([m for m in matches if m.startswith('__')])

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The list of matches starts with the name of the variable, etc. before the attribute (eg. ['t.__class__', 't.__format__', 't.__repr__', 't.__init__', 't._bar', 't._foo'] ) so that doesn't quite work unfortunately

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unless I'm sorting in the wrong place, which is totally plausible

Copy link
Member

Choose a reason for hiding this comment

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

Hm I didn't actually test these so they might not be right, but there just might be some nice way similar to one of these.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, [m for m in matches if m.startswith('_')] still selects the double underscore attributes.
Edit: gotcha.

Yeah, the way I did this is a bit hacky... I'll see if there's somewhere else where I can make this solution nicer

Copy link
Member

Choose a reason for hiding this comment

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

Ah ok so these won't actually work, but if there is some nice way to do
this in several steps without the for loop it could be nice. Either way,
the only real blocker right now is getting it passing the tests and getting
prints/comments out.

On Thu, Sep 10, 2015 at 12:20 PM, Wes E. Vial notifications@github.com
wrote:

In bpython/autocomplete.py
#561 (comment):

 return [], None

+def sort_by_underscore(matches):

  • """Sort single underscore attributes before double underscore ones.
  • """
  • matches = sorted(matches)
  • if len(matches) == 0 or len(matches) == 1:
  •    return matches
    
  • one_underscore = None
  • for i in xrange(1, len(matches)+1):

Also, [m for m in matches if m.startswith('_')] still selects the double
underscore attributes.


Reply to this email directly or view it on GitHub
https://github.com/bpython/bpython/pull/561/files#r39180057.

i = -i
dot_i = matches[i].rfind('.') + 1
if matches[i][dot_i] == '_' and matches[i][dot_i+1] != '_':
one_underscore = i
else:
break
if one_underscore_i != None:
return matches[one_underscore:] + matches[:one_underscore]
return matches

def get_default_completer(mode=SIMPLE):
return (
Expand Down
6 changes: 6 additions & 0 deletions bpython/test/test_autocomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ def test_first_completer_returns_None(self):
b = completer(['a'])
self.assertEqual(autocomplete.get_completer([a, b], 0, ''), (['a'], b))

def test_completer_shows_single_underscore_before_double(self):
# TODO: do this!
a = completer([])



class TestCumulativeCompleter(unittest.TestCase):

Expand Down Expand Up @@ -263,6 +268,7 @@ def __getattr__(self, attr):
self.com.matches(3, 'a._', locals_=locals_))



class TestMagicMethodCompletion(unittest.TestCase):

def test_magic_methods_complete_after_double_underscores(self):
Expand Down