Example #1
0
    def inserted_as_shim(self):
        executable = self
        saved_which = Executable.which

        def stub_which(self, program):
            full_path_to_executable = saved_which(self, program)
            if program in [full_path_to_executable, executable.name]:
                return program
            else:
                return full_path_to_executable

        saved_execute = Executable.execute

        def stub_execute(self, method, commandline_arguments, *args, **kwargs):
            if executable.name == self.name:
                return executable.execute(method, commandline_arguments, *args,
                                          **kwargs)
            else:
                return saved_execute(self, method, commandline_arguments,
                                     *args, **kwargs)

        stub_which.__name__ = 'which'
        stub_execute.__name__ = 'execute'
        with replaced(Executable.which, stub_which,
                      Executable), replaced(Executable.execute, stub_execute,
                                            Executable):
            yield executable
Example #2
0
def test_replace():
    """Replaced methods replace the original one, but are restored after the with."""
    class SomethingElse(object):
        def foo(self, n, y=None):
            assert None, 'This should never be reached in this test'

    # Case: bound method
    s = SomethingElse()

    def replacement(n, y=None):
        return y

    original_method = six.get_method_function(s.foo)

    with replaced(s.foo, replacement):
        assert s.foo(1, y='a') == 'a'
        assert s.foo(2) == None

    assert six.get_method_function(s.foo) is original_method

    # Case: unbound method
    """Python 3 does not support the concept of unbound methods, they are
    just plain functions without an im_class pointing back to their class.
    See https://docs.python.org/3/whatsnew/3.0.html#operators-and-special-methods,
    and https://mail.python.org/pipermail/python-dev/2005-January/050625.html
    for the rationale.

    To be able to support them under Python3, on= is mandatory.
    """

    s = SomethingElse()

    def replacement(self, n, y=None):
        return y

    original_method = six.get_unbound_function(SomethingElse.foo)

    with replaced(SomethingElse.foo, replacement, on=SomethingElse):
        assert s.foo(1, y='a') == 'a'
        assert s.foo(2) == None

    restored_method = six.get_unbound_function(SomethingElse.foo)
    assert restored_method is original_method

    # Case: unbound method (no on= given)
    s = SomethingElse()

    def replacement(self, n, y=None):
        return y

    with pytest.raises(
            ValueError,
            match='You have to supply a on= when stubbing an unbound method'):
        with replaced(SomethingElse.foo, replacement):
            pass
Example #3
0
def test_i18n_dhtml(web_fixture, dhtml_fixture):
    """Dhtml files can have i18nsed versions, which would be served up if applicable."""
    class MainUI(UserInterface):
        def assemble(self):
            self.define_page(HTML5Page).use_layout(BasicPageLayout())
            self.define_user_interface('/dhtml_ui',
                                       DhtmlUI, {'main_slot': 'main'},
                                       name='test_ui',
                                       static_div_name='astatic')

    fixture = dhtml_fixture

    # Dhtml files should be located in the web.static_root
    web_fixture.config.web.static_root = fixture.static_dir.name

    wsgi_app = web_fixture.new_wsgi_app(site_root=MainUI)

    browser = Browser(wsgi_app)

    # request the file, but get the translated alternative for the locale
    def stubbed_create_context_for_request():
        return LocaleContextStub(locale='af')

    with replaced(wsgi_app.create_context_for_request,
                  stubbed_create_context_for_request):
        browser.open('/dhtml_ui/correctfile.d.html')

    assert browser.title == 'Afrikaans bo!'
Example #4
0
    def i18n_dhtml(self, fixture):
        """Djhtml files can have i18nsed versions, which would be served up if applicable."""
        @stubclass(WebExecutionContext)
        class AfrikaansContext(WebExecutionContext):
            @property
            def interface_locale(self):
                return 'af'

        class MainUI(UserInterface):
            def assemble(self):
                self.define_page(HTML5Page).use_layout(
                    PageLayout(
                        contents_layout=ColumnLayout('main').with_slots()))
                self.define_user_interface('/dhtml_ui',
                                           DhtmlUI, {'main_slot': 'main'},
                                           name='test_ui',
                                           static_div_name='astatic')

        # Djhtml files should be located in the web.static_root
        fixture.config.web.static_root = fixture.static_dir.name

        wsgi_app = fixture.new_wsgi_app(site_root=MainUI)

        browser = Browser(wsgi_app)

        # request the file, but get the transalated alternative for the locale
        def stubbed_create_context_for_request():
            return AfrikaansContext()

        with replaced(wsgi_app.create_context_for_request,
                      stubbed_create_context_for_request):
            browser.open('/dhtml_ui/correctfile.d.html')

        vassert(browser.title == 'Afrikaans bo!')
