Home > Back-end >  Python class with a decorator is being flagged by pylint as unused-import
Python class with a decorator is being flagged by pylint as unused-import

Time:09-27

For example, let's say I have three Python files; one file is the init.py which has routines for creating the namespaces of my Flask API and initializing the Flask app:

from flask import Flask
app = Flask(...)
... initialize the namespace etc. ...

... and another Python file with the definitions of the API Resource subclasses that exist in the enpoint.py file. It contains a few Python classes that make use of decorators from Flask-RESTX to wire up the endpoints:

@namespace.route("/path")
class EndpointApi:
    def get():
        ...

The third file is main.py which simply starts the Flask server running. Unfortunately for me though, it contains an import which is flagged by pylint.

My app is working fine, but when I run pylint, it tells me there are unused imports. If I remove the imports, then the logic in the decorator that adds the route to the Flask API does not execute, and the result is that the endpoint is no longer added to the API.

Is there some way to add a class file (like endpoints.py) without importing it? I want pylint to stop warning me about unused imports, when clearly I'm using the decorator to call some global function that adds the API Resource handlers to Flask.

Sure, I could ignore the pylint error with a comment, but is there a better way? I am truly disgusted with placing a comment on every line of an import statement which I'm sure is not an "unused-import" (I have about 30).

Obviously, I could just refactor the decorator pattern into its constituent parts, and extract the relevant code to be included inside the main.py file. The equivalent code would look like this in main.py:

from endpoint import EndpointApi
EndpointApi = namespace.route("/path")(EndpointApi)

This is exactly the same code that's run in the decorator, so pylint considers my EndpointApi to be unused even though the decorator is using it to append a "/path" route to the namespace. Removing the decorator and adding the equivalent code to main.py decreases maintainability because now the relevant parts of EndpointApi are in two different files instead of all being defined one.

Edit

No, from endpoint import * makes it worse:

main.py:3:0: W0614: Unused import(s) EndpointApi, Resource and ns from wildcard import of endpoint (unused-wildcard-import)

Minimal example

flask-restx-hello $ pylint *py; for x in *py; do echo $x; cat $x; done
************* Module main
main.py:3:0: W0611: Unused EndpointApi imported from endpoint (unused-import)

------------------------------------------------------------------
Your code has been rated at 9.29/10 (previous run: 7.86/10,  1.43)

endpoint.py
"""docstring"""
from flask_restx import Resource

from init import ns


@ns.route('/hello')
class EndpointApi(Resource):
    """docstring"""

    def get(self):
        """docstring"""

        return {'hello': 'world'}

init.py
"""docstring"""
from flask import Flask
from flask_restx import Api

app = Flask(__name__)
api = Api(app)
ns = api.namespace('sick', description='crazy', path='/root/haha')

main.py
"""docstring"""
from init import app
from endpoint import EndpointApi

if __name__ == '__main__':
    app.run(debug=True)

$ cat requirements.txt
aniso8601==9.0.1
attrs==22.1.0
click==8.0.4
dataclasses==0.8
Flask==2.0.3
flask-restx==0.5.1
importlib-metadata==4.8.3
itsdangerous==2.0.1
Jinja2==3.0.3
jsonschema==4.0.0
MarkupSafe==2.0.1
pkg-resources==0.0.0
pyrsistent==0.18.0
pytz==2022.2.1
six==1.16.0
typing-extensions==4.1.1
Werkzeug==2.0.3
zipp==3.6.0

CodePudding user response:

Pylint isn't wrong. You aren't using endpoint anywhere in main.py. The only reason you're importing endpoint is to execute the decorator. Which is fine, but there is no way for pylint to know that.

In this case, it's ok to ignore the warning.

CodePudding user response:

If you don't want to disable each of the import errors on every single link like this:

    # pylint: disable=no-name-in-module

you could use:

    # pylint: disable=import-error

Commenting this once in the file will disable pylint import errors for the entire file.

Additionally, this post on stack overflow may help: Is it possible to ignore one single specific line with Pylint?

For more info on W0611 pylint unused imports: https://pylint.pycqa.org/en/latest/user_guide/messages/warning/unused-import.html

  • Related