python python-3.x sqlalchemy flask-sqlalchemy pylint

python - Pylint no puede encontrar miembro de consulta SQLAlchemy



python-3.x flask-sqlalchemy (8)

Solución

  1. pip install pylint-flask
  2. Cargue el plugin instalado.

    Por ejemplo, si usa el código VS, edite el archivo setting.json de la siguiente manera:

    "python.linting.pylintArgs": ["--load-plugins", "pylint_flask"]

Opcional

Si tiene otras advertencias, defina los miembros restantes en los miembros generated-members en el archivo pylintrc

Tengo una aplicación Flask (v0.10.1) que usa Flask-SQLAlchemy (v2.0) y estoy tratando de configurar Pylint para verificarlo. Corriendo con Python 3.4.2.

El primer error fue:

Instance of ''SQLAlchemy'' has no ''Table'' member (no-member)

Y arreglé este, ignorando la comprobación de atributos de miembro en SQLAlchemy:

ignored-classes=SQLAlchemy

Pero tengo un problema con el miembro de consulta en las entidades:

Class ''UserToken'' has no ''query'' member (no-member)

¿Hay alguna forma de solucionar este problema sin tener que ignorar los errores de no miembros en cada llamada de consulta?

Frasco de arranque

from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() app = Flask(__name__) db.init_app(app) app.run()

Entidad UserToken:

from app import db class UserToken(db.Model): user_token_id = db.Column(db.Integer, primary_key=True, index=True) token_auth = db.Column(db.String(64), unique=True, nullable=False, index=True)

El controlador:

from entities import UserToken token = UserToken.query.filter( UserToken.token_auth == token_hash, ).first()


Aquí hay una versión de la respuesta de Joeforker que agrega dinámicamente todos los métodos públicos del objeto Session a los locales de scoped_session en el momento de la pelusa, en lugar de codificar algunos nombres de métodos conocidos.

Defina {path}/{to}/pylintplugins.py :

import sys from astroid import MANAGER, scoped_nodes from astroid.builder import AstroidBuilder from sqlalchemy.orm import Session def register(_linter): pass def transform(cls): if cls.name == ''scoped_session'': builder = AstroidBuilder(MANAGER) module_node = builder.module_build(sys.modules[Session.__module__]) session_cls_node = [ c for c in module_node.get_children() if getattr(c, "type", None) == "class" and c.name == Session.__name__ ][0] for prop in Session.public_methods: cls.locals[prop] = [ c for c in session_cls_node.get_children() if getattr(c, "type", None) == "method" and c.name == prop ] MANAGER.register_transform(scoped_nodes.Class, transform)

Y en tu archivo .pylintrc :

load-plugins={path}.{to}.pylintplugins


Así es como estoy lidiando con el problema para scoped_session . Trivial para ampliar para comprobar si hay más nombres de cls con atributos SQLAlchemy.

from astroid import MANAGER from astroid import scoped_nodes def register(_linter): pass def transform(cls): if cls.name == ''scoped_session'': for prop in [''add'', ''delete'', ''query'', ''commit'', ''rollback'']: cls.locals[prop] = [scoped_nodes.Function(prop, None)] MANAGER.register_transform(scoped_nodes.Class, transform)

Adaptado de https://docs.pylint.org/en/1.6.0/plugins.html . Luego, asegúrese de que Pylint carga su plugin

pylint -E --load-plugins warning_plugin Lib/warnings.py

(o cargarlo en pylintrc)


Cualquier clase que declare como heredera de db.Model no tendrá miembro de query hasta que el código se ejecute, por lo que Pylint no puede detectarlo.

La solución para esto, además de ignorar los errores de no miembros en cada llamada de query es agregar la query en la lista de generated-members en un archivo de configuración de Pylint, ya que es un miembro que solo se creará en tiempo de ejecución.

Cuando ejecute Pylint, buscará un archivo de configuración como se indica en su documentation :

Puede especificar un archivo de configuración en la línea de comandos usando la opción --rcfile. De lo contrario, Pylint busca un archivo de configuración en el siguiente orden y utiliza el primero que encuentra:

  1. pylintrc en el directorio de trabajo actual
  2. Si el directorio de trabajo actual está en un módulo de Python, Pylint busca la jerarquía de los módulos de Python hasta que encuentra un archivo pylintrc. Esto le permite especificar estándares de codificación módulo por módulo. Por supuesto, un directorio se considera un módulo de Python si contiene un archivo __init__.py
  3. El archivo nombrado por la variable de entorno PYLINTRC
  4. Si tienes un directorio de inicio que no es /root :
    1. .pylintrc en tu directorio home
    2. .config/pylintrc en su directorio de inicio
  5. /etc/pylintrc

Entonces, si no tiene una configuración y desea una configuración predeterminada de todo el sistema para pylint, puede usar pylint --generate-rcfile > /etc/pylintrc . Esto generará un archivo de configuración comentado de acuerdo con la configuración actual (o el valor predeterminado si no tiene uno) que puede editar según sus preferencias.

ps: generated-members en un archivo de configuración es la forma correcta de lidiar con esta advertencia, como lo dice la configuración comentada

# List of members which are set dynamically and missed by pylint inference # system, and so shouldn''t trigger E0201 when accessed. Python regular # expressions are accepted.


Después de mucha investigación, no pude hacer que Pylint entendiera a este miembro, así que solo agregué la query a la lista de generated-members y la verificación se ignora.

No es una solución perfecta pero funciona.


Después de probar muchas de estas opciones, complementos y agregar consultas y todo. La única solución que borró esos errores de scoped_session fue usar:

  1. pylint --generate-rcfile > pylintrc
  2. busque las clases ignoradas y agregue scoped_session después de la coma, no deje espacio
  3. Ejecute pylint en su módulo de nuevo.

Me encuentro con el mismo problema cuando uso flask_sqlalchemy. mi solución es:

pylint --generate-rcfile>~/.config/pylintrc

y luego encontrar el

ignored-modules

línea, reescribirla a:

ignored-modules=flask_sqlalchemy

Todos los errores E1101 se han ido.

Recuerda leer el comentario:

# List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching.


Otra alternativa es agregar scoped_session a la lista de clases ignoradas:

# List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=scoped_session