Giter Club home page Giter Club logo

pylint_flask_sqlalchemy's Introduction

Pylint Flask SQLAlchemy

PyPI Workflow Downloads

About

pylint_flask_sqlalchemy is a Pylint to improve static code analysis of Flask-SQLAlchemy based projects.

pylint_flask_sqlalchemy is now hosted on GitHub: https://github.com/anybox/pylint_flask_sqlalchemy

Installation

pip install pylint_flask_sqlalchemy

And tell Pylint to --load-plugins pylint_flask_sqlalchemy.

Usage

Here's a simple flask application:

"""app.py"""
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db"
db = SQLAlchemy(app)


class Group(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True, nullable=False)

    def __repr__(self):
        return f"<Group {self.name}>"


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    group = db.relationship(Group)

    def __repr__(self):
        return f"<User {self.username}>"

user = User(username="test")
db.session.add(user)
db.session.commit()

Without the plugin 😓

pylint app.py

app.py:11:9: E1101: Instance of 'SQLAlchemy' has no 'Column' member (no-member)
app.py:11:19: E1101: Instance of 'SQLAlchemy' has no 'Integer' member (no-member)
app.py:12:11: E1101: Instance of 'SQLAlchemy' has no 'Column' member (no-member)
app.py:12:21: E1101: Instance of 'SQLAlchemy' has no 'String' member (no-member)
app.py:19:9: E1101: Instance of 'SQLAlchemy' has no 'Column' member (no-member)
app.py:19:19: E1101: Instance of 'SQLAlchemy' has no 'Integer' member (no-member)
app.py:20:15: E1101: Instance of 'SQLAlchemy' has no 'Column' member (no-member)
app.py:20:25: E1101: Instance of 'SQLAlchemy' has no 'String' member (no-member)
app.py:21:12: E1101: Instance of 'SQLAlchemy' has no 'relationship' member (no-member)
app.py:28:0: E1101: Instance of 'scoped_session' has no 'add' member (no-member)
app.py:29:0: E1101: Instance of 'scoped_session' has no 'commit' member (no-member)

----------------------------------------------------------------------
Your code has been rated at -18.95/10 (previous run: 10.00/10, -28.95)

With pylint_flask_sqlalchemy 🥳

pylint --load-plugins pylint_flask_sqlalchemy app.py

----------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: -13.08/10, +23.08)

pylint_flask_sqlalchemy's People

Contributors

herrboyer avatar j0ack avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pylint_flask_sqlalchemy's Issues

Crash on flask_sqlalchemy

Using versions:

pylint-flask 0.6
pylint-flask-sqlalchemy 0.2.0
pylint-plugin-utils 0.8.2
SQLAlchemy 2.0.19

When parsing the following file:

"test pylint"

from flask_sqlalchemy import SQLAlchemy

z = SQLAlchemy()

pylint crashed with a AstroidError and with the following stacktrace:

