@@ -185,6 +185,19 @@ def _maybe_make_unit_desc(self, unit_desc):
185
185
unit_desc ))
186
186
return unit_desc
187
187
188
+ def _maybe_make_dimension (self , dimension ):
189
+ """Return a `measurements.Dimension` instance."""
190
+ # For backwards compatibility the argument can be either a Dimension, a
191
+ # string or a `units.UnitDescriptor`.
192
+ if isinstance (dimension , Dimension ):
193
+ return dimension
194
+ if isinstance (dimension , units .UnitDescriptor ):
195
+ return Dimension .from_unit_descriptor (dimension )
196
+ if isinstance (dimension , str ):
197
+ return Dimension .from_string (string )
198
+
199
+ raise TypeError ('Cannot convert %s to a dimension' , dimension )
200
+
188
201
def with_units (self , unit_desc ):
189
202
"""Declare the units for this Measurement, returns self for chaining."""
190
203
self .units = self ._maybe_make_unit_desc (unit_desc )
@@ -193,7 +206,7 @@ def with_units(self, unit_desc):
193
206
def with_dimensions (self , * dimensions ):
194
207
"""Declare dimensions for this Measurement, returns self for chaining."""
195
208
self .dimensions = tuple (
196
- self ._maybe_make_unit_desc (dim ) for dim in dimensions )
209
+ self ._maybe_make_dimension (dim ) for dim in dimensions )
197
210
return self
198
211
199
212
def with_validator (self , validator ):
@@ -304,6 +317,55 @@ def set(self, value):
304
317
self .is_value_set = True
305
318
306
319
320
+ class Dimension (object ):
321
+ """Dimension for multi-dim Measurements.
322
+
323
+ Dimensions optionally include a unit and a description. This is intended
324
+ as a drop-in replacement for UnitDescriptor for backwards compatibility.
325
+ """
326
+
327
+ def __init__ (self , description = '' , unit = units .NO_DIMENSION ):
328
+ self .description = description
329
+ self .unit = unit
330
+
331
+ @classmethod
332
+ def from_unit_descriptor (cls , unit_desc ):
333
+ return cls (unit = unit_desc )
334
+
335
+ @classmethod
336
+ def from_string (cls , string ):
337
+ """Convert a string into a Dimension"""
338
+ # Note: There is some ambiguity as to whether the string passed is intended
339
+ # to become a unit looked up by name or suffix, or a Dimension descriptor.
340
+ if string in units .UNITS_BY_ALL :
341
+ return cls (description = string , unit = units .Unit (string ))
342
+ else :
343
+ return cls (description = string )
344
+
345
+ @property
346
+ def code (self ):
347
+ """Provides backwards compatibility to `units.UnitDescriptor` api."""
348
+ return self .unit .code
349
+
350
+ @property
351
+ def suffix (self ):
352
+ """Provides backwards compatibility to `units.UnitDescriptor` api."""
353
+ return self .unit .suffix
354
+
355
+ @property
356
+ def name (self ):
357
+ """Provides backwards compatibility to `units.UnitDescriptor` api."""
358
+ return self .description or self .unit .name
359
+
360
+ def _asdict (self ):
361
+ return {
362
+ 'code' : self .code ,
363
+ 'description' : self .description ,
364
+ 'name' : self .name ,
365
+ 'suffix' : self .suffix ,
366
+ }
367
+
368
+
307
369
class DimensionedMeasuredValue (mutablerecords .Record (
308
370
'DimensionedMeasuredValue' , ['name' , 'num_dimensions' ],
309
371
{'notify_value_set' : None , 'value_dict' : collections .OrderedDict })):
0 commit comments