Example #5
0
    def test_replacing_functions_is_disallowed(self):
        """Functions can not be replaced, only methods can."""
        def function1():
            pass

        def function2():
            pass

        with assert_raises(ValueError):
            with replaced(function1, function2):
                pass
Example #6
0
    def test_replaced_signature_should_match(self):
        """Replacing methods should have the same signature as the ones they replace."""
        class SomethingElse(object):
            def foo(self, n, y=None):
                assert None, 'This should never be reached in this test'

        s = SomethingElse()

        def replacement():
            pass

        with assert_raises(AssertionError):
            with replaced(s.foo, replacement):
                pass
Example #7
0
def test_regenerating_method_results(reahl_system_fixture, web_fixture,
                                     remote_method_fixture,
                                     regenerate_method_result_scenarios):
    """If a MethodResult is set up to replay_request=True, the view it is part of (and thus itself) is recreated
       before the (new incarnation of the) MethodResult generates its actual response. Replaying the request means recreating
       all Widgets on the current View as well as the MethodResult itself. The construction of any of these
       objects may happen differently because of the changes made during the RemoteMethod's execution. Replaying
       the request ensures that the MethodResult reflects such changes, yet ensures that the RemoteMethod
       is not executed twice.
    """

    wsgi_app = remote_method_fixture.new_wsgi_app(
        remote_method=regenerate_method_result_scenarios.remote_method)
    browser = Browser(wsgi_app)

    import sqlalchemy.orm

    @stubclass(sqlalchemy.orm.Session)
    class TransactionStub:
        is_active = True

        def commit(self):
            pass

        def rollback(self):
            pass

    def wrapped_nested_transaction():
        return web_fixture.nested_transaction

    web_fixture.nested_transaction = TransactionStub()
    with replaced(Session().begin_nested, wrapped_nested_transaction):
        with CallMonitor(web_fixture.nested_transaction.commit) as monitor:
            browser.post('/_amethod_method', {})
        assert browser.raw_html == regenerate_method_result_scenarios.expected_response
        assert monitor.times_called == 2
Example #8
0
    def test_replace(self):
        """Replaced methods replace the original one, but are restored after the with."""
        class SomethingElse(object):
            def foo(self, n, y=None):
                assert None, 'This should never be reached in this test'

        # Case: bound method
        s = SomethingElse()

        def replacement(n, y=None):
            return y

        original_method = six.get_method_function(s.foo)

        with replaced(s.foo, replacement):
            assert s.foo(1, y='a') == 'a'
            assert s.foo(2) == None

        assert six.get_method_function(s.foo) is original_method

        # Case: unbound method
        """Python 3 does not support the concept of unbound methods, they are
        just plain functions without an im_class pointing back to their class.
        See https://docs.python.org/3/whatsnew/3.0.html#operators-and-special-methods,
        and https://mail.python.org/pipermail/python-dev/2005-January/050625.html
        for the rationale.

        If stubble wishes to support them under Python 3, the signature of
        stubble.replaced will need to change to take the class as a parameter.
        But since reahl itself does not use this feature, we just deprecate
        it under Python 2 and make it illegal under Python 3.

        Note that we are only talking about instance methods here, not class
        methods. Instance methods always require an instance to be called on, so
        there should always be an instance they can be stubbed on, i.e. by using
        replaced(instance.method, ...) instead of replaced(someclass.method, ...).
        """

        s = SomethingElse()

        def replacement(self, n, y=None):
            return y

        if six.PY2:
            original_method = six.get_method_function(SomethingElse.foo)

            with warnings.catch_warnings(record=True) as raised_warnings:
                warnings.simplefilter("always")
                with replaced(SomethingElse.foo, replacement):
                    assert s.foo(1, y='a') == 'a'
                    assert s.foo(2) == None
                    assert six.get_method_function(
                        SomethingElse.foo) is not original_method
            assert six.get_method_function(
                SomethingElse.foo) is original_method

            [deprecation] = raised_warnings
            assert issubclass(deprecation.category, DeprecationWarning)
        else:
            with assert_raises(ValueError):
                with replaced(SomethingElse.foo, replacement):
                    pass
