def facet(target, allowed_attrs):
    class Facet:
        def __repr__(self):
            return '<Facet %r on %r>' % (allowed_attrs, target)
        def __getattr__(self, name):
            if name in allowed_attrs:
                return getattr(target, name)
            raise AttributeError('attribute %r is not defined' % name)
    return Facet()

def restrict(namespace, allowed_builtins, allowed_modules):
    original_import = __import__
    def restricted_import(name, globals, locals, fromlist):
        if name in allowed_modules:
            return original_import(name, globals, locals, fromlist)
        raise ImportError('No module named %s' % name)
    builtins = {'__import__': restricted_import}
    for name in allowed_builtins:
        builtins[name] = getattr(__builtins__, name)
    namespace.__builtins__ = builtins

# Here are some examples.

list = [1, 2, 3]
immutable_facet = facet(list, ['__getitem__', '__len__', '__iter__'])

class Counter:
    def __init__(self): self.n = 0
    def increment(self): self.n += 1
    def value(self): return self.n
counter = Counter()
readonly_facet = facet(counter, ['value'])

# The challenge: write untrusted_module.py to modify 'list' or 'counter'.

allowed_builtins = '''ArithmeticError AssertionError AttributeError
    DeprecationWarning EOFError Ellipsis EnvironmentError Exception False
    FloatingPointError FutureWarning IOError ImportError IndentationError
    IndexError KeyError KeyboardInterrupt LookupError MemoryError NameError
    None NotImplemented NotImplementedError OSError OverflowError
    OverflowWarning PendingDeprecationWarning ReferenceError RuntimeError
    RuntimeWarning StandardError StopIteration SyntaxError SyntaxWarning
    SystemError TabError True TypeError UnboundLocalError UnicodeDecodeError
    UnicodeEncodeError UnicodeError UnicodeTranslateError UserWarning
    ValueError Warning ZeroDivisionError abs apply basestring bool buffer
    callable chr classmethod cmp coerce compile complex copyright credits
    delattr dict dir divmod enumerate eval filter float getattr globals
    hasattr hash hex id int intern isinstance issubclass iter len license
    list locals long map max min object oct ord pow property range reduce
    repr round setattr slice staticmethod str sum tuple type unichr unicode
    vars xrange zip'''.split()
allowed_modules = ['exceptions']

import untrusted_module
restrict(untrusted_module, allowed_builtins, allowed_modules)
untrusted_module.have_at_it(immutable_facet, readonly_facet)
