astropy/astropy — pull request #587 by iguananaut (2013-01-11 18:33:55+00:00)
Title: Undefined behavior for Unit multiplied/divided by a Quantity

I'm not even sure if this is *supposed* to be able to work. I can multiply a `Quantity` by a `Unit` though:

```
In [5]: from astropy import units as u

In [6]: Quantity(3e8, 'm/s') * u.s
Out[6]:
```

which at least seems logical. The reverse not so much:

```
In [7]: u.s * Quantity(3e8, 'm/s')
Out[7]: ERROR: ValueError: Unknown format code 'e' for object of type 'unicode' [astropy.units.format.generic]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in ()
----> 1 u.s * Quantity(3e8, 'm/s')

/bray/sc1/root/home/embray/.virtualenvs/astropy-dev-27/lib/python2.7/site-packages/IPython/core/displayhook.pyc in __call__(self, result)
236 self.start_displayhook()
237 self.write_output_prompt()
--> 238 format_dict = self.compute_format_data(result)
239 self.write_format_data(format_dict)
240 self.update_user_ns(result)

/bray/sc1/root/home/embray/.virtualenvs/astropy-dev-27/lib/python2.7/site-packages/IPython/core/displayhook.pyc in compute_format_data(self, result)
148 MIME type representation of the object.
149 """
--> 150 return self.shell.display_formatter.format(result)
151
152 def write_format_data(self, format_dict):

/bray/sc1/root/home/embray/.virtualenvs/astropy-dev-27/lib/python2.7/site-packages/IPython/core/formatters.pyc in format(self, obj, include, exclude)
124 continue
125 try:
--> 126 data = formatter(obj)
127 except:
128 # FIXME: log the exception

/bray/sc1/root/home/embray/.virtualenvs/astropy-dev-27/lib/python2.7/site-packages/IPython/core/formatters.pyc in __call__(self, obj)
445 type_pprinters=self.type_printers,
446 deferred_pprinters=self.deferred_printers)
--> 447 printer.pretty(obj)
448 printer.flush()
449 return stream.getvalue()

/bray/sc1/root/home/embray/.virtualenvs/astropy-dev-27/lib/python2.7/site-packages/IPython/lib/pretty.pyc in pretty(self, obj)
358 if callable(meth):
359 return meth(obj, self, cycle)
--> 360 return _default_pprint(obj, self, cycle)
361 finally:
362 self.end_group()

/bray/sc1/root/home/embray/.virtualenvs/astropy-dev-27/lib/python2.7/site-packages/IPython/lib/pretty.pyc in _default_pprint(obj, p, cycle)
478 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
479 # A user-provided repr.
--> 480 p.text(repr(obj))
481 return
482 p.begin_group(1, '<')

/bray/sc1/root/src/astropy/astropy/astropy/units/core.pyc in __repr__(self)
908 def __repr__(self):
909 if len(self._bases):
--> 910 return super(CompositeUnit, self).__repr__()
911 else:
912 return 'Unit(dimensionless)'

/bray/sc1/root/src/astropy/astropy/astropy/units/core.pyc in __repr__(self)
74
75 def __repr__(self):
---> 76 return 'Unit("' + str(self) + '")'
77
78 def to_string(self, format='generic'):

/bray/sc1/root/src/astropy/astropy/astropy/units/core.pyc in __str__(self)
71 def __str__(self):
72 """Return string representation for unit"""
---> 73 return unit_format.Generic().to_string(self)
74
75 def __repr__(self):

/bray/sc1/root/src/astropy/astropy/astropy/units/format/generic.pyc in to_string(self, unit)
272 if isinstance(unit, core.CompositeUnit):
273 if unit.scale != 1 and self._show_scale:
--> 274 s = '{0:e} '.format(unit.scale)
275 else:
276 s = ''

ValueError: Unknown format code 'e' for object of type 'unicode'
```

What's actually happening here is that `unit.scale` is a `Quantity` object when it should just be a float or something. `UnitBase.__mul__` doesn't handle this case correctly. Likewise for `UnitBase.__div__`.

This is easy to fix, but should a `Unit` times a `Quantity` be a `Quantity` or a new `CompositeUnit`?