Pylint: E1101 False Positive
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
Commenti recenti