Greg Ewing firstname.lastname@example.org wrote:
Maybe, instead of there being one ultra-global namespace for importing modules from, it should be part of a function's environment. By default a function invocation would inherit the "import environment" of it's caller, but the caller could override this to provide a more restricted environment.
This is a reasonable idea too.
It bears an intriguing similarity to scoping in general. One can put capabilities into local variables, and then functions and classes that you define inside that scope automatically have access to them. That doesn't work for separate modules, of course, which have no enclosing lexical scope.
So your proposal seems sort of like a kind of dynamic scoping for modules, but instead of the imported module having access to all variables in the scope of the "import" statement (the *lexical* scope of the import statement), it has access to specific ones -- either a special "variables accessible to imported modules" dict or specially flagged ones, or something.
For what it's worth, the solution to this problem in E is quite elegant. When code is loaded from a module, it is executed with optional arguments. So if your spam module requires a TCP socket, you can write (transliterating to Python syntax):
# Python with E's parameterized import import socket import spam(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
If spam needs access to the eggs module, you could write:
import eggs import spam(eggs)
But as Samuele Pedroni has pointed out  there are deeper problems here, namely that modules are currently singletons, which doesn't fit with the notion of parameterization. It also doesn't fit with security!
Consider a module that is safe to use if you give it your credit card number, and safe to use if you give it a network socket, but unsafe if you give it both!
Capabilities offer this kind of security -- you can arrange it so that nobody else can give privileges to an object, thus allowing you to give the object privileges which would otherwise be dangerous.
This is easy with objects in cap-Python, but not with modules:
ttt1 = TicTacToe() ttt1.verify_card_number(mycreditcard)
ttt2 = TicTacToe() ttt2.connect_to_server(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
So one design for cap-Python might say that only safe modules can be imported by cap-Python code. Every unsafe privilege would have to be granted by using references (passed as arguments, assigned to variables, etc.). No authority would ever be made available to capability-secured code through "import".
This might not be much of a loss, since all of the unsafe stuff that you can currently import -- socket, os, etc. -- is rather too coarse-grained anyway and will almost certainly be wrapped in a finer-grained interface before being given to capability-confined code.
http://zooko.com/ ^-- under re-construction: some new stuff, some broken links
So your proposal seems sort of like a kind of dynamic scoping for modules
Yes, it would be dynamic scoping of the import namespace.
The reason I think it needs to be dynamic rather than lexical is that it isn't really objects or functions that we want to allow or deny capabilities to, it's *users* (for some suitably general notion of "user"). It may be okay for a particular method to do something when it's called by one user, but not another.
The current method of controlling access to modules by overriding __import__ suffers from the problem that a given module can only have one __import__ hook at a time. There's no way for different users of the same module to have different importing abilities.