From 984ceb104d91cdd23daf8a1b6c2382d1eacd1e90 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Wed, 16 Dec 2015 18:45:21 +0000 Subject: [PATCH] Move Dictifiable out of model package into util. Many objects that aren't model objects are Dictifiable at this point so there is no reason to have this in model. This changes eliminates Dictifiable's dependency on sqlalchemy (by using a more pythonic type check). Now that Dictifiable has no external dependencies, it is much easier to reuse it (and more important objects that extend it) in other projects such as planemo. --- lib/galaxy/model/__init__.py | 3 +- lib/galaxy/model/item_attrs.py | 66 ++----------------- .../model/tool_shed_install/__init__.py | 2 +- lib/galaxy/tools/__init__.py | 2 +- lib/galaxy/tools/data/__init__.py | 2 +- lib/galaxy/tools/parameters/basic.py | 2 +- lib/galaxy/tools/parameters/grouping.py | 2 +- lib/galaxy/tools/toolbox/base.py | 2 +- lib/galaxy/tools/toolbox/panel.py | 2 +- lib/galaxy/util/dictifiable.py | 62 +++++++++++++++++ lib/galaxy/web/base/controller.py | 3 +- .../webapps/tool_shed/model/__init__.py | 2 +- 12 files changed, 79 insertions(+), 71 deletions(-) create mode 100644 lib/galaxy/util/dictifiable.py diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 98b6fddbe56..400a2d9f50a 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -33,7 +33,8 @@ import galaxy.model.orm.now import galaxy.security.passwords import galaxy.util from galaxy.datatypes.metadata import MetadataCollection -from galaxy.model.item_attrs import Dictifiable, UsesAnnotations +from galaxy.model.item_attrs import UsesAnnotations +from galaxy.util.dictifiable import Dictifiable from galaxy.security import get_permitted_actions from galaxy.util import is_multi_byte, Params, restore_text, send_mail from galaxy.util import ready_name_for_url, unique_id diff --git a/lib/galaxy/model/item_attrs.py b/lib/galaxy/model/item_attrs.py index 89320edfd99..dc9666a13af 100644 --- a/lib/galaxy/model/item_attrs.py +++ b/lib/galaxy/model/item_attrs.py @@ -1,10 +1,7 @@ from sqlalchemy.sql.expression import func -from sqlalchemy.orm.collections import InstrumentedList # Cannot import galaxy.model b/c it creates a circular import graph. import galaxy import logging -import datetime -import uuid log = logging.getLogger( __name__ ) @@ -165,61 +162,8 @@ class UsesAnnotations: return getattr( galaxy.model, class_name, None ) -class Dictifiable: - """ Mixin that enables objects to be converted to dictionaries. This is useful - when for sharing objects across boundaries, such as the API, tool scripts, - and JavaScript code. """ - - def to_dict( self, view='collection', value_mapper=None ): - """ - Return item dictionary. - """ - - if not value_mapper: - value_mapper = {} - - def get_value( key, item ): - """ - Recursive helper function to get item values. - """ - # FIXME: why use exception here? Why not look for key in value_mapper - # first and then default to to_dict? - try: - return item.to_dict( view=view, value_mapper=value_mapper ) - except: - if key in value_mapper: - return value_mapper.get( key )( item ) - if type(item) == datetime.datetime: - return item.isoformat() - elif type(item) == uuid.UUID: - return str(item) - # Leaving this for future reference, though we may want a more - # generic way to handle special type mappings going forward. - # If the item is of a class that needs to be 'stringified' before being put into a JSON data structure - # elif type(item) in []: - # return str(item) - return item - - # Create dict to represent item. - rval = dict( - model_class=self.__class__.__name__ - ) - - # Fill item dict with visible keys. - try: - visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' ) - except AttributeError: - raise Exception( 'Unknown Dictifiable view: %s' % view ) - for key in visible_keys: - try: - item = self.__getattribute__( key ) - if type( item ) == InstrumentedList: - rval[ key ] = [] - for i in item: - rval[ key ].append( get_value( key, i ) ) - else: - rval[ key ] = get_value( key, item ) - except AttributeError: - rval[ key ] = None - - return rval +__all__ = [ + 'UsesAnnotations', + 'UsesItemRatings', + 'RuntimeException', +] diff --git a/lib/galaxy/model/tool_shed_install/__init__.py b/lib/galaxy/model/tool_shed_install/__init__.py index af476cf36ac..4219afc944f 100644 --- a/lib/galaxy/model/tool_shed_install/__init__.py +++ b/lib/galaxy/model/tool_shed_install/__init__.py @@ -1,6 +1,6 @@ import logging import os -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable from galaxy.util.bunch import Bunch from galaxy.util import asbool from tool_shed.util import common_util diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index f1fa2ae7be3..462faf7337d 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -47,7 +47,7 @@ from galaxy.util.hash_util import hmac_new from galaxy.util.odict import odict from galaxy.util.template import fill_template from galaxy.web import url_for -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable from tool_shed.util import common_util from tool_shed.util import shed_util_common as suc diff --git a/lib/galaxy/tools/data/__init__.py b/lib/galaxy/tools/data/__init__.py index aecb22488a0..379fd6b113f 100644 --- a/lib/galaxy/tools/data/__init__.py +++ b/lib/galaxy/tools/data/__init__.py @@ -20,7 +20,7 @@ from urllib2 import urlopen from galaxy import util from galaxy.util.odict import odict -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable log = logging.getLogger( __name__ ) diff --git a/lib/galaxy/tools/parameters/basic.py b/lib/galaxy/tools/parameters/basic.py index 43d86627d25..b7e24bf0017 100644 --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -23,7 +23,7 @@ from .dataset_matcher import DatasetMatcher from .dataset_matcher import DatasetCollectionMatcher # For BaseURLToolParameter from galaxy.web import url_for -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable import galaxy.model log = logging.getLogger(__name__) diff --git a/lib/galaxy/tools/parameters/grouping.py b/lib/galaxy/tools/parameters/grouping.py index f99c48ae023..ecd006b934a 100644 --- a/lib/galaxy/tools/parameters/grouping.py +++ b/lib/galaxy/tools/parameters/grouping.py @@ -15,7 +15,7 @@ from galaxy.util import relpath from galaxy.util import sanitize_for_filename from galaxy.util.bunch import Bunch from galaxy.util.expressions import ExpressionContext -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable class Group( object, Dictifiable ): diff --git a/lib/galaxy/tools/toolbox/base.py b/lib/galaxy/tools/toolbox/base.py index ee8f51fbd8e..c2c68a2d56e 100644 --- a/lib/galaxy/tools/toolbox/base.py +++ b/lib/galaxy/tools/toolbox/base.py @@ -9,7 +9,7 @@ from sqlalchemy import and_ from markupsafe import escape from urlparse import urlparse -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable from galaxy.util.odict import odict from galaxy.util import listify diff --git a/lib/galaxy/tools/toolbox/panel.py b/lib/galaxy/tools/toolbox/panel.py index 2e122016b6c..7d0e85f7c4f 100644 --- a/lib/galaxy/tools/toolbox/panel.py +++ b/lib/galaxy/tools/toolbox/panel.py @@ -2,7 +2,7 @@ from abc import abstractmethod from galaxy.util.odict import odict from galaxy.util import bunch -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable panel_item_types = bunch.Bunch( diff --git a/lib/galaxy/util/dictifiable.py b/lib/galaxy/util/dictifiable.py new file mode 100644 index 00000000000..29051e887f0 --- /dev/null +++ b/lib/galaxy/util/dictifiable.py @@ -0,0 +1,62 @@ +import datetime +import uuid + + +class Dictifiable: + """ Mixin that enables objects to be converted to dictionaries. This is useful + when for sharing objects across boundaries, such as the API, tool scripts, + and JavaScript code. """ + + def to_dict( self, view='collection', value_mapper=None ): + """ + Return item dictionary. + """ + + if not value_mapper: + value_mapper = {} + + def get_value( key, item ): + """ + Recursive helper function to get item values. + """ + # FIXME: why use exception here? Why not look for key in value_mapper + # first and then default to to_dict? + try: + return item.to_dict( view=view, value_mapper=value_mapper ) + except: + if key in value_mapper: + return value_mapper.get( key )( item ) + if type(item) == datetime.datetime: + return item.isoformat() + elif type(item) == uuid.UUID: + return str(item) + # Leaving this for future reference, though we may want a more + # generic way to handle special type mappings going forward. + # If the item is of a class that needs to be 'stringified' before being put into a JSON data structure + # elif type(item) in []: + # return str(item) + return item + + # Create dict to represent item. + rval = dict( + model_class=self.__class__.__name__ + ) + + # Fill item dict with visible keys. + try: + visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' ) + except AttributeError: + raise Exception( 'Unknown Dictifiable view: %s' % view ) + for key in visible_keys: + try: + item = self.__getattribute__( key ) + if isinstance( item, list ): + rval[ key ] = [] + for i in item: + rval[ key ].append( get_value( key, i ) ) + else: + rval[ key ] = get_value( key, item ) + except AttributeError: + rval[ key ] = None + + return rval diff --git a/lib/galaxy/web/base/controller.py b/lib/galaxy/web/base/controller.py index 3c46652783c..2aef1d28a6f 100644 --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -23,7 +23,8 @@ from galaxy.web.form_builder import build_select_field, HistoryField, PasswordFi from galaxy.workflow.modules import WorkflowModuleInjector, MissingToolException from galaxy.security.validate_user_input import validate_publicname from galaxy.util.sanitize_html import sanitize_html -from galaxy.model.item_attrs import Dictifiable, UsesAnnotations +from galaxy.model.item_attrs import UsesAnnotations +from galaxy.util.dictifiable import Dictifiable from galaxy.datatypes.interval import ChromatinInteractions diff --git a/lib/galaxy/webapps/tool_shed/model/__init__.py b/lib/galaxy/webapps/tool_shed/model/__init__.py index 23a3f98e83f..3bd9afdf22f 100644 --- a/lib/galaxy/webapps/tool_shed/model/__init__.py +++ b/lib/galaxy/webapps/tool_shed/model/__init__.py @@ -6,7 +6,7 @@ from galaxy import util from galaxy.util import unique_id from galaxy.util.bunch import Bunch from galaxy.util.hash_util import new_secure_hash -from galaxy.model.item_attrs import Dictifiable +from galaxy.util.dictifiable import Dictifiable import tool_shed.repository_types.util as rt_util from mercurial import hg