Traceback (most recent call last):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/checkers/utils.py", line 1390, in safe_infer
    value = next(infer_gen)
            ^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/nodes/node_ng.py", line 171, in infer
    yield from self._infer(context=context, **kwargs)
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/decorators.py", line 143, in raise_if_nothing_inferred
    yield next(generator)
          ^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/decorators.py", line 112, in wrapped
    for res in _func(node, context, **kwargs):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/bases.py", line 177, in _infer_stmts
    for inf in stmt.infer(context=context):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/nodes/node_ng.py", line 184, in infer
    for i, result in enumerate(self._infer(context=context, **kwargs)):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/decorators.py", line 143, in raise_if_nothing_inferred
    yield next(generator)
          ^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/decorators.py", line 112, in wrapped
    for res in _func(node, context, **kwargs):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/bases.py", line 177, in _infer_stmts
    for inf in stmt.infer(context=context):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/nodes/node_ng.py", line 184, in infer
    for i, result in enumerate(self._infer(context=context, **kwargs)):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/decorators.py", line 143, in raise_if_nothing_inferred
    yield next(generator)
          ^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/decorators.py", line 112, in wrapped
    for res in _func(node, context, **kwargs):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/inference.py", line 334, in infer_import_from
    module = self.do_import_module()
             ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/nodes/_base_nodes.py", line 146, in do_import_module
    return mymodule.import_module(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/nodes/scoped_nodes/scoped_nodes.py", line 530, in import_module
    return AstroidManager().ast_from_module_name(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/manager.py", line 246, in ast_from_module_name
    return self.ast_from_file(found_spec.location, modname, fallback=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/manager.py", line 138, in ast_from_file
    return AstroidBuilder(self).file_build(filepath, modname)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/builder.py", line 145, in file_build
    return self._post_build(module, builder, encoding)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/builder.py", line 173, in _post_build
    module = self._manager.visit_transforms(module)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/manager.py", line 109, in visit_transforms
    return self._transform.visit(node)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/transforms.py", line 89, in visit
    return self._visit(module)
           ^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/transforms.py", line 54, in _visit
    visited = self._visit_generic(value)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/transforms.py", line 61, in _visit_generic
    return [self._visit_generic(child) for child in node]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/transforms.py", line 61, in <listcomp>
    return [self._visit_generic(child) for child in node]
            ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/transforms.py", line 67, in _visit_generic
    return self._visit(node)
           ^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/transforms.py", line 57, in _visit
    return self._transform(node)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/astroid/transforms.py", line 39, in _transform
    ret = transform_func(node)
          ^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint_flask_sqlalchemy/__init__.py", line 23, in transform
    for key in module.__all__:
               ^^^^^^^^^^^^^^
AttributeError: module 'sqlalchemy' has no attribute '__all__'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/lint/pylinter.py", line 811, in _lint_file
    check_astroid_module(module)
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/lint/pylinter.py", line 1085, in check_astroid_module
    retval = self._check_astroid_module(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/lint/pylinter.py", line 1135, in _check_astroid_module
    walker.walk(node)
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/utils/ast_walker.py", line 94, in walk
    self.walk(child)
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/utils/ast_walker.py", line 91, in walk
    callback(astroid)
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/checkers/refactoring/refactoring_checker.py", line 1528, in visit_assign
    self._append_context_managers_to_stack(node)
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/checkers/refactoring/refactoring_checker.py", line 1583, in _append_context_managers_to_stack
    inferred = utils.safe_infer(value.func)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/checkers/utils.py", line 1394, in safe_infer
    raise AstroidError from e
astroid.exceptions.AstroidError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/lint/pylinter.py", line 775, in _lint_files
    self._lint_file(fileitem, module, check_astroid_module)
  File "/opt/scodoc/venv/lib/python3.11/site-packages/pylint/lint/pylinter.py", line 813, in _lint_file
    raise astroid.AstroidError from e
astroid.exceptions.AstroidError

Method should have 'self' as first argument

This comes from SQLA's declared_attr decorator

@declared_attr
def time_updated(cls):
    return Column(DateTime(255), onupdate=func.now())

Results in:

{
	"owner": "python",
	"code": "no-self-argument",
	"severity": 8,
	"message": "Method should have \"self\" as first argument",
	"source": "pylint"
}

Instance of 'query' has no 'outerjoin' member (no-member)

It would be great if the plugin would support the outerjoin member, currently pylint fails with:

models.py:47:12: E1101: Instance of 'query' has no 'outerjoin' member (no-member)

Sample code:

db.session.query(Book, Data)
.outerjoin(
    Data,
    Data.book_id == Book.id),
)
.all()

Support of multiple model files

It works perfectly fine with only one model file.

However, when it comes to two model files, "no-member" error still comes up.

Instance of 'Column' has no 'in_' member (no-member)

It seems that operators on ORM columns are not mapped properly for sqlalchemy 1.3 …

Test case:

"""Minimal test-case to reproduce a pylint-flask-sqlalchemy issue."""
# pylint: disable=too-few-public-methods

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class User(db.Model):
    """Minimal model class."""

    id = db.Column(db.Integer(), primary_key=True)


User.query.filter(User.id.in_([1, 2, 3])).all()

Gives tihs output:

$ pylint minimal-pylint.py 
************* Module minimal-pylint
minimal-pylint.py:15:18: E1101: Instance of 'Column' has no 'in_' member (no-member)

-------------------------------------------------------------------
Your code has been rated at 0.00/10 (previous run: -4.00/10, +4.00)

Two linting errors in every python file (always line 5 and 12)

I add the "pylint_flask_sqlalchemy" plugin to my VSCODE settings.json file:

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

I then get 2 linting error on every single python file. The errors are always for line 5 and 12:

  • Unnecessary pass statement pylint(unecessary-pass) [12, 5]
  • standard import "import re" should be placed before "from astroid import MANAGER" pylint(wrongimport-order) [5, 1]

I get these errors even if I put the following code in a module:

""" module that is doing nothing """
i = 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1
i = i + 1

I am using Python 3.8.6 and the following pylint versions:
pylint==2.6.0
pylint-flask==0.6
pylint-flask-sqlalchemy==0.2.0
pylint-plugin-utils==0.6

If I remove the plugin ""pylint_flask_sqlalchemy", then my errors are gone (but I then obviously get all the sqlalchemy" related errors

Compatibility Issues Due to `astroid` API Changes

Description

pylint_flask_sqlalchemy v1.0.0 is incompatible with pylint and astroid v3.1.0, causing TypeError due to missing col_offset, parent, end_lineno, and end_col_offset in ClassDef.

Steps to Reproduce

  1. Install pylint and astroid v3.1.0.
  2. Install pylint_flask_sqlalchemy v1.0.0.
  3. Run pylint on a Flask-SQLAlchemy project.
  4. Observe TypeError.

Expected Behavior

The plugin should work without errors.

Actual Behavior

Errors due to missing parameters in ClassDef.

Possible Fix

Update ClassDef instantiation in the plugin:

node.locals[key] = [ClassDef(key, None, 0, node, end_lineno=None, end_col_offset=None)]

Additional Information

  • Dependencies: pylint==3.1.0, astroid==3.1.0, pylint_flask_sqlalchemy==1.0.0
  • PyPi is still serving v0.2.0 of pylint-flask-sqlalchemy and should be updated to point to latest version on Github, not Gitlab
  • A fork at https://github.com/chok/pylint_flask_sqlalchemy/ seems to address the TypeError issues. Consider reviewing changes there for potential inclusion or inspiration for fixes.

Suggested Labels

  • bug
  • compatibility

release a 1.0.0 version

  • make sure the changelog is up to date
  • setup a release job on github
  • hope the CI of the people who use the plugin wont break 🤞

Update source code links on PyPI.org

Currently the project links here on pypi.org pointing to the "Homepage", "Source Code"... still point to the archived gitlab project. This should be updated to the latest repository. Maybe add a link back to the gitlab project here?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.