Added support for the __all__ += <module>.__all__ idiom for mutating the __all__ value. This idiom is used by numpy.

This commit is contained in:
Eric Traut 2020-10-02 10:55:24 -07:00
parent f0a231d7fc
commit b2882fd6be
3 changed files with 27 additions and 1 deletions

View File

@ -40,6 +40,7 @@ The following idioms are supported for defining the values contained within `__a
* `__all__ = ['a', b']`
* `__all__ += ['a', b']`
* `__all__ += submodule.__all__`
* `__all__.extend(['a', b'])`
* `__all__.append('a')`
* `__all__.remove('a')`

View File

@ -734,8 +734,10 @@ export class Binder extends ParseTreeWalker {
this._bindPossibleTupleNamedTarget(node.destExpression);
this._createAssignmentTargetFlowNodes(node.destExpression, /* walkTargets */ false, /* unbound */ false);
// Is this an assignment to dunder all?
// Is this an assignment to dunder all of the form
// __all__ += <expression>?
if (
node.operator === OperatorType.AddEqual &&
this._currentScope.type === ScopeType.Module &&
node.leftExpression.nodeType === ParseNodeType.Name &&
node.leftExpression.value === '__all__'
@ -743,6 +745,7 @@ export class Binder extends ParseTreeWalker {
const expr = node.rightExpression;
if (expr.nodeType === ParseNodeType.List) {
// Is this the form __all__ += ["a", "b"]?
expr.entries.forEach((listEntryNode) => {
if (
listEntryNode.nodeType === ParseNodeType.StringList &&
@ -752,6 +755,18 @@ export class Binder extends ParseTreeWalker {
this._dunderAllNames?.push(listEntryNode.strings[0].value);
}
});
} else if (
expr.nodeType === ParseNodeType.MemberAccess &&
expr.leftExpression.nodeType === ParseNodeType.Name &&
expr.memberName.value === '__all__'
) {
// Is this using the form "__all__ += <mod>.__all__"?
const namesToAdd = this._getDunderAllNamesFromImport(expr.leftExpression.value);
if (namesToAdd) {
namesToAdd.forEach((name) => {
this._dunderAllNames?.push(name);
});
}
}
}

View File

@ -7,6 +7,7 @@
// @filename: testpkg/__init__.py
// @library: true
//// from . import submod
//// from .submod2 import *
//// from submod import foofoofoo5, foofoofoo6, foofoofoo7, foofoofoo8
//// foofoofoo0: int = 0
//// foofoofoo1: int = 1
@ -20,6 +21,7 @@
//// __all__.remove("foofoofoo1")
//// __all__.remove("foofoofoo6")
//// __all__.append("foofoofoo0")
//// __all__ += submod2.__all__
// @filename: testpkg/submod.py
// @library: true
@ -31,6 +33,11 @@
//// __all__ += ["foofoofoo6"]
//// __all__.extend(["foofoofoo7"])
// @filename: testpkg/submod2.py
// @library: true
//// foofoofoo9: int = 9
//// __all__ = ["foofoofoo9"]
// @filename: .src/test.py
//// from testpkg import *
//// foofoofoo[|/*marker1*/|]
@ -56,6 +63,9 @@ await helper.verifyCompletion('exact', {
{
label: 'foofoofoo7',
},
{
label: 'foofoofoo9',
},
],
},
});