Skip to content

[WIP] Fixes #8113 : fix deprecation msg for attribute(property)#8122

Closed
Dorozhko-Anton wants to merge 2 commits intoscikit-learn:masterfrom
Dorozhko-Anton:attribute_deprecation
Closed

[WIP] Fixes #8113 : fix deprecation msg for attribute(property)#8122
Dorozhko-Anton wants to merge 2 commits intoscikit-learn:masterfrom
Dorozhko-Anton:attribute_deprecation

Conversation

@Dorozhko-Anton
Copy link
Copy Markdown

Reference Issue

Fixes #8113

What does this implement/fix? Explain your changes.

If deprecated function is attribute (@property) then change message to "Attribute ... "

To check if function is an attribute

  1. check that it is method (first argument should be self)
  2. get all properties of class
  3. check if name of function in properties

Any other comments?

For now I avoid this #8113 (comment)
because I have not figured out how to wrap property object properly

@jnothman
Copy link
Copy Markdown
Member

Yes, this is a bit hacky, but I don't mind it entirely. Doesn't work for x = property(deprecated('blah')(getter), setter), since it assumes the property attribute is identical to the function name.

@jnothman
Copy link
Copy Markdown
Member

In terms of properly wrapping a property, is return prop.getter(deprecated(prop.fget, extra=extra, entity='Attribute')) going to work, assuming we only want to warn upon getting, for now?

@Dorozhko-Anton
Copy link
Copy Markdown
Author

So may be It is OK to make deeper introspection and compare name of the method with all properties' getters, setters, deleters. Then I have a question about warning message. Should I discriminate getter, setter and deleter in the deprecation message?

x = property(fget=deprecated("deprecated")(x_getter), fset=x_setter)

Should it print out?

Getter of Attribute x is deprecated; ... 

@jnothman
Copy link
Copy Markdown
Member

jnothman commented Dec 29, 2016 via email

@Dorozhko-Anton
Copy link
Copy Markdown
Author

I have added comparison with setters, getters and deleters. But there is still problem with checking that f is method, because ispect.ismethod() does not always work and there were changes in python 3 of signature inspection.

def ismethod(f):
    spec = inspect.getargspec(f) //deprecated in python 3
    return 'self' in spec.args

@jnothman
Copy link
Copy Markdown
Member

My suggestion of using fget, etc. was in the case that we decorated the property (deprecated(property(func))) rather than the current property(decorated(func)). I'm a bit confused what you're doing now.

@Akshay0724
Copy link
Copy Markdown
Contributor

Akshay0724 commented Jan 7, 2017

Both part( i.e deprecated(property(funct.)) & property(deprecated(funct.)) ) have to be handled separately.
Order of execution of both is reversed:

Case 1.
@Property
@deprecated
Method()

In this case first decorated class object is created,than it becomes property.Object which is passed to __ call __(in class deprecated in decorating.py) looks like a method.So this part should be handled in _decorate_fun()(line 62 in decorating.py)
How to detect a method is property or not?
from args(passed to method) we can get self(i.e object of class) and from that object through inspect module we can get all the property of that class.Now we have to check if any function name in property(i.e fget, fset, fdel) matches with with the name of function passed to decorator for ever property. If match is found than it is a property otherwise a method.

Case 2.
@deprecated
@Property
Method()

In this case method get converted to property first and than deprecated object is created. So object which is passed to decorator can be in investigated at that time that it is a method or property in __ call __() itself.
I have made changes to deprecation.py

  1. __ call __() method is modified so that it can check Case 2.
  2. _decorate_property method is added to handle Case 2.
  3. _decorate_fun is modified to handle Case1. as well as a normal method.

Notebook contain modified deprecation.py file and a test case

@jnothman
Copy link
Copy Markdown
Member

jnothman commented Jan 7, 2017 via email

@Akshay0724
Copy link
Copy Markdown
Contributor

Well if we consider only one case and neglect the other than warning of one case will not look correct.Though both the order looks correct so we have to mention that which order to be followed while deprecating a property.

@jnothman
Copy link
Copy Markdown
Member

jnothman commented Jan 8, 2017 via email

@Akshay0724
Copy link
Copy Markdown
Contributor

Deprecating a property in this way---

`@deprecated(msg)
def getx(self): 
    print "Output: Deprecated Property fget"
    return self.__x    

@deprecated(msg)
def setx(self, value): 
    print "Output: Deprecated Property fset"
    self.__x = value

@deprecated(msg)    
def delx(self):  
    print "Output: Deprecated Property fdel"
    del self.__x
    
Y = property(fget = getx,fset = setx,fdel = delx, doc = "I'm the 'Y' property.")`

is analogous to case 1. of my previous comment.So this should be handled alone.

Can I make a pull request handling this case?
Thanks

@jnothman
Copy link
Copy Markdown
Member

jnothman commented Jan 8, 2017 via email

@Akshay0724
Copy link
Copy Markdown
Contributor

Akshay0724 commented Jan 8, 2017

(I have just given a example if we deprecate only one of the method than also it will work and give warning only when that method is called.)

Sorry, I'd not understand what you are trying to say. I mean when we deprecate any one of getter,setter,deleter than how could the deprecated class be called when method other than the deprecated one is called.

Or I think it is common to deprecate getter and warning would be shown only when it is used.

@Akshay0724
Copy link
Copy Markdown
Contributor

Akshay0724 commented Jan 11, 2017

Hello @jnothman, I have found a solution to your stated problem,by this solution we did not need to deprecate each of the accessors instead we can directly deprecate an attribute.

By using builtins module in python we can explicitly write code for creating a attribute. So after writing that piece of code we can create an attribute in this way--

  @property
  @deprecated
  def X():
        def getx(self):
           return self.x

        def setx(self,x):
           self.x=x

        def delx(self):
           del x

Please share your view about this approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Warning of utils.deprecated for properties is ugly

3 participants