Example #9
0
def test_web_session_handling(reahl_system_fixture, web_fixture):
    """The core web framework (this egg) does not implement a notion of session directly.
       It relies on such a notion, but expects an implementation for this to be supplied.

       An implementation should implement the UserSessionProtocol. The implementation
       is thus responsible for associating an instance of itself with the current request.

       The implementation to be used is set in the web.session_class configuration setting.

       The framework ensures that an instance of web.session_class is available during any
       Request. The database is committed before any user code executes, so that any database activity
       done by web.session_class would be committed even if an exception in the user code occurs.
       After user code is executed, methods are called on the web.session_class so that it can set
       its key on the response and save the last_activity_time.
       Finally, another commit is issued to the database so that any database activity during these last
       actions would also be saved.
    """
    stubclass(UserSessionProtocol)

    class UserSessionStub(UserSessionProtocol):
        session = None
        last_activity_time_set = False
        key_is_set = False

        @classmethod
        def for_current_session(cls):
            assert None, 'Not implemented'

        @classmethod
        def get_or_create_session(cls):
            cls.session = cls()
            return cls.session

        @classmethod
        def initialise_web_session_on(cls, context):
            context.session = cls.get_or_create_session()

        def set_session_key(self, response):
            self.key_is_set = True
            self.saved_response = response

        def is_active(self):
            pass

        def is_secured(self):
            pass

        def set_as_logged_in(self, party, stay_logged_in):
            pass

        def log_out(self):
            pass

        def set_last_activity_time(self):
            self.last_activity_time_set = True

        def get_interface_locale(self):
            return 'en_gb'

    import sqlalchemy.orm

    @stubclass(sqlalchemy.orm.Session)
    class TransactionStub:
        is_active = True

        def commit(self):
            pass

        def rollback(self):
            pass

    web_fixture.nested_transaction = TransactionStub()

    def wrapped_nested_transaction():
        return web_fixture.nested_transaction

    with replaced(Session().begin_nested, wrapped_nested_transaction):
        # Setting the implementation in config
        web_fixture.config.web.session_class = UserSessionStub
        with CallMonitor(web_fixture.nested_transaction.commit) as monitor:

            @stubclass(Resource)
            class ResourceStub:
                should_commit = True

                def cleanup_after_transaction(self):
                    assert monitor.times_called == 2  # The database has been committed after user code started executed, before cleanup

                def handle_request(self, request):
                    context = ExecutionContext.get_context()
                    assert context.session is UserSessionStub.session  # By the time user code executes, the session is set
                    assert monitor.times_called == 1  # The database has been committed before user code started executing
                    assert context.session.last_activity_time_set
                    assert not UserSessionStub.session.key_is_set
                    return Response()

            @stubclass(ReahlWSGIApplication)
            class ReahlWSGIApplicationStub2(ReahlWSGIApplicationStub):
                def resource_for(self, request):
                    return ResourceStub()

            browser = Browser(ReahlWSGIApplicationStub2(web_fixture.config))

            # A session is obtained, and the correct params passed to the hook methods
            assert not UserSessionStub.session  # Before the request, the session is not yet set
            assert monitor.times_called == 0  # ... and the database is not yet committed
            browser.open('/')

            assert monitor.times_called == 2  # The database is committed to save session changes before user code and again after user code executed
            assert UserSessionStub.session  # The session was set
            assert UserSessionStub.session.key_is_set  # The set_session_key was called
            assert UserSessionStub.session.saved_response.status_int is 200  # The correct response was passed to set_session_key

            assert UserSessionStub.session.last_activity_time_set  # set_last_activity_time was called