Search code examples
pythonpython-typingpyright

basedpyright: a decorated function inside a function/method "is not accessed"


(Not relevant to the question itself, but the example uses quart-trio package, which is similar in both interface and function to flask.)

This code has no errors:

from quart_trio import QuartTrio

app = QuartTrio(__name__)

@app.route('/')
async def index() -> str:
    return "ok"

app.run()

However, this code, which I assume would be identical, reports an issue:

from quart_trio import QuartTrio

def create_app() -> QuartTrio:
    app = QuartTrio(__name__)

    @app.route('/')
    async def index() -> str:           # error: Function "index" is not accessed (reportUnusedFunction)
        return "ok"

    return app

app = create_app()
app.run()

The same happens inside a method:

from quart_trio import QuartTrio

class Server:
    def __init__(self) -> None:
        super().__init__()
        self.app = QuartTrio(__name__)

        @self.app.route('/')
        async def index() -> str:       # error: Function "index" is not accessed (reportUnusedFunction)
            return "ok"

    def serve(self) -> None:
        self.app.run()

Server().serve()

Anyone has an explanation? Is there a better way to write it that does not trigger the checker? Or is this something that should be considered a bug in basedpyright, and reported as an issue?


Solution

  • A workaround is to assign to a _ variable:

    def create_app() -> QuartTrio:
        @app.route('/')
        async def index() -> str: ...
    
        _ = index  # index() is now "used".
    

    I have posted a corresponding enhancement request here. It was closed as "not planned", due to index being treated as a name instead of the function itself:

    def create_app() -> QuartTrio:
        async def _index() -> str: ...
    
        index = app.route('/')(_index)  # index is unused
    

    This leads to another workaround, which is to call the decorator on a separate statement:

    def create_app() -> QuartTrio:
        async def index() -> str: ...
    
        app.route('/')(index)