Home > Eclipse, PyDev, PyLint, python, sqlalchemy > Pylint: E1101 False Positive

Pylint: E1101 False Positive

22 Giugno 2011

Ho scritto un codice per capire bene come funzioni la
relazione many-to-many con l’orm di sqlalchemy (in declarative mode).

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy import ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref
from sqlalchemy.orm import relationship
from sqlalchemy.orm import sessionmaker


class Model(object):
    '''Model class with common application data'''
    base = declarative_base()
    engine = create_engine('sqlite:///test.db', echo = False)
    metadata = base.metadata
    # m2m relationship
    boms_codes = Table('boms_codes', metadata,
                               Column('codes_id', Integer,
                                      ForeignKey('codes.id')),
                               Column('boms_id', Integer,
                                      ForeignKey('boms.id')))
    def __init__(self):
        self.metadata = Model.metadata
        self.metadata.create_all(Model.engine)
        session = sessionmaker(bind = Model.engine)
        self.session = session()

class Code(Model.base):
    '''Code class for ORM Mapping'''
    __tablename__ = 'codes'
    id = Column(Integer, primary_key = True)
    code = Column(String)
    desc = Column(String)

    bom_id = Column(Integer, ForeignKey('boms.id'))
    def __init__(self, code, desc):
        self.code = code
        self.desc = desc
    def __repr__(self):
        return "<Code '%s: %s')>" % (self.code, self.desc)

class Bom(Model.base):
    '''Bill of material class for ORM Mapping'''
    __tablename__ = 'boms'
    id = Column(Integer, primary_key = True)
    code = Column(String)
    desc = Column(String)
    # m2m relationship
    code_id = relationship("Code", secondary = Model.boms_codes,
                                backref = backref('Bom'),
                                single_parent = False)
                                #cascade = 'all,delete-orphan')
    
    def __init__(self, code, desc):
        self.code = code
        self.desc = desc
    def __repr__(self):
        return "<B.O.M. '%s': %s>" % (self.code, self.desc)

def main():
    '''auto-test'''
    model = Model()
    cod_a = Code(code = '001', desc = 'code 001')
    cod_b = Code(code = '002', desc = 'code 002')
    model.session.add_all((cod_a, cod_b))
    model.session.commit()
    bom_a = Bom(code = '1001', desc = 'bom 1001')
    bom_b = Bom(code = '1002', desc = 'bom 1002')
    model.session.add_all((bom_a, bom_b))
    model.session.commit()
    bom_a.code_id.append(cod_a) # pylint: disable=E1101
    bom_a.code_id.append(cod_b)
    bom_b.code_id.append(cod_b) # pylint: disable=E1101
    model.session.commit()
    
if __name__ == '__main__':
    Model() 

Prima di postarlo, gli ho fatto fare un giro con pylint.

Sorpresa!
mi segnale 3 errori fiammanti qui:

    bom_a.code_id.append(cod_a)
    bom_a.code_id.append(cod_b)
    bom_b.code_id.append(cod_b)

googlando ho scoperto essere FALSI POSITIVI, nel senso che
il codice funziona benissimo, ma pylint, essendo uno “static checker”
vede nelle linee suddette questo tipo di errore:

ID:E1101 main: Instance of ‘RelationshipProperty’ has no ‘append’ member
ovvero non sa di avere a che fare con una lista e si “incarta”.

Per risolvere il problema ho navigato un po’:
c’è chi consiglia di disabilitare globalmente il tipo di errore E1101,
o da riga di comando o, con Eclipse, in questo modo:


Ma il metodo non mi piace, poichè mi sfuggerebbero gli altri errori “veri”.

Altra strada suggerita qui:

è quella di “esonerare” solo la linea di codice, dal controllo, commentandola
in questo modo:

    bom_a.code_id.append(cod_a) # pylint: disable=E1101
    bom_a.code_id.append(cod_b)
    bom_b.code_id.append(cod_b) # pylint: disable=E1101


come si nota, le righe che presentano il commento

# pylint: disable=Exxxx

vengono by-passate, quelle senza, segnalate correttamente.
In questo modo non è necessario bloccare a monte l’intera categoria di errori
(E1101), che, non essendo semplici Warnings, è meglio gestire con cautela.

Nel caso aggiungendo il commento, si dovesse sforare dagli 80 caratteri
per linea, aggiungere anche il bypass per il C0301

# pylint: disable=E1101,C0301
Categorie:Eclipse, PyDev, PyLint, python, sqlalchemy Tag:
I commenti sono chiusi.