Changeset 1557:a5831435c654
- Timestamp:
- 10/16/08 14:12:37 (3 months ago)
- Files:
-
- lib/galaxy/datatypes/data.py (modified) (2 diffs)
- lib/galaxy/datatypes/metadata.py (modified) (6 diffs)
- lib/galaxy/datatypes/sequence.py (modified) (1 diff)
- lib/galaxy/datatypes/tabular.py (modified) (1 diff)
- lib/galaxy/model/__init__.py (modified) (2 diffs)
- lib/galaxy/tools/__init__.py (modified) (1 diff)
- lib/galaxy/tools/parameters/basic.py (modified) (1 diff)
- lib/galaxy/tools/parameters/validation.py (modified) (1 diff)
- lib/galaxy/web/controllers/root.py (modified) (4 diffs)
- templates/dataset/edit_attributes.mako (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
lib/galaxy/datatypes/data.py
r1533 r1557 2 2 from galaxy import util 3 3 from cgi import escape 4 from galaxy.datatypes.metadata import * 5 from galaxy.datatypes.metadata import MetadataElement 6 from galaxy.datatypes import metadata 4 import metadata 5 from metadata import MetadataElement #import directly to maintain ease of use in Datatype class definitions 7 6 8 7 log = logging.getLogger(__name__) … … 18 17 """ 19 18 def __init__( cls, name, bases, dict_ ): 20 cls.metadata_spec = MetadataSpecCollection()21 for base in bases: 22 if hasattr( base, "metadata_spec"):23 cls.metadata_spec.update( base.metadata_spec)24 Statement.process( cls )19 cls.metadata_spec = metadata.MetadataSpecCollection() 20 for base in bases: #loop through bases (class/types) of cls 21 if hasattr( base, "metadata_spec" ): #base of class Data (object) has no metadata 22 cls.metadata_spec.update( base.metadata_spec ) #add contents of metadata spec of base class to cls 23 metadata.Statement.process( cls ) 25 24 26 25 class Data( object ): lib/galaxy/datatypes/metadata.py
r1531 r1557 1 1 import sys, logging 2 2 3 from galaxy.util .bunch import Bunch3 from galaxy.util import string_as_bool 4 4 from galaxy.util.odict import odict 5 5 from galaxy.web import form_builder 6 from types import *7 6 8 7 log = logging.getLogger( __name__ ) 9 8 10 # Taken in part from Elixir and how they do it: http://elixir.ematia.de 11 12 STATEMENTS = "__galaxy_statements__" 9 STATEMENTS = "__galaxy_statements__" #this is the name of the property in a Datatype class where new metadata spec element Statements are stored 13 10 14 11 class Statement( object ): 15 '''12 """ 16 13 This class inserts its target into a list in the surrounding 17 14 class. the data.Data class has a metaclass which executes these 18 15 statements. This is how we shove the metadata element spec into 19 16 the class. 20 '''17 """ 21 18 def __init__( self, target ): 22 19 self.target = target 23 20 def __call__( self, *args, **kwargs ): 24 class_locals = sys._getframe( 1).f_locals25 statements = class_locals.setdefault( STATEMENTS, [])26 statements.append( (self, args, kwargs))21 class_locals = sys._getframe( 1 ).f_locals #get the locals dictionary of the frame object one down in the call stack (i.e. the Datatype class calling MetadataElement) 22 statements = class_locals.setdefault( STATEMENTS, [] ) #get and set '__galaxy_statments__' to an empty list if not in locals dict 23 statements.append( ( self, args, kwargs ) ) #add Statement containing info to populate a MetadataElementSpec 27 24 @classmethod 28 25 def process( cls, element ): 29 26 for statement, args, kwargs in getattr( element, STATEMENTS, [] ): 30 statement.target( element, *args, **kwargs ) 27 statement.target( element, *args, **kwargs ) #statement.target is MetadataElementSpec, element is a Datatype class 28 29 30 class MetadataCollection: 31 """ 32 MetadataCollection is not a collection at all, but rather a proxy 33 to the real metadata which is stored as a Dictionary. This class 34 handles processing the metadata elements when they are set and 35 retrieved, returning default values in cases when metadata is not set. 36 """ 37 def __init__(self, parent ): 38 self.parent = parent 39 #initialize dict if needed 40 if self.parent._metadata is None: 41 self.parent._metadata = {} 42 @property 43 def spec( self ): 44 return self.parent.datatype.metadata_spec 45 def __iter__( self ): 46 return self.parent._metadata.__iter__() 47 def get( self, key, default=None ): 48 try: 49 return self.__getattr__( key ) or default 50 except: 51 return default 52 def items(self): 53 return iter( [ ( k, self.get( k ) ) for k in self.spec.iterkeys() ] ) 54 def __str__(self): 55 return dict( self.items() ).__str__() 56 def __nonzero__( self ): 57 return bool( self.parent._metadata ) 58 def __getattr__( self, name ): 59 if name in self.spec: 60 if name in self.parent._metadata: 61 return self.spec[name].wrap( self.parent._metadata[name] ) 62 return self.spec[name].wrap( self.spec[name].default ) 63 if name in self.parent._metadata: 64 return self.parent._metadata[name] 65 def __setattr__( self, name, value ): 66 if name == "parent": 67 self.__dict__[name] = value 68 else: 69 if name in self.spec: 70 self.parent._metadata[name] = self.spec[name].unwrap( value ) 71 else: 72 self.parent._metadata[name] = value 73 def element_is_set( self, name ): 74 return bool( self.parent._metadata.get( name, False ) ) 75 def get_html_by_name( self, name, **kwd ): 76 if name in self.spec: 77 return self.spec[name].param.get_html( value=getattr( self, name ), context=self, **kwd ) 78 31 79 32 80 class MetadataSpecCollection( odict ): 33 '''81 """ 34 82 A simple extension of dict which allows cleaner access to items 35 83 and allows the values to be iterated over directly as if it were a 36 84 list. append() is also implemented for simplicity and does not 37 85 "append". 38 '''39 def __init__( self, dict = None):40 odict.__init__( self, dict = None)86 """ 87 def __init__( self, dict = None ): 88 odict.__init__( self, dict = None ) 41 89 def append( self, item ): 42 90 self[item.name] = item … … 44 92 return self.itervalues() 45 93 def __getattr__( self, name ): 46 return self.get( name)94 return self.get( name ) 47 95 48 96 class MetadataParameter( object ): 49 def __init__( self, spec, value, context ): 50 ''' 97 def __init__( self, spec ): 98 self.spec = spec 99 100 def get_html_field( self, value=None, context={}, other_values={}, **kwd ): 101 return form_builder.TextField( self.spec.name, value=value ) 102 103 def get_html( self, value, context={}, other_values={}, **kwd ): 104 """ 51 105 The "context" is simply the metadata collection/bunch holding 52 106 this piece of metadata. This is passed in to allow for … … 55 109 example, a column assignment should validate against the 56 110 number of columns in the dataset. 57 ''' 58 self.spec = spec 59 """Since strings are stored as unicode, we need to decode them for display""" 60 if isinstance( value, ListType ): 61 for i, elem in enumerate( value ): 62 if type ( elem ) == unicode: 63 value[i] = elem.decode( 'ascii' ) 64 elif isinstance ( value, basestring ): 65 if type( value ) == unicode: 66 value = value.decode( 'ascii' ) 67 self.value = value 68 self.context = context 69 self.display = True 70 71 def __str__(self): 72 if self.value is None: 73 return str(self.spec.no_value) 74 return str(self.value) 75 76 @classmethod 77 def marshal( cls, value ): 78 ''' 111 """ 112 if self.spec.get("readonly"): 113 return value 114 if self.spec.get("optional"): 115 checked = False 116 if value: checked = "true" 117 checkbox = form_builder.CheckboxField( "is_" + self.spec.name, checked=checked ) 118 return checkbox.get_html() + self.get_html_field( value=value, context=context, other_values=other_values, **kwd ).get_html() 119 else: 120 return self.get_html_field( value=value, context=context, other_values=other_values, **kwd ).get_html() 121 122 def to_string( self, value ): 123 return str( value ) 124 125 @classmethod 126 def marshal ( cls, value ): 127 """ 79 128 This method should/can be overridden to convert the incoming 80 129 value to whatever type it is supposed to be. 81 ''' 82 return value 83 84 @classmethod 85 def validate( cls, value ): 86 ''' 130 """ 131 return value 132 133 def validate( self, value ): 134 """ 87 135 Throw an exception if the value is invalid. 88 '''136 """ 89 137 pass 90 138 91 def get_html_field( self, value=None, other_values={} ): 92 return form_builder.TextField( self.spec.name, value=value or self.value ) 93 94 def get_html( self ): 95 if self.spec.get("readonly"): 96 return self.value 97 if self.spec.get("optional"): 98 checked = False 99 if self.value: checked = "true" 100 checkbox = form_builder.CheckboxField( "is_" + self.spec.name, checked=checked ) 101 return checkbox.get_html() + self.get_html_field().get_html() 102 else: 103 return self.get_html_field().get_html() 104 105 @classmethod 106 def unwrap( cls, form_value ): 107 value = cls.marshal(form_value) 108 cls.validate(value) 109 return value 110 139 140 def unwrap( self, form_value ): 141 """ 142 Turns a value into its storable form. 143 """ 144 value = self.marshal( form_value ) 145 self.validate( value ) 146 return value 147 148 def wrap( self, value ): 149 """ 150 Turns a value into its usable form. 151 """ 152 return value 153 154 111 155 class MetadataElementSpec( object ): 112 '''156 """ 113 157 Defines a metadata element and adds it to the metadata_spec (which 114 158 is a MetadataSpecCollection) of datatype. 115 '''159 """ 116 160 117 161 def __init__( self, datatype, name=None, desc=None, param=MetadataParameter, default=None, no_value = None, visible=True, **kwargs ): 118 162 self.name = name 119 163 self.desc = desc or name 120 self.param = param121 164 self.default = default 122 165 self.no_value = no_value … … 124 167 # Catch-all, allows for extra attributes to be set 125 168 self.__dict__.update(kwargs) 126 datatype.metadata_spec.append( self ) 169 #set up param last, as it uses values set above 170 self.param = param( self ) 171 datatype.metadata_spec.append( self ) #add spec element to the spec 127 172 def get( self, name ): 128 173 return self.__dict__.get(name, None) 129 def hasAttribute( self, attribute ): 130 return ((self.permission & attribute) == attribute) 131 def wrap( self, value, context ): 132 return self.param( self, value, context ) 133 def unwrap( self, form_value, context ): 134 return self.param.unwrap( form_value ) 135 136 137 # Basic attributes for describing metadata elements 138 MetadataAttributes = Bunch( 139 READONLY = 1, 140 OPTIONAL = 2 141 ) 142 143 144 class MetadataCollection: 145 """ 146 MetadataCollection is not a collection at all, but rather a proxy 147 to the real metadata which is stored as a Bunch. This class 148 handles updating the reference to the Bunch when it is changed (so 149 that SQLAlchemy knows to update it) as well as returning default 150 values in cases when metadata is not set. 151 """ 152 def __init__(self, parent, spec): 153 self.parent = parent 154 if spec is None: self.spec = MetadataSpecCollection() 155 else: self.spec = spec 156 157 #set default metadata values 158 if self.parent._metadata is None: 159 self.parent._metadata = {} 160 161 def __iter__(self): 162 return self.bunch.__iter__() 163 def get( self, key, default=None ): 164 try: 165 return self.bunch.get( key, default ) or self.spec[key].default 166 except: 167 return default 168 def items(self): 169 return iter( [(k, self.get(k)) for k in self.spec.iterkeys() ] ) 170 def __str__(self): 171 return dict( self.items() ).__str__() 172 def __nonzero__(self): 173 return self.bunch.__nonzero__() 174 def __getattr__(self, name): 175 if name == "bunch": 176 return self.parent._metadata 177 if name in self.bunch: 178 return self.bunch[name] 179 if name in self.spec: 180 return self.spec[name].default 181 def __setattr__(self, name, value): 182 if name in ["parent","spec"]: 183 self.__dict__[name] = value 184 elif name == "bunch": 185 self.parent._metadata = value 186 else: 187 self.bunch[name] = value 188 def element_is_set( self, name ): 189 return bool( self.bunch.get( name, False ) ) 190 191 MetadataElement = Statement(MetadataElementSpec) 192 174 def wrap( self, value ): 175 """ 176 Turns a stored value into its usable form. 177 """ 178 return self.param.wrap( value ) 179 def unwrap( self, value ): 180 """ 181 Turns an incoming value into its storable form. 182 """ 183 return self.param.unwrap( value ) 184 185 MetadataElement = Statement( MetadataElementSpec ) 193 186 194 187 """ … … 197 190 198 191 class SelectParameter( MetadataParameter ): 199 def __init__( self, spec, value, context ): 200 MetadataParameter.__init__( self, spec, value, context ) 201 self.values = spec.get("values") 202 203 def __setattr__(self, name, value): 204 MetadataParameter.__setattr__(self, name, value) 205 if name in ['value']: 206 if value is None: 207 MetadataParameter.__setattr__(self, name, []) 208 elif not isinstance(value, list): 209 MetadataParameter.__setattr__(self, name, [value]) 210 211 def __iter__( self ): 212 return iter( self.value ) 213 214 def __str__(self): 215 if self.value in [None, []]: 216 return str(self.spec.no_value) 217 return ",".join(map(str,self.value)) 218 219 def get_html_field( self, value=None, other_values={} ): 220 field = form_builder.SelectField( self.spec.name, multiple=self.spec.get("multiple"), display=self.spec.get("display") ) 221 for value, label in self.values or [(value, value) for value in self.value]: 192 def __init__( self, spec ): 193 MetadataParameter.__init__( self, spec ) 194 self.values = self.spec.get( "values" ) 195 self.multiple = string_as_bool( self.spec.get( "multiple" ) ) 196 197 def to_string( self, value ): 198 if value in [ None, [] ]: 199 return str( self.spec.no_value ) 200 if not isinstance( value, list ): 201 value = [value] 202 return ",".join( map( str, value ) ) 203 204 def get_html_field( self, value=None, context={}, other_values={}, values=None, **kwd ): 205 field = form_builder.SelectField( self.spec.name, multiple=self.multiple, display=self.spec.get("display") ) 206 for val, label in self.values or values or [(val2, val2) for val2 in value]: 222 207 try: 223 if value in self.value:224 field.add_option( label, val ue, selected=True )208 if ( self.multiple and val in value ) or ( not self.multiple and val == value ): 209 field.add_option( label, val, selected=True ) 225 210 else: 226 field.add_option( label, val ue, selected=False )211 field.add_option( label, val, selected=False ) 227 212 except TypeError: 228 field.add_option( val ue, label, selected=False )213 field.add_option( val, label, selected=False ) 229 214 230 215 return field 231 216 232 def get_html( self ):217 def get_html( self, value, context={}, other_values={}, values=None, **kwd ): 233 218 if self.spec.get("readonly"): 234 if self.value in [None, [] ]: 235 return str(self.spec.no_value) 236 return ", ".join(map(str,self.value)) 237 return MetadataParameter.get_html(self) 219 if value in [ None, [] ]: 220 return str( self.spec.no_value ) 221 return ", ".join( map( str, value ) ) 222 return MetadataParameter.get_html( self, value, context=context, other_values=other_values, values=values, **kwd ) 223 224 def wrap( self, value ): 225 value = self.marshal( value ) #do we really need this (wasteful)? - yes because we are not sure that all existing selects have been stored previously as lists. Also this will handle the case where defaults/no_values are specified and are single non-list values. 226 if self.multiple: 227 return value 228 elif value: 229 return value[0] #single select, only return the first value 230 return None 238 231 239 232 @classmethod … … 241 234 # Store select as list, even if single item 242 235 if value is None: return [] 243 if not isinstance( value, list): return [value]236 if not isinstance( value, list ): return [value] 244 237 return value 245 238 246 239 class RangeParameter( SelectParameter ): 247 def __init__( self, spec , value, context):248 SelectParameter.__init__( self, spec , value, context)240 def __init__( self, spec ): 241 SelectParameter.__init__( self, spec ) 249 242 # The spec must be set with min and max values 250 _min = spec.get("min") or 1 251 _max = spec.get("max") or 1 252 step = self.spec.get("step") or 1 253 self.values = zip(range( _min, _max, step ), range( _min, _max, step )) 254 243 self.min = spec.get( "min" ) or 1 244 self.max = spec.get( "max" ) or 1 245 self.step = self.spec.get( "step" ) or 1 246 247 def get_html_field( self, value=None, context={}, other_values={}, values=None, **kwd ): 248 if values is None: 249 values = zip( range( self.min, self.max, self.step ), range( self.min, self.max, self.step )) 250 return SelectParameter.get_html_field( self, value=value, context=context, other_values=other_values, values=values, **kwd ) 251 252 def get_html( self, value, context={}, other_values={}, values=None, **kwd ): 253 if values is None: 254 values = zip( range( self.min, self.max, self.step ), range( self.min, self.max, self.step )) 255 return SelectParameter.get_html( self, value, context=context, other_values=other_values, values=values, **kwd ) 256 255 257 @classmethod 256 258 def marshal( cls, value ): 257 values = [int(x) for x in value] 259 value = SelectParameter.marshal( value ) 260 values = [ int(x) for x in value ] 258 261 return values 259 262 260 263 class ColumnParameter( RangeParameter ): 261 def __init__( self, spec, value, context ): 262 RangeParameter.__init__( self, spec, value, context ) 263 column_range = range( 1, context.metadata.columns+1, 1 ) 264 self.values = zip( column_range, column_range ) 265 264 265 def get_html_field( self, value=None, context={}, other_values={}, values=None, **kwd ): 266 if values is None and context: 267 column_range = range( 1, context.columns+1, 1 ) 268 values = zip( column_range, column_range ) 269 return RangeParameter.get_html_field( self, value=value, context=context, other_values=other_values, values=values, **kwd ) 270 271 def get_html( self, value, context={}, other_values={}, values=None, **kwd ): 272 if values is None and context: 273 column_range = range( 1, context.columns+1, 1 ) 274 values = zip( column_range, column_range ) 275 return RangeParameter.get_html( self, value, context=context, other_values=other_values, values=values, **kwd ) 276 277 class ColumnTypesParameter( MetadataParameter ): 278 279 def to_string( self, value ): 280 return ",".join( map( str, value ) ) 281 282 class PythonObjectParameter( MetadataParameter ): 283 def __init__( self, spec ): 284 MetadataParameter.__init__( self, spec ) 285 286 def to_string( self, value ): 287 if not value: 288 return self.spec.to_string( self.spec.no_value ) 289 return self.spec.to_string( value ) 290 291 def get_html_field( self, value=None, context={}, other_values={}, **kwd ): 292 return form_builder.TextField( self.spec.name, value=self.to_string( value ) ) 293 294 def get_html( self, value=None, context={}, other_values={}, **kwd ): 295 return str( self ) 296 266 297 @classmethod 267 298 def marshal( cls, value ): 268 return int(value) 269 270 class ColumnTypesParameter( MetadataParameter ): 271 def __init__( self, spec, value, context ): 272 MetadataParameter.__init__( self, spec, value, context ) 273 def __str__(self): 274 return ",".join( map( str, self.value ) ) 275 276 class PythonObjectParameter( MetadataParameter ): 277 def __init__( self, spec, value, context ): 278 MetadataParameter.__init__( self, spec, value, context ) 279 self.value = value 280 self.display = False 281 282 def __str__(self): 283 if not self.value: 284 return self.spec.to_string( self.spec.no_value ) 285 return self.spec.to_string( self.value ) 286 287 def get_html_field( self, value=None, other_values={} ): 288 return form_builder.TextField( self.spec.name, value=str( self ) ) 289 290 def get_html( self ): 291 return str( self ) 292 293 @classmethod 294 def marshal( cls, value ): 295 return value 296 299 return value lib/galaxy/datatypes/sequence.py
r1554 r1557 25 25 """Add metadata elements""" 26 26 MetadataElement( name="species", desc="Species", default=[], param=metadata.SelectParameter, multiple=True, readonly=True, no_value=None ) 27 MetadataElement( name="species_chromosomes", desc="Species Chromosomes", value={}, param=metadata.PythonObjectParameter, readonly=True, no_value={}, to_string=str )27 MetadataElement( name="species_chromosomes", desc="Species Chromosomes", value={}, param=metadata.PythonObjectParameter, readonly=True, no_value={}, to_string=str, visible=False ) 28 28 29 29 class Fasta( Sequence ): lib/galaxy/datatypes/tabular.py
r1531 r1557 12 12 from galaxy.datatypes import metadata 13 13 from galaxy.datatypes.metadata import MetadataElement 14 from galaxy.datatypes.metadata import MetadataAttributes15 14 16 15 log = logging.getLogger(__name__) lib/galaxy/model/__init__.py
r1543 r1557 162 162 def get_metadata( self ): 163 163 if not hasattr( self, '_metadata_collection' ): 164 self._metadata_collection = MetadataCollection( self , self.datatype.metadata_spec)164 self._metadata_collection = MetadataCollection( self ) 165 165 return self._metadata_collection 166 166 def set_metadata( self, bunch ): … … 193 193 def change_datatype( self, new_ext ): 194 194 self.clear_associated_files() 195 if hasattr( self, '_metadata_collection' ):196 del self._metadata_collection197 195 datatypes_registry.change_datatype( self, new_ext ) 198 196 def get_size( self ): lib/galaxy/tools/__init__.py
r1553 r1557 1314 1314 if rval is None: 1315 1315 rval = self.metadata.spec[name].no_value 1316 rval = self.metadata.spec[name].wrap( rval, self.metadata.parent ) 1316 rval = self.metadata.spec[name].param.to_string( rval ) 1317 setattr( self, name, rval ) #lets store this value, so we don't need to recalculate if needed again 1317 1318 return rval 1318 1319 def __nonzero__( self ): lib/galaxy/tools/parameters/basic.py
r1544 r1557 831 831 if dataset: 832 832 for meta_key, meta_dict in filter_value.iteritems(): 833 if ",".join( dataset.metadata.get( meta_key ) ) == meta_dict['value']:833 if dataset.metadata.spec[meta_key].param.to_string( dataset.metadata.get( meta_key ) ) == meta_dict['value']: 834 834 options.extend( meta_dict['options'] ) 835 835 return options lib/galaxy/tools/parameters/validation.py
r1510 r1557 252 252 if not value: return 253 253 if hasattr( value, "metadata" ): 254 if str( getattr( value.datatype.metadata_spec, self.metadata_name ).wrap( value.metadata.get( self.metadata_name ), value ) ) in self.valid_values:254 if value.metadata.spec[self.metadata_name].param.to_string( value.metadata.get( self.metadata_name ) ) in self.valid_values: 255 255 return 256 256 raise ValueError( self.message ) lib/galaxy/web/controllers/root.py
r1551 r1557 220 220 221 221 # The following for loop will save all metadata_spec items 222 for name, spec in data. datatype.metadata_spec.items():222 for name, spec in data.metadata.spec.items(): 223 223 if spec.get("readonly"): 224 224 continue … … 226 226 if optional and optional == 'true': 227 227 # optional element... == 'true' actually means it is NOT checked (and therefore ommitted) 228 setattr(data.metadata, name,None)228 setattr(data.metadata, name, None) 229 229 else: 230 setattr( data.metadata,name,spec.unwrap(p.get(name, None), p))230 setattr( data.metadata, name, spec.unwrap( p.get (name, None) ) ) 231 231 232 232 data.datatype.after_edit( data ) … … 235 235 elif p.detect: 236 236 # The user clicked the Auto-detect button on the 'Edit Attributes' form 237 for name, spec in data. datatype.metadata_spec.items():237 for name, spec in data.metadata.spec.items(): 238 238 # We need to be careful about the attributes we are resetting 239 if name != 'name' and name != 'info' and name != 'dbkey':239 if name not in [ 'name', 'info', 'dbkey' ]: 240 240 if spec.get( 'default' ): 241 setattr( data.metadata, name,spec.unwrap( spec.get( 'default' ), spec ))241 setattr( data.metadata, name, spec.unwrap( spec.get( 'default' ) ) ) 242 242 data.datatype.set_meta( data ) 243 243 data.datatype.after_edit( data ) … … 259 259 # sets it properly in the metadata 260 260 data.metadata.dbkey = data.dbkey 261 metadata = list()262 # a list of MetadataParemeters263 for name, spec in data.datatype.metadata_spec.items():264 if spec.visible:265 metadata.append( spec.wrap( data.metadata.get(name), data ) )266 261 # let's not overwrite the imported datatypes module with the variable datatypes? 262 ### the built-in 'id' is overwritten in lots of places as well 267 263 ldatatypes = [x for x in trans.app.datatypes_registry.datatypes_by_extension.iterkeys()] 268 264 ldatatypes.sort() 269 265 trans.log_event( "Opened edit view on dataset %s" % str(id) ) 270 return trans.fill_template( "/dataset/edit_attributes.mako", data=data, metadata=metadata,266 return trans.fill_template( "/dataset/edit_attributes.mako", data=data, 271 267 datatypes=ldatatypes, err=None ) 272 268 templates/dataset/edit_attributes.mako
r1549 r1557 39 39 <div style="clear: both"></div> 40 40 </div> 41 %for element in metadata:42 %if element.display:41 %for name, spec in data.metadata.spec.items(): 42 %if spec.visible: 43 43 <div class="form-row"> 44 44 <label> 45 ${ element.spec.desc}:45 ${spec.desc}: 46 46 </label> 47 47 <div style="float: left; width: 250px; margin-right: 10px;"> 48 ${ element.get_html()}48 ${data.metadata.get_html_by_name( name )} 49 49 </div> 50 50 <div style="clear: both"></div>