def test_setattr_replaces(self):
        """ScopeReplacer can create an instance in local scope.

        An object should appear in globals() by constructing a ScopeReplacer,
        and it will be replaced with the real object upon the first request.
        """
        actions = []
        TestClass.use_actions(actions)

        def factory(replacer, scope, name):
            return TestClass()

        try:
            test_obj6
        except NameError:
            # test_obj6 shouldn't exist yet
            pass
        else:
            self.fail('test_obj6 was not supposed to exist yet')

        lazy_import.ScopeReplacer(scope=globals(),
                                  name='test_obj6',
                                  factory=factory)

        # We can't use isinstance() because that uses test_obj6.__class__
        # and that goes through __getattribute__ which would activate
        # the replacement
        self.assertEqual(lazy_import.ScopeReplacer,
                         object.__getattribute__(test_obj6, '__class__'))
        test_obj6.bar = 'test'
        self.assertNotEqual(lazy_import.ScopeReplacer,
                            object.__getattribute__(test_obj6, '__class__'))
        self.assertEqual('test', test_obj6.bar)
    def test_setattr(self):
        class Replaced:
            pass

        def factory(*args):
            return Replaced()

        replacer = lazy_import.ScopeReplacer({}, factory, 'name')

        def racer():
            replacer.foo = 42

        self.run_race(racer)
    def test_getattribute(self):
        class Replaced:
            foo = 'bar'

        def factory(*args):
            return Replaced()

        replacer = lazy_import.ScopeReplacer({}, factory, 'name')

        def racer():
            replacer.foo

        self.run_race(racer)
    def test_replace_side_effects(self):
        """Creating a new object should only create one entry in globals.

        And only that entry even after replacement.
        """
        try:
            test_scope1
        except NameError:
            # test_scope1 shouldn't exist yet
            pass
        else:
            self.fail('test_scope1 was not supposed to exist yet')

        # ignore the logged actions
        TestClass.use_actions([])

        def factory(replacer, scope, name):
            return TestClass()

        orig_globals = set(globals().keys())

        lazy_import.ScopeReplacer(scope=globals(),
                                  name='test_scope1',
                                  factory=factory)

        new_globals = set(globals().keys())

        self.assertEqual(lazy_import.ScopeReplacer,
                         object.__getattribute__(test_scope1, '__class__'))
        self.assertEqual('foo', test_scope1.foo(1))
        self.assertIsInstance(test_scope1, TestClass)

        final_globals = set(globals().keys())

        self.assertEqual(set(['test_scope1']), new_globals - orig_globals)
        self.assertEqual(set(), orig_globals - new_globals)
        self.assertEqual(set(), final_globals - new_globals)
        self.assertEqual(set(), new_globals - final_globals)
    def test_call(self):
        def factory(*args):
            return factory

        replacer = lazy_import.ScopeReplacer({}, factory, 'name')
        self.run_race(replacer)