2
2
from unittest .mock import patch
3
3
import builtins
4
4
import rlcompleter
5
+ from test .support import MISSING_C_DOCSTRINGS
5
6
6
7
class CompleteMe :
7
8
""" Trivial class used in testing rlcompleter.Completer. """
@@ -40,21 +41,41 @@ def test_global_matches(self):
40
41
41
42
# test with a customized namespace
42
43
self .assertEqual (self .completer .global_matches ('CompleteM' ),
43
- [ 'CompleteMe(' ])
44
+ [ 'CompleteMe(' if MISSING_C_DOCSTRINGS else 'CompleteMe() ' ])
44
45
self .assertEqual (self .completer .global_matches ('eg' ),
45
46
['egg(' ])
46
47
# XXX: see issue5256
47
48
self .assertEqual (self .completer .global_matches ('CompleteM' ),
48
- [ 'CompleteMe(' ])
49
+ [ 'CompleteMe(' if MISSING_C_DOCSTRINGS else 'CompleteMe() ' ])
49
50
51
+ # TODO: RUSTPYTHON
52
+ @unittest .expectedFailure
50
53
def test_attr_matches (self ):
51
54
# test with builtins namespace
52
55
self .assertEqual (self .stdcompleter .attr_matches ('str.s' ),
53
56
['str.{}(' .format (x ) for x in dir (str )
54
57
if x .startswith ('s' )])
55
58
self .assertEqual (self .stdcompleter .attr_matches ('tuple.foospamegg' ), [])
56
- expected = sorted ({'None.%s%s' % (x , '(' if x != '__doc__' else '' )
57
- for x in dir (None )})
59
+
60
+ def create_expected_for_none ():
61
+ if not MISSING_C_DOCSTRINGS :
62
+ parentheses = ('__init_subclass__' , '__class__' )
63
+ else :
64
+ # When `--without-doc-strings` is used, `__class__`
65
+ # won't have a known signature.
66
+ parentheses = ('__init_subclass__' ,)
67
+
68
+ items = set ()
69
+ for x in dir (None ):
70
+ if x in parentheses :
71
+ items .add (f'None.{ x } ()' )
72
+ elif x == '__doc__' :
73
+ items .add (f'None.{ x } ' )
74
+ else :
75
+ items .add (f'None.{ x } (' )
76
+ return sorted (items )
77
+
78
+ expected = create_expected_for_none ()
58
79
self .assertEqual (self .stdcompleter .attr_matches ('None.' ), expected )
59
80
self .assertEqual (self .stdcompleter .attr_matches ('None._' ), expected )
60
81
self .assertEqual (self .stdcompleter .attr_matches ('None.__' ), expected )
@@ -64,7 +85,7 @@ def test_attr_matches(self):
64
85
['CompleteMe.spam' ])
65
86
self .assertEqual (self .completer .attr_matches ('Completeme.egg' ), [])
66
87
self .assertEqual (self .completer .attr_matches ('CompleteMe.' ),
67
- ['CompleteMe.mro(' , 'CompleteMe.spam' ])
88
+ ['CompleteMe.mro() ' , 'CompleteMe.spam' ])
68
89
self .assertEqual (self .completer .attr_matches ('CompleteMe._' ),
69
90
['CompleteMe._ham' ])
70
91
matches = self .completer .attr_matches ('CompleteMe.__' )
@@ -81,17 +102,41 @@ def test_attr_matches(self):
81
102
if x .startswith ('s' )])
82
103
83
104
def test_excessive_getattr (self ):
84
- # Ensure getattr() is invoked no more than once per attribute
105
+ """Ensure getattr() is invoked no more than once per attribute"""
106
+
107
+ # note the special case for @property methods below; that is why
108
+ # we use __dir__ and __getattr__ in class Foo to create a "magic"
109
+ # class attribute 'bar'. This forces `getattr` to call __getattr__
110
+ # (which is doesn't necessarily do).
85
111
class Foo :
86
112
calls = 0
113
+ bar = ''
114
+ def __getattribute__ (self , name ):
115
+ if name == 'bar' :
116
+ self .calls += 1
117
+ return None
118
+ return super ().__getattribute__ (name )
119
+
120
+ f = Foo ()
121
+ completer = rlcompleter .Completer (dict (f = f ))
122
+ self .assertEqual (completer .complete ('f.b' , 0 ), 'f.bar' )
123
+ self .assertEqual (f .calls , 1 )
124
+
125
+ def test_property_method_not_called (self ):
126
+ class Foo :
127
+ _bar = 0
128
+ property_called = False
129
+
87
130
@property
88
131
def bar (self ):
89
- self .calls += 1
90
- return None
132
+ self .property_called = True
133
+ return self ._bar
134
+
91
135
f = Foo ()
92
136
completer = rlcompleter .Completer (dict (f = f ))
93
137
self .assertEqual (completer .complete ('f.b' , 0 ), 'f.bar' )
94
- self .assertEqual (f .calls , 1 )
138
+ self .assertFalse (f .property_called )
139
+
95
140
96
141
def test_uncreated_attr (self ):
97
142
# Attributes like properties and slots should be completed even when
@@ -114,6 +159,9 @@ def test_complete(self):
114
159
self .assertEqual (completer .complete ('el' , 0 ), 'elif ' )
115
160
self .assertEqual (completer .complete ('el' , 1 ), 'else' )
116
161
self .assertEqual (completer .complete ('tr' , 0 ), 'try:' )
162
+ self .assertEqual (completer .complete ('_' , 0 ), '_' )
163
+ self .assertEqual (completer .complete ('match' , 0 ), 'match ' )
164
+ self .assertEqual (completer .complete ('case' , 0 ), 'case ' )
117
165
118
166
def test_duplicate_globals (self ):
119
167
namespace = {
@@ -134,7 +182,7 @@ def test_duplicate_globals(self):
134
182
# No opening bracket "(" because we overrode the built-in class
135
183
self .assertEqual (completer .complete ('memoryview' , 0 ), 'memoryview' )
136
184
self .assertIsNone (completer .complete ('memoryview' , 1 ))
137
- self .assertEqual (completer .complete ('Ellipsis' , 0 ), 'Ellipsis(' )
185
+ self .assertEqual (completer .complete ('Ellipsis' , 0 ), 'Ellipsis() ' )
138
186
self .assertIsNone (completer .complete ('Ellipsis' , 1 ))
139
187
140
188
if __name__ == '__main__' :
0 commit comments