1. Olemis Lang
  2. brython
  3. Issues
Issue #43 resolved

property decorator does not return correct value

Billy Earney
created an issue

I've noticed that "many" python modules use the property decorator quite a bit, and property is a builtin function, so I've tried to partially implement it to to obtain its retrieve (fget) functionality. I think I've done this properly, but I'm not sure the $DecoratorCTX and a classes getattr will handle this properly..

for example, the code below should print out 5, but it returns the "function" instead, so its just ignoring the decorator.

class myclass:
  @property
  def getx(self):
      return 5

x=myclass()
print(x.getx)

Any suggestions on how to accomplish this?

Comments (8)

  1. Billy Earney reporter

    Pierre,

    Unless you have started on a solution, I think I've "mentally" figured out what needs to happen. I still need to code it, but I'll try to do that later today..

  2. Billy Earney reporter

    Pierre, the property decorator seems to work on a simple function but fails on examples like the one above. I've spent some time looking at DecoratorCtx in py2js.js and resolve_attr in py_utils.js, and I have a basic understanding of what is going on, but I'm not sure how to expand the code to get it working for functions in classes. Any ideas?

    Thanks!

  3. Olemis Lang repo owner

    JFTR , this snippet

    a = [0]
    
    def dec(f):
        a[0] += 1
        return 1
    
    class C:
        @dec
        def m(self):
            pass
    
    print(a)
    print(C.m)
    print(C().m)
    

    outputs

    [1]
    <function C.m>
    <bound method 'm' of C object>
    <completed in 10 ms>
    

    so:

    • Decorator function is invoked
    • But its result is not recorded in class suite / attribute
    • ... won't work in instance scope either
  4. Olemis Lang repo owner

    OTOH this one will «work»

    a = [0]
    
    def dec(f):
        a[0] += 1
        return 1
    
    class C:
        def m(self):
            pass
        m = dec(m)
    
    print(a)
    print(C.m)
    print(C().m)
    

    output

    [1]
    1
    1
    <completed in 5 ms>
    
  5. Pierre Quentel

    The bug was related to the way the object $class is built inside the class definition function. When a method of name foo() is defined in the class, it is both a local name for the function, and an attribute of $class :

    var foo = $class.foo = function()  [...}
    

    In py2js.js this is done inside the function this.to_js() of $DefCtx : the scope of the function is searched by the line

    var scope = $get_scope(this)
    

    and if this scope is a class definition, the additional "$class.foo=" is added in the next lines

    In $DecoratorCtx, I had forgotten to check the scope when adding the line for the decorator

    Thanks to both of you for the report

  6. Olemis Lang repo owner

    great ! :)

    I've started a candidate solution for property and descriptors . May we track progress on this ticket as well , or create another one .

    Besides , I guess we should add some tests in test_decorator.py . Last time I saw it there were no test cases for these scenarios (since they failed ?)

  7. Billy Earney reporter

    Pierre,

    Thanks!.. I looked at the source you added, and I tried something close but not exactly what you did. I believe I just added $class. to the beginning of the local name, and thus replaced the local name with an attribute. I was wondering why you had both variable name (foo) and $class. variable name ($class.foo). I believe the above explains that.. Thanks!

  8. Log in to comment