(Python) Function decorator to pass Playwright Page object to wrapped function

Viewed 389

Goal: I am trying to create a function decorator which passes a Playwright Page(playwright.sync_api._generated.Page) object to the wrapped function.

Issue: For most function calls, I would be able to return the value returned by the function call. However, since Playwright necessitates the browser.close() call, I can't simply return the Page object. I am not sure whether the problem is in (1) the function decorator which I have defined, or (2) my usage of the function decorator.

I tried to model my decorator after pytest fixtures. Using pytest, I would do something like this:

@pytest.fixture(scope="module")
def playwright_page():
    with sync_playwright() as play:
        browser = play.chromium.launch()
        page = browser.new_page()
        yield page
        browser.close()

and then

def open_google(playwright_page):
    playwright_page.goto("https://google.com")

Function Decotator:

>>> from playwright.sync_api import sync_playwright
>>> def playwright_page(func):
        def wrapper(*args, **kwargs):
            with sync_playwright() as play:
                browser = play.chromium.launch()
                page = browser.new_page()
                yield page
                browser.close()
        return wrapper

Attempt 1:

>>> @playwright_page
def open_google():
    page.goto("https://google.com")

    
>>> open_google()
<generator object playwright_page.<locals>.wrapper at 0x0000015C5F6CBC10>

Attempt 2:

>>> @playwright_page
    def open_google():
        page = next(page)
        page.goto("https://google.com")

    
>>> open_google()
<generator object playwright_page.<locals>.wrapper at 0x0000015C5FDB7F90>
1 Answers

Instead of trying to yield the Page object, such as for pytest fixtures, I should have been calling func and passing the Page object.

>>> from playwright.sync_api import sync_playwright
>>> def playwright_page(func):
        def wrapper():
            with sync_playwright() as play:
                browser = play.chromium.launch()
                page = browser.new_page()
                results = func(page)
                browser.close()
                return results
        return wrapper


>>> @playwright_page
    def open_google(page):
        page.goto("https://google.com")
Related