# ----------------- # list comprehensions # ----------------- # basics: a = ['' for a in [1]] #? str() a[0] #? ['insert'] a.insert a = [a for a in [1]] #? int() a[0] y = 1.0 # Should not leak. [y for y in [3]] #? float() y a = [a for a in (1, 2)] #? int() a[0] a = [a for a,b in [(1,'')]] #? int() a[0] a = [a for (a,b) in [(1,'')]] #? int() a[0] arr = [1,''] a = [a for a in arr] #? int() a[0] #? str() a[1] #? int() str() a[2] a = [a if 1.0 else '' for a in [1] if [1.0]] #? int() str() a[0] # name resolve should be correct left, right = 'a', 'b' left, right = [x for x in (left, right)] #? str() left # with a dict literal #? int() [a for a in {1:'x'}][0] # list comprehensions should also work in combination with functions def _listen(arg): for x in arg: #? str() x _listen(['' for x in [1]]) #? ([str for x in []])[0] # ----------------- # nested list comprehensions # ----------------- b = [a for arr in [[1, 1.0]] for a in arr] #? int() b[0] #? float() b[1] b = [arr for arr in [[1, 1.0]] for a in arr] #? int() b[0][0] #? float() b[1][1] b = [a for arr in [[1]] if '' for a in arr if ''] #? int() b[0] b = [b for arr in [[[1.0]]] for a in arr for b in a] #? float() b[0] #? str() [x for x in 'chr'][0] # From GitHub #26 #? list() a = [[int(v) for v in line.strip().split() if v] for line in ["123", str(), "123"] if line] #? list() a[0] #? int() a[0][0] # From GitHub #1524 #? [nothing for nothing, _ in [1]][0] # ----------------- # generator comprehensions # ----------------- left, right = (i for i in (1, '')) #? int() left #? str() right gen = (i for i in (1,)) #? int() next(gen) #? gen[0] gen = (a for arr in [[1.0]] for a in arr) #? float() next(gen) #? int() (i for i in (1,)).send() # issues with different formats left, right = (i for i in ('1', 2)) #? str() left #? int() right # ----------------- # name resolution in comprehensions. # ----------------- def x(): """Should not try to resolve to the if hio, which was a bug.""" #? 22 [a for a in h if hio] if hio: pass # ----------------- # slices # ----------------- #? list() foo = [x for x in [1, '']][:1] #? int() foo[0] #? str() foo[1] # ----------------- # In class # ----------------- class X(): def __init__(self, bar): self.bar = bar def foo(self): x = [a for a in self.bar][0] #? int() x return x #? int() X([1]).foo() # ----------------- # dict comprehensions # ----------------- #? int() list({a - 1: 3 for a in [1]})[0] d = {a - 1: b for a, b in {1: 'a', 3: 1.0}.items()} #? int() list(d)[0] #? str() float() d.values()[0] #? str() d[0] #? float() str() d[1] #? float() d[2] # ----------------- # set comprehensions # ----------------- #? set() {a - 1 for a in [1]} #? set() {a for a in range(10)} #? int() [x for x in {a for a in range(10)}][0] #? int() {a for a in range(10)}.pop() #? float() str() {b for a in [[3.0], ['']] for b in a}.pop() #? int() next(iter({a for a in range(10)})) #? int() [a for a in {1, 2, 3}][0] # ----------------- # syntax errors # ----------------- # Issue #1146 #? ['list'] [int(str(x.value) for x in list def reset_missing_bracket(): pass # ----------------- # function calls # ----------------- def foo(arg): return arg x = foo(x for x in [1]) #? int() next(x) #? x[0] # While it's illegal to have more than one argument, when a generator # expression is involved, it's still a valid parse tree and Jedi should still # work (and especially not raise Exceptions). It's debatable wheter inferring # values for invalid statements is a good idea, but not failing is a must. #? int() next(foo(x for x in [1], 1)) def bar(x, y): return y #? str() next(bar(x for x in [1], x for x in ['']))