Code Monkey home page Code Monkey logo

resumeback's Issues

classmethod decorations broke in Python 3.9

Something must have changed with how classmethods function in 3.9.

λ pytest -k test_classmethod
================================================= test session starts =================================================
platform linux -- Python 3.9.5, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /home/fichte/code/resumeback
plugins: xonsh-0.9.27
collected 60 items / 58 deselected / 2 selected

tests/test_descriptors.py F.                                                                                    [100%]

====================================================== FAILURES =======================================================
__________________________________________________ test_classmethod ___________________________________________________

    def test_classmethod():
        ts = State()

        class B:
            @classmethod
            @send_self
            def clsmethod(this, cls, param):
                yield defer(this.next)
                assert cls is B
                ts.run = param

        b = B()
>       wait_until_finished(b.clsmethod(123))

tests/test_descriptors.py:33:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
resumeback/__init__.py:371: in __call__
    gen_wrapper.next()  # Start the first iteration
resumeback/__init__.py:109: in _next
    return self._send(generator)
resumeback/__init__.py:147: in _send
    return generator.send(value)
resumeback/__init__.py:357: in wrapper
    return (yield from self.func(gen_wrapper, *args, **kwargs))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

this = <class 'tests.test_descriptors.test_classmethod.<locals>.B'>
cls = <resumeback.GeneratorWrapper object at 0x7f68d3808430>, param = 123

    @classmethod
    @send_self
    def clsmethod(this, cls, param):
>       yield defer(this.next)
E       AttributeError: type object 'B' has no attribute 'next'

tests/test_descriptors.py:28: AttributeError
------------------------------------------------ Captured stdout call -------------------------------------------------
<bound method test_classmethod.<locals>.B.clsmethod of <class 'tests.test_descriptors.test_classmethod.<locals>.B'>> (123,)
=============================================== short test summary info ===============================================
FAILED tests/test_descriptors.py::test_classmethod - AttributeError: type object 'B' has no attribute 'next'
===================================== 1 failed, 1 passed, 58 deselected in 0.13s ======================================

Accumulate decorators and decorate myself like @send_self@classmethod

At first glance, I did not know what yield do in Python, but after having a hard time studying it, I finally understand the idea. But having calling this = yield and later passing the mysterious this.send as callback, does not seem clear than right away defining some lambda or closure. However, you should ask this to a python beginning which do not know neither closures nor what yield does, because I am already used to lambdas and closures. Or perhaps I am not seeing the big picture because the example is too simple or I am too dumb, therefore in a more complex scenario this could have great advantages. Then you could add also a complex example using closures vs resumeback.


I got that linear order, however I do not see how that can easier than just use closures. My problem is against the declaration of the first this = yield and the second yield function(this.send). If I look both codes:

  1. With closure
    def main():
        arbitrary_value = 10
    
        def on_done(number):
            number = str(number)
            print("Result:", number * arbitrary_value)
    
        ask_for_user_input("Please enter a number", on_done)
  2. With resumeback
    from resumeback import send_self
    
    @send_self
    def main():
        this = yield  # "this" is now a reference to the just-created generator
        arbitrary_value = 10
    
        # Yield pauses execution until one of the generator methods is called,
        # such as `.send`, which we provide as the callback parameter.
        number = yield ask_for_user_input("Please enter a number", this.send)
        number = str(number)
        print("Result:", number * arbitrary_value)

I can clearly understand when I what is going on with closures. But when looking at those two yield's with resumeback, I do not see it working clearly. Basically, I would say that closures are more intuitive than the this = yied plus the second yield function(this.send) call.

I think it would help, if the first this = yield call could not required, so I can forget about it. Hence, only the second yield call could be done like this:

from resumeback import send_self

@send_self
def main():
    arbitrary_value = 10

    # Yield pauses execution until one of the generator methods is called,
    # such as `.send`, which we provide as the callback parameter.
    number = yield ask_for_user_input("Please enter a number", send_self)
    number = str(number)
    print("Result:", number * arbitrary_value)

Can the this = yield call be embed inside the decorator @send_self and formerly to "send myself" I could just call yield function(send_self)?

I would say that it would look much better than having to remember both to do the first call this = yield and yield function(this.send).

@FichteFoll I could do this:

from resumeback import send_self

@send_self
def main(this):
    # Yield pauses execution until one of the generator methods is called,
    # such as `.send`, which we provide as the callback parameter.
    number = yield ask_for_user_input("Please enter a number", this.send)
    number = str(number)
    print("Result:", number * arbitrary_value)

I'm unsure how I would make the above work for methods though. Gonna need even more magic

I would suggest the this to be a function pointer, so, it can be more straight forward. However, I do not know about other usages of it where could not be pointing to a function directly:

from resumeback import send_self

@send_self
def main(myself):
    arbitrary_value = 10

    # Yield pauses execution until one of the generator methods is called,
    # such as `.send`, which we provide as the callback parameter.
    number = yield ask_for_user_input("Please enter a number", myself)
    number = str(number)
    print("Result:", number * arbitrary_value)

For classmethods, perhaps it could be a cumulative sum of decorators:

from resumeback import send_self

@send_self
@classmethod
def main(myself, cls):
    arbitrary_value = 10

    # Yield pauses execution until one of the generator methods is called,
    # such as `.send`, which we provide as the callback parameter.
    number = yield ask_for_user_input("Please enter a number", myself)
    number = str(number)
    print("Result:", number * arbitrary_value)

But I do not know whether or not you can patch stuff like that in Python.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.