Coder Social home page Coder Social logo

Pass exception to generators about dishka HOT 3 CLOSED

Tishka17 avatar Tishka17 commented on June 19, 2024
Pass exception to generators

from dishka.

Comments (3)

lubaskinc0de avatar lubaskinc0de commented on June 19, 2024

i am try to work on this and will post my progress here.

from dishka.

lubaskinc0de avatar lubaskinc0de commented on June 19, 2024

Problem Description:

We have a generator function that provides a dependency at the beginning of the request lifecycle and finalizes it at the end of the request lifecycle.

Inside the request lifecycle e.g:

with container() as request_container:
    ...

An exception may occur, the dependency is finalized anyway, but we also want to give it information about the exception that occurred by sending its object to the generator using the .send() and .asend() methods for asynchronous generators.

The code

provider = Provider()


class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def __str__(self) -> str:
        return f"I'm {self.name}, my age is: {self.age}"


def get_person() -> Iterator[Person]:
    print("dependency initialization")

    x = yield Person("alex", 18)
    if isinstance(x, Exception):
        print("Some exception occurred:", x)

    print("dependency finalization")


provider.provide(get_person, scope=Scope.REQUEST)
container = make_container(provider)

with container() as request_container:
    person = request_container.get(Person)
    print("Hello!", person)
    raise ValueError("Some error in request scope!")

Expected output

dependency initialization
Hello! Im alex, my age is: 18
Some exception occurred: Some error in request scope!
dependency finalization

<Traceback here>

Current output

dependency initialization
Hello! Im alex, my age is: 18
dependency finalization

<Traceback here>

Correct me if I'm wrong.

from dishka.

lubaskinc0de avatar lubaskinc0de commented on June 19, 2024

Implementation of this functionality

Where do we need to make changes?

In the case of REQUEST scope, the finalization of generators is handled by the Container.close method, which in this case is called by the __exit__ method of the ContextWrapper class.

Accordingly, we need to change __exit__ and .close() in the synchronous and asynchronous versions of Container respectively.

What can we use to implement this functionality?

We can easily see if an exception has occurred in the context manager block, because __exit__ takes information about the exception that occurred

def __exit__(self, exc_type, exc_val, exc_tb):

Where exc_val is the instance of the exception class that occurred, and I guess that's what we need to pass to the generator function.

The finalization of the generators is handled by the .close() method of the container, it is called by __exit__() of the ContextWrapper, here is how the finalization itself happens:

    def close(self) -> None:
        errors = []
        for exit_generator in self._exits[:::-1]:
            try:
                if exit_generator.type is FactoryType.GENERATOR:
                    next(exit_generator.callable)

We could add an Optional parameter to the .close() method that defaults to None, the signature would look like this, and it wouldn't break backwards compatibility:

def close(self, exception: Optional[Exception] = None) -> None:

Next, we just check for the argument in the loop and call .send()

                if exit_generator.type is FactoryType.GENERATOR:
                    if not exception:
                        next(exit_generator.callable)
                    else:
                        exit_generator.callable.send(exception)

The same is for the asynchronous version of Container, respectively.

Conclusion

If you have no objections, I'll start to get down to implementation.

from dishka.

Related Issues (20)

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.