2 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/6a1755cd7fa0/ Changeset: 6a1755cd7fa0 User: jmchilton Date: 2014-06-11 22:16:05 Summary: Introduce unit(-ish) tests for routes. Allows testing both how URLs are going to map to controllers and actions as well as testing what paths will be produced by url_for. Requires some refactoring of Galaxy framework classes and buildapp to allow stubbing out actual instantiation of controllers, etc.... Affected #: 3 files diff -r f07db0284a42d88a1c88f280c9c22757a671deec -r 6a1755cd7fa0115142e1c277db4129e6e2add217 lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -454,7 +454,8 @@ for key in dir( module ): T = getattr( module, key ) if inspect.isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ): - self.add_ui_controller( name, T( app ) ) + controller = self._instantiate_controller( T, app ) + self.add_ui_controller( name, controller ) def add_api_controllers( self, package_name, app ): """ @@ -480,7 +481,14 @@ if inspect.isclass( T ) and not key.startswith("Base") and issubclass( T, BaseAPIController ): # By default use module_name, but allow controller to override name controller_name = getattr( T, "controller_name", name ) - self.add_api_controller( controller_name, T( app ) ) + controller = self._instantiate_controller( T, app ) + self.add_api_controller( controller_name, controller ) + + def _instantiate_controller( self, T, app ): + """ Extension point, allow apps to contstruct controllers differently, + really just used to stub out actual controllers for routes testing. + """ + return T( app ) class GalaxyWebTransaction( base.DefaultWebTransaction ): diff -r f07db0284a42d88a1c88f280c9c22757a671deec -r 6a1755cd7fa0115142e1c277db4129e6e2add217 lib/galaxy/webapps/galaxy/buildapp.py --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -70,10 +70,38 @@ webapp.add_route( '/u/:username/v/:slug', controller='visualization', action='display_by_username_and_slug' ) webapp.add_route( '/search', controller='search', action='index' ) - # ================ - # ===== API ===== - # ================ + # TODO: Refactor above routes into external method to allow testing in + # isolation as well. + populate_api_routes( webapp, app ) + # ==== Done + # Indicate that all configuration settings have been provided + webapp.finalize_config() + + # Wrap the webapp in some useful middleware + if kwargs.get( 'middleware', True ): + webapp = wrap_in_middleware( webapp, global_conf, **kwargs ) + if asbool( kwargs.get( 'static_enabled', True ) ): + webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=[ app.visualizations_registry ], **kwargs ) + #webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=None, **kwargs ) + if asbool(kwargs.get('pack_scripts', False)): + pack_scripts() + # Close any pooled database connections before forking + try: + galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose() + except: + pass + # Close any pooled database connections before forking + try: + galaxy.model.tool_shed_install.mapping.metadata.engine.connection_provider._pool.dispose() + except: + pass + + # Return + return webapp + + +def populate_api_routes( webapp, app ): webapp.add_api_controllers( 'galaxy.webapps.galaxy.api', app ) valid_history_contents_types = [ @@ -350,32 +378,6 @@ controller="metrics", action="create", conditions=dict( method=["POST"] ) ) - # ==== Done - # Indicate that all configuration settings have been provided - webapp.finalize_config() - - # Wrap the webapp in some useful middleware - if kwargs.get( 'middleware', True ): - webapp = wrap_in_middleware( webapp, global_conf, **kwargs ) - if asbool( kwargs.get( 'static_enabled', True ) ): - webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=[ app.visualizations_registry ], **kwargs ) - #webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=None, **kwargs ) - if asbool(kwargs.get('pack_scripts', False)): - pack_scripts() - # Close any pooled database connections before forking - try: - galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose() - except: - pass - # Close any pooled database connections before forking - try: - galaxy.model.tool_shed_install.mapping.metadata.engine.connection_provider._pool.dispose() - except: - pass - - # Return - return webapp - def pack_scripts(): from glob import glob from subprocess import call diff -r f07db0284a42d88a1c88f280c9c22757a671deec -r 6a1755cd7fa0115142e1c277db4129e6e2add217 test/unit/test_routes.py --- /dev/null +++ b/test/unit/test_routes.py @@ -0,0 +1,81 @@ +#import routes + +# Unused but adds some stuff to routes.Mapper. +from galaxy.web.framework import WebApplication +from galaxy.webapps.galaxy import buildapp as galaxy_buildapp + +from galaxy.web import url_for +from galaxy.util.bunch import Bunch + + +class TestWebapp( WebApplication ): + + def _instantiate_controller( self, type, app ): + # Stub out all actual controllers - just want to test routes. + return object() + + def assert_maps( self, url, method="GET", **parts ): + map_result = self.mapper.match( url, environ={"REQUEST_METHOD": method } ) + for key, expected_value in parts.iteritems(): + actual_value = map_result[ key ] + if actual_value != expected_value: + message = "Problem mapping route [%s], part %s expected value [%s] but obtained [%s]" + raise AssertionError(message % ( url, key, expected_value, actual_value ) ) + + +def test_galaxy_routes( ): + test_config = Bunch( template_path="/tmp", template_cache="/tmp" ) + app = Bunch( config=test_config, security=object(), trace_logger=None ) + test_webapp = TestWebapp( app ) + + galaxy_buildapp.populate_api_routes( test_webapp, app ) + + assert_url_is( url_for( "api_key_retrieval" ), "/api/authenticate/baseauth" ) + + # Test previously problematic tool ids with slashes. + test_webapp.assert_maps( + "/api/tools/testtoolshed.g2.bx.psu.edu/devteam/tool1", + controller="tools", + id="testtoolshed.g2.bx.psu.edu/devteam/tool1" + ) + + test_webapp.assert_maps( + "/api/datatypes/sniffers", + controller="datatypes", + action="sniffers" + ) + + test_webapp.assert_maps( + "/api/histories/123/contents/456", + controller="history_contents", + action="show" + ) + + test_webapp.assert_maps( + "/api/histories/123/contents/456", + method="PUT", + controller="history_contents", + action="update", + ) + + # Test differeniating datasets and datasets collections + # in history contents. + test_webapp.assert_maps( + "/api/histories/123/contents/datasets/456", + method="PUT", + controller="history_contents", + action="update", + type="dataset" + ) + + test_webapp.assert_maps( + "/api/histories/123/contents/dataset_collections/456", + method="PUT", + controller="history_contents", + action="update", + type="dataset_collection" + ) + + +def assert_url_is( actual, expected ): + assert actual == expected, "Expected URL [%s] but obtained [%s]" % ( expected, actual ) https://bitbucket.org/galaxy/galaxy-central/commits/651c1ed8e4d3/ Changeset: 651c1ed8e4d3 User: jmchilton Date: 2014-06-11 22:16:05 Summary: Rework type-differentiated history contents routes. url_for now can produce the routes I build by hand in say bioblend and the GUI. Affected #: 4 files diff -r 6a1755cd7fa0115142e1c277db4129e6e2add217 -r 651c1ed8e4d35cc140d20038c17e33eeb4381804 lib/galaxy/dataset_collections/util.py --- a/lib/galaxy/dataset_collections/util.py +++ b/lib/galaxy/dataset_collections/util.py @@ -70,7 +70,7 @@ encoded_id = security.encode_id( dataset_colleciton_instance.id ) if isinstance( parent, model.History ): encoded_history_id = security.encode_id( parent.id ) - dict_value[ 'url' ] = web.url_for( 'history_content', history_id=encoded_history_id, id=encoded_id, type="dataset_collection" ) + dict_value[ 'url' ] = web.url_for( 'history_content_typed', history_id=encoded_history_id, id=encoded_id, type="dataset_collection" ) elif isinstance( parent, model.LibraryFolder ): encoded_library_id = security.encode_id( parent.library.id ) encoded_folder_id = security.encode_id( parent.id ) diff -r 6a1755cd7fa0115142e1c277db4129e6e2add217 -r 651c1ed8e4d35cc140d20038c17e33eeb4381804 lib/galaxy/webapps/galaxy/api/history_contents.py --- a/lib/galaxy/webapps/galaxy/api/history_contents.py +++ b/lib/galaxy/webapps/galaxy/api/history_contents.py @@ -143,7 +143,7 @@ 'purged': hda.purged, 'hid' : hda.hid, 'history_content_type' : hda.history_content_type, - 'url' : url_for( 'history_content', history_id=encoded_history_id, id=encoded_id ), + 'url' : url_for( 'history_content_typed', history_id=encoded_history_id, id=encoded_id, type="dataset" ), } def __collection_dict( self, trans, dataset_collection_instance, view="collection" ): diff -r 6a1755cd7fa0115142e1c277db4129e6e2add217 -r 651c1ed8e4d35cc140d20038c17e33eeb4381804 lib/galaxy/webapps/galaxy/buildapp.py --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -108,15 +108,16 @@ 'dataset', 'dataset_collection', ] - # This must come before history contents below. + # Accesss HDA details via histories/:history_id/contents/datasets/:hda_id - webapp.mapper.resource( "typed_content", + webapp.mapper.resource( "content_typed", "{type:%s}s" % "|".join( valid_history_contents_types ), - name_prefix="history_content_", + name_prefix="history_", controller='history_contents', path_prefix='/api/histories/:history_id/contents', parent_resources=dict( member_name='history', collection_name='histories' ), ) + # Legacy access to HDA details via histories/:history_id/contents/:hda_id webapp.mapper.resource( 'content', 'contents', diff -r 6a1755cd7fa0115142e1c277db4129e6e2add217 -r 651c1ed8e4d35cc140d20038c17e33eeb4381804 test/unit/test_routes.py --- a/test/unit/test_routes.py +++ b/test/unit/test_routes.py @@ -76,6 +76,16 @@ type="dataset_collection" ) + assert_url_is( + url_for( "history_content", history_id="123", id="456" ), + "/api/histories/123/contents/456" + ) + + assert_url_is( + url_for( "history_content_typed", history_id="123", id="456", type="dataset" ), + "/api/histories/123/contents/datasets/456" + ) + def assert_url_is( actual, expected ): assert actual == expected, "Expected URL [%s] but obtained [%s]" % ( expected, actual ) Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.