Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Converting a constant to a Quantity breaks __repr__ #3537

Merged
merged 2 commits into from Mar 4, 2015

Conversation

mhvk
Copy link
Contributor

@mhvk mhvk commented Feb 23, 2015

import astropy.units as u

import astropy.constants

u.Quantity(astropy.constants.c)
/usr/lib/python2.7/site-packages/IPython/core/formatters.py:239: FormatterWarning: Exception in text/latex formatter: 'unicode' object has no attribute '_repr_latex_'
  FormatterWarning,
Out[3]: <repr(<astropy.units.quantity.Quantity at 0x7fba9bb288c0>) failed: AttributeError: 'Quantity' object has no '_unitstr' member>

@mhvk
Copy link
Contributor

mhvk commented Feb 23, 2015

The problem here (and perhaps also with #3538) is that Constant misses __array_finalize__ and hence does not update itself properly when being viewed as a new object:

import astropy.constants as c
c.c.view(c.Constant)
# <repr(<astropy.constants.constant.Constant at 0x7fc60bf6f828>) failed: AttributeError: 'Constant' object has no 'name' member>

@mhvk
Copy link
Contributor

mhvk commented Feb 23, 2015

OK, the now attached fixes to Constant should do it. @mdboom - please have a look, as I had to change the internals of Constant somewhat.

@astrofrog astrofrog added this to the v1.0.1 milestone Feb 23, 2015
@astrofrog
Copy link
Member

ping @embray since he wrote a lot of the constants code

@@ -159,10 +159,10 @@ def name(self):
return self._name

@lazyproperty
def unit(self):
def _unit(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we are privatizing a public property here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not quite so bad: since Constant subclasses from Quantity, it still has the unit property (which just returns _unit, i.e., this thing here). I had to make sure, though, that _unit was a Unit instance, which is what this lazyproperty takes care of.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Makes sense, then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure I follow though. Why do we need the property at all if this is also handled by Quantity now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I am the one who misunderstood: Constants are intialised with units passed in as a string. My impression was that this unit could not be parsed immediately since some units depend on constants. Is this true? I thought this was the reason they were passed through Unit only later, using lazyproperty. The change I made was to rename the string-based unit from _unit to _unit_string, so that both _unit and unit can return Unit objects (since it was a problem for Quantity if _unit was a string rather than a Unit instance).

@mhvk
Copy link
Contributor

mhvk commented Feb 23, 2015

Just to explain: part of the logic of changing _unit to _unit_string is that some Quantity internals assume that its subclasses have a proper Unit object in their _unit attribute (this is partially for speed-up, so one doesn't have to pass the unit through the Unit initializer all the time).

@mhvk mhvk added the constants label Feb 23, 2015
@embray
Copy link
Member

embray commented Feb 23, 2015

Just so I'm clear here, is the default here going to be equivalent to subok=True or subok=False? I don't see the point of converting a Constant down to a Quantity where unnecessary, since it's only dropping additional information for no gain.

@mhvk
Copy link
Contributor

mhvk commented Feb 24, 2015

@embray - if one passes through u.Quantity(<constant>), one will by default get a Quantity (i.e., subok=False). I also do not see a particular point of doing that, but it seems a sufficiently rare case that it is not worth adding an if-statement that would slow things down for other uses. And at least it should not raise any errors!

@embray
Copy link
Member

embray commented Feb 24, 2015

Okay. I guess that's fine--most of the time if someone where doing u.Quantity it would be just to convert/check that everything passed in to some routine is a Quantity to use in a calculation. In most cases that means combining it with other quantities/values in which case maintaining the Constant-ness is meaningless.

@mhvk
Copy link
Contributor

mhvk commented Feb 26, 2015

@embray - indeed, the issue was triggered by assert_quantity_allclose failing on u.Quantity(<constant>) -- and there it is fine if the constant-ness is lost.
But is my PR right? In particular, is it true that the unit has to be stored as a string initially because initialising the actual Unit would cause an import loop?

@embray
Copy link
Member

embray commented Mar 4, 2015

Sounds like for the most part there's no further issue here so I'll go ahead and merge.

embray added a commit that referenced this pull request Mar 4, 2015
Converting a constant to a Quantity breaks __repr__
@embray embray merged commit 0912059 into astropy:master Mar 4, 2015
@mhvk mhvk deleted the constant-array-finalize branch March 4, 2015 21:13
embray added a commit that referenced this pull request Mar 6, 2015
Converting a constant to a Quantity breaks __repr__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants