Search code examples
pythonflask-restfulpylint

[Python][Flask] PyLint too many instance attributes, is this resource correctly written?


I am writing an application in Python using Flask, now during creation of a Resource class for an endpoint I get a Pylint 'too-many-instance-attributes' warning. Now I do not know anymore if what I am doing is even a 'correct' way of writing Resources.

I inject dependencies into the resource like this:

api.add_resource(TicketsQuery, '/tickets/query',
             '/ticket/query/<int:ticketID>',
             resource_class_kwargs={'cleaner': Cleaner(StrategyResponseTickets()),
                                    'machine_cleaner': Cleaner(StrategyResponseMachines()),
                                    'db': soap_caller,
                                    'cache': cache,
                                    'field_map': app.config['FIELD_FILTER_MAP']['TICKETS'],
                                    'endpoint_permission': TicketsQueryPermission
                                    })

Which then shows up in the Resource as a kwargs argument. I also decorate the functions inside the init since I need a variable from the class (to do the decoration itself).

class TicketsQuery(Resource):
def __init__(self, **kwargs):
    # Dependencies
    self.cleaner = kwargs['cleaner']
    self.machine_cleaner = kwargs['machine_cleaner']
    self.db = kwargs['db']
    self.cache = kwargs['cache']
    self.field_map = kwargs['field_map']
    self.endpoint_permission = kwargs['endpoint_permission']

    # Permissions of endpoint method calls, implemented using wrapper
    self.get = authorization_required(self.endpoint_permission, UserType.GENERIC_EMPLOYEE)(self.get)
    self.post = authorization_required(self.endpoint_permission, UserType.GENERIC_EMPLOYEE)(self.post)

def get(self, permission_set: TicketsPermissionSet, ticketID=-1):

Is this a correct way of writing Resources in Flask? Or is there a better structure to adhere to? Any insight or tips are appreciated!


Solution

  • Don't be discouraged by a linter warning ~ it's there to remind you to stick to a specific style. If you don't yet have a .pylintrc in the project's root folder then the linter will be using the default rules; this is simply a style warning against "too many variables in instance" ~ i.e. too many self.*'s - it is 100% a pylint thing, and nothing to do with Flask.

    You can suppress the warning on this but keep it active for any others by adding a comment # pylint: disable=too-many-instance-attributes above the class's def __init__(...):.

    If you'd like a more pylintesque way of solving it, run pylint --generate-rcfile (assuming you've pip install pylint'd and these messages aren't just coming from the IDE) in your project's root folder to generate a .pylintrc.

    From there you can add the error's code R0902 to the disable= list ~ i.e. disable=R0902, or disable=A*,B*,R0902 ~ if you're disabling multiple warnings (which accept globbing, so you could just disable ALL R* messages, but it's best to only do that if you're sure you know what warnings you're turning off). OR, you can find the line max-attributes= under [DESIGN] and set/up that number to a higher value you'd consider more reasonable.

    For reference, the resources to find this information if you'd like to explore further ~ here's a list of the warnings you can get from pylint which you can search either by the name of the error too-many-instance-attributes or by its code R0902, and here's a sample pylintrc, which you can mostly browse by the code i.e. R0902 to find the property in it that affects that warning.

    Lastly, here's another SO article on the same pylint error message, if you want more examples ~ How to deal with Pylint's "too-many-instance-attributes" message?.