PEP-484 typing stubs for SQLAlchemy 1.4 and SQLAlchemy 2.0

Overview

SQLAlchemy 2 Stubs

These are PEP-484 typing stubs for SQLAlchemy 1.4 and 2.0. They are released concurrently along with a Mypy extension which is designed to work with these stubs, which assists primarily in the area of ORM mappings.

The stubs replace the use of the "sqlalchemy-stubs" package published by Dropbox. Differences include that these stubs are generated against 1.4's API as well as some adjustments to the use of generics.

This project should be considered alpha level and is not as mature as the Dropbox stubs for the initial release.

See the Mypy plugin documentation at https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html for an overview of how to use PEP-484 annotations with ORM mapped classes.

Code of Conduct

Above all, SQLAlchemy places great emphasis on polite, thoughtful, and constructive communication between users and developers. Please see our current Code of Conduct at Code of Conduct.

License

SQLAlchemy is distributed under the MIT license.

Comments
  • 'DeclarativeMeta' is not defined

    'DeclarativeMeta' is not defined

    Describe your question When creating a Base class with @as_declarative the following errors shows up using mypy error: Name 'DeclarativeMeta' is not defined. Am I doing something wrong or is there a better way?

    Example - please use the Minimal, Complete, and Verifiable guidelines if possible Using the example as provided in the documentation, it works without a problem:

    Base = declarative_base()
    
    class User(Base):
        __tablename__ = 'user'
    
        id = Column(Integer, primary_key=True)
        name = Column(String)
    
        addresses: Mapped[List["Address"]] = relationship("Address", back_populates="user")
    
    class Address(Base):
        __tablename__ = 'address'
    
        id = Column(Integer, primary_key=True)
        user_id: int = Column(ForeignKey("user.id"))
    
        user: Mapped[User] = relationship(User, back_populates="addresses")
    
    main  mypy --config mypy.ini --strict simple-test.py
    Success: no issues found in 1 source file
    

    When trying to use it as following it shows the error:

    @as_declarative()
    class Base(object):
        id = Column(Integer, primary_key=True)
    
    
    class User(Base):
        __tablename__ = "user"
    
        name = Column(String)
    
        addresses: Mapped[List["Address"]] = relationship("Address", back_populates="user")
    
    
    class Address(Base):
        __tablename__ = "address"
    
        user_id: int = Column(ForeignKey("user.id"))
    
        user: Mapped[User] = relationship(User, back_populates="addresses")
    
    main  mypy --config mypy.ini --strict simple-test.py
    simple-test.py: error: Name 'DeclarativeMeta' is not defined
    

    mypy config

    [mypy]
    plugins = sqlalchemy.ext.mypy.plugin
    

    Versions

    • OS: MacOS 11.0
    • Python: Python 3.9.2
    • Mypy: mypy 0.812
    • SQLAlchemy: 1.4.3
    • sqlalchemy2-stub: 0.0.1a4
    • Database: n/a
    • DBAPI: n/a
    bug 
    opened by blokje 22
  • Fix formatting

    Fix formatting

    Description

    Updates code style and pre-commit checks to match sqlalchemy. A few things to note:

    • # fmt: off + # fmt: on was needed to keep black and zimports from fighting
    • I added flake8-pyi and did not include flake8-builtins, flake8-docstrings, and flake8-rst-docstrings because they are irrelevant for pyi files

    Checklist

    This pull request is:

    • [ ] A documentation / typographical error fix
      • Good to go, no issue or tests are needed
    • [x] A short code fix
      • please include the issue number, and create an issue if none exists, which must include a complete example of the issue. one line code fixes without an issue and demonstration will not be accepted.
      • Please include: Fixes: #<issue number> in the commit message
      • please include tests. one line code fixes without tests will not be accepted.
    • [ ] A new feature implementation
      • please include the issue number, and create an issue if none exists, which must include a complete example of how the feature would look.
      • Please include: Fixes: #<issue number> in the commit message
      • please include tests.

    Have a nice day!

    opened by bryanforbes 15
  • Asynchronous sessionmaker initialization type error

    Asynchronous sessionmaker initialization type error

    Describe the bug mypy fails on asynchronous sessionmaker initialization.

    Expected behavior No errors.

    To Reproduce Please try to provide a Minimal, Complete, and Verifiable example. See also Reporting Bugs on the website, and some example issues.

    Please do not use Flask-SQLAlchemy or any other third-party extensions or dependencies in test cases. The test case must illustrate the problem without using any third party SQLAlchemy extensions. Otherwise, please report the bug to those projects first.

    import os
    
    from sqlalchemy.ext.asyncio import AsyncSession
    from sqlalchemy.ext.asyncio import create_async_engine
    from sqlalchemy.orm import sessionmaker
    
    engine = create_async_engine(os.getenv("DATABASE_URL"))
    async_session = sessionmaker(engine, class_=AsyncSession)
    

    Error

    session.py:8: error: Value of type variable "_TSessionMakerType" of "sessionmaker" cannot be "AsyncSession"
    Found 1 error in 1 file (checked 1 source file)
    

    Versions.

    • OS: Linux
    • Python: 3.9.6
    • SQLAlchemy: 1.4.23
    • mypy: 0.910
    • SQLAlchemy2-stubs: v0.0.2a9

    Additional context The problem appeared on the latest release of sqlalchemy2-stubs and was not present on v0.0.2a8.

    Have a nice day!

    bug 
    opened by r4rdsn 13
  • relationship types not detected when passing related class as str

    relationship types not detected when passing related class as str

    I was just trying out the new stubs on an existing project if mine, and it looks like you did some awesome work there - I can get rid of a lot of workarounds. Thanks! Nevertheless, there's one issue I wanted to share with you.

    Describe the bug There are two ways to pass the first parameter of a relationship: by class or by str. When using the class directly everything works as expected, the type is detected when using uselist or relationsship. And I don't find any false positives afterwards.

    When I use a str to configure my relationship things get pretty messy. First, I need to type the annotations manually, I wasn't able to find any way to configure it such that auto-detection works.

    [SQLAlchemy Mypy plugin] Can't infer type from ORM mapped expression assigned to attribute 'addresses'; please specify a Python type or Mapped[<python type>] on the left hand side.
    

    Second, even when annotating it manually, I'll have to cast it every single time I use it (when it's some kind of Iterable as shown in the example below).

    error: "List?[Address?]" has no attribute "__iter__" (not iterable)
    error: "List?[Address?]" has no attribute "append"
    

    Expected behavior Type detection works for relationship independent of type of first argument.

    To Reproduce

    from __future__ import annotations
    
    from typing import List
    
    from sqlalchemy import Integer, Column, String, ForeignKey
    from sqlalchemy.orm import declarative_base, relationship
    
    Base = declarative_base()
    
    
    class User(Base):
    
        __tablename__ = "users"
    
        id = Column(Integer, primary_key=True)
        name = Column(String)
    
        addresses: List[Address] = relationship("Address", back_populates="user", uselist=True)
    
        def clone(self) -> User:
            new_user = User(name=self.name)
    
            for existing_addr in self.addresses:
                new_user.addresses.append(
                    Address(address=existing_addr.address)
                )
            return new_user
    
    
    class Address(Base):
    
        __tablename__ = "addresses"
    
        id = Column(Integer, primary_key=True)
        address = Column(String)
        
        user_id = Column(Integer, ForeignKey("users.id"))
        
        user = relationship(User, back_populates="addresses", uselist=False)
    
    

    Versions.

    • OS: WIn10
    • Python: 3.8.6
    • SQLAlchemy: 1.4.9
    • Database:
    • DBAPI:

    Have a nice day! You too ;)

    bug duplicate 
    opened by TilmanK 11
  • don't use typing with ServerDefaultType

    don't use typing with ServerDefaultType

    The server default is any expression that is passed as DDL to the database and these usually don't have SQL types explicitly stated.

    With the code as is, pylance is complaining about this:

    Column(DateTime(), server_default=func.now())
    

    and requiring I do this:

    Column(DateTime(), server_default=func.now(type_=DateTime))
    

    people don't need to do that, server_defaults SQL type always comes from the column type and doesn't normally need to be stated.

    Also, column_server_default.py was importing "functions as func", which is wrong. "func" is not a module it's a namespace object, fixed that.

    opened by zzzeek 8
  • Cannot unpack Row instance

    Cannot unpack Row instance

    Describe the bug mypy is complaining about unpacking Row object, even though it works.

    To Reproduce

    test_table = Table(
        "test_table",
        metadata,
        Column("i", UUID(as_uuid=True), nullable=False, primary_key=True),
        Column("x", UUID(as_uuid=True), index=True),
        Column("y", UUID(as_uuid=True), index=True),
    )
    query = test_table.select()
    async with engine.connect() as connection:
      result = await connection.execute(query)
    row = result.fetchone()
    if row:
      my_dict = {**row}
    

    Error

    Argument after ** must be a mapping, not "Row"
    

    Versions.

    • OS: Linux Mint 19.3 Cinnamon
    • Python: 3.7.10
    • SQLAlchemy: 1.4.15
    • Database: PostgreSQL
    • DBAPI: asyncpg
    mypy expected behavior 
    opened by mdczaplicki 8
  • Improve `orm.session`

    Improve `orm.session`

    Description

    Improve orm.session. Depends on #46. This is a large one because of _SessionProtocol and _AsyncSessionProtocol. These are needed to allow sessionmaker() to take classes that aren't required to inherit from Session or AsyncSession, but are duck-typed to be like Session or AsyncSession.

    Fixes #17.

    Checklist

    This pull request is:

    • [ ] A documentation / typographical error fix
      • Good to go, no issue or tests are needed
    • [X] A short code fix
      • please include the issue number, and create an issue if none exists, which must include a complete example of the issue. one line code fixes without an issue and demonstration will not be accepted.
      • Please include: Fixes: #<issue number> in the commit message
      • please include tests. one line code fixes without tests will not be accepted.
    • [ ] A new feature implementation
      • please include the issue number, and create an issue if none exists, which must include a complete example of how the feature would look.
      • Please include: Fixes: #<issue number> in the commit message
      • please include tests.

    Have a nice day!

    opened by bryanforbes 6
  • implement support to intercept as_declarative()

    implement support to intercept as_declarative()

    I installed the the type stubs and configured the mypy plugin as directed in the documentation

    My database is defined like this:

    @as_declarative()
    class Base:
        def __repr__(self):
            name = self.__class__.__name__
            attrs = (
                "%s=%r" % (attr, getattr(self, attr))
                for attr in self._sa_class_manager.keys()
                if not (attr[-2:] == "id" or isinstance(getattr(self, attr), list))
            )
            return name + "(%s)" % ", ".join(attrs)
    
    
    class Source(Base):
        __tablename__ = "sources"
        id = sa.Column(sa.Integer, primary_key=True)
        address = sa.Column(sa.String, index=True)
        match_id = sa.Column(sa.Integer, sa.ForeignKey("matches.id"))
    
        match = relationship("Match", back_populates="sources")
    
    
    class Match(Base):
        __tablename__ = "matches"
        id = sa.Column(sa.Integer, primary_key=True)
        original_id = sa.Column(sa.Integer, sa.ForeignKey("original.id"))
        romanized_id = sa.Column(sa.Integer, sa.ForeignKey("romanized.id"))
        count = sa.Column(sa.Integer)
    
        original = relationship("Original", back_populates="matches")
        romanized = relationship("Romanized", back_populates="matches")
        sources = relationship("Source", back_populates="match")
    
    
    sa.Index("matches_idx", Match.original_id, Match.romanized_id, unique=True)
    
    
    class Standard(Base):
        __tablename__ = "standards"
        id = sa.Column(sa.Integer, primary_key=True)
        st = sa.Column(sa.String, index=True, unique=True)
    
    
    class Original(Base):
        __tablename__ = "original"
        id = sa.Column(sa.Integer, primary_key=True)
        form = sa.Column(sa.String, index=True, unique=True)
    
        matches = relationship("Match", back_populates="original")
    
    
    class Romanized(Base):
        __tablename__ = "romanized"
        id = sa.Column(sa.Integer, primary_key=True)
        form = sa.Column(sa.String, index=True)
        standard_id = sa.Column(sa.Integer, sa.ForeignKey("standards.id"))
    
        standard = relationship(Standard)
        matches = relationship("Match", back_populates="romanized")
    
    
    sa.Index("standard_form", Romanized.form, Romanized.standard_id, unique=True)
    

    When I run mypy, I get these errors:

    $ mypy deromanize 
    deromanize/cacheutils.py:201: error: Need type annotation for 'match'
    deromanize/cacheutils.py:211: error: Need type annotation for 'original'
    deromanize/cacheutils.py:212: error: Need type annotation for 'romanized'
    deromanize/cacheutils.py:213: error: Need type annotation for 'sources'
    deromanize/cacheutils.py:230: error: Need type annotation for 'matches'
    deromanize/cacheutils.py:239: error: Need type annotation for 'standard'
    deromanize/cacheutils.py:240: error: Need type annotation for 'matches'
    Found 7 errors in 1 file (checked 6 source files)
    

    This does not match the documented error message:

    test3.py:22: error: [SQLAlchemy Mypy plugin] Can't infer scalar or
    collection for ORM mapped expression assigned to attribute 'user'
    if both 'uselist' and 'collection_class' arguments are absent from the
    relationship(); please specify a type annotation on the left hand side.
    Found 1 error in 1 file (checked 1 source file)
    

    Furthermore, when I attempt to add annotations, that doesn't work either:

    class Source(Base):
        __tablename__ = "sources"
        id = sa.Column(sa.Integer, primary_key=True)
        address = sa.Column(sa.String, index=True)
        match_id = sa.Column(sa.Integer, sa.ForeignKey("matches.id"))
    
        match: 'Match' = relationship("Match", back_populates="sources")
    
    deromanize/cacheutils.py:201: error: Incompatible types in assignment (expression has type "RelationshipProperty[<nothing>]", variable has type "Match")
    

    Am I doing something wrong or is this a bug?

    bug 
    opened by ninjaaron 6
  • on_conflict_do_update and on_conflict_do_nothing returns None it typing, but actually returns 'Insert'

    on_conflict_do_update and on_conflict_do_nothing returns None it typing, but actually returns 'Insert'

    Describe the bug Using on_conflict_do_update method with returning and PyCharm highlight return with "Cannot find reference 'returning' in 'None'"

    Expected behavior Don't see any highlight.

    To Reproduce Install packages, and try to use

    insert(self.table).on_conflict_do_update(
          index_elements=(self.table.c.id,),
          set_={
              'count': self.table.c.count + insert_query.excluded.count,
          },
      ).returning(self.table.c.id)
    

    Error

    "Cannot find reference 'returning' in 'None'"
    

    Proposition Change:

    def on_conflict_do_update(
            self,
            constraint: Optional[Any] = ...,
            index_elements: Optional[Any] = ...,
            index_where: Optional[Any] = ...,
            set_: Optional[Any] = ...,
            where: Optional[Any] = ...,
        ) -> 'Insert': ...
        def on_conflict_do_nothing(
            self,
            constraint: Optional[Any] = ...,
            index_elements: Optional[Any] = ...,
            index_where: Optional[Any] = ...,
        ) -> 'Insert': ...
    

    Versions.

    • OS: Ubuntu 20.4
    • IDE: PyCharm Professional 2022.1
    • Python: 3.8
    • SQLAlchemy: 1.4.32
    • mypy: 0.782
    • SQLAlchemy2-stubs: 0.0.2a21

    Have a nice day!

    bug missing type 
    opened by BlackLIonz 5
  • Cannot execute DDL construct

    Cannot execute DDL construct

    Describe the bug If I use a DDL construct, mypy conplains that it can't be executed. However using .execute raises a deprecation warning:

    testscript.py:9: RemovedIn20Warning: The DDLElement.execute() method is considered legacy as of the 1.x series of SQLAlchemy and will be removed in 2.0. All statement execution in SQLAlchemy 2.0 is performed by the Connection.execute() method of Connection, or in the ORM by the Session.execute() method of Session. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    

    Expected behavior Mypy doesn't complain

    To Reproduce

    from sqlalchemy.schema import CreateSequence, Sequence
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    
    engine = create_engine("sqlite:////:memory:")
    session = sessionmaker(bind=engine)()
    
    construct = CreateSequence(Sequence("foo"))
    try:
        construct.execute(bind=session)  # warning
        session.execute(construct)  # mypy
    except:
        pass
    

    Error

    testscript.py:10: error: Argument "bind" to "execute" of "DDLElement" has incompatible type "Session"; expected "Union[Engine, Connection, None]"
    

    Versions.

    • OS: Linux
    • Python: 3.7.1
    • SQLAlchemy: 1.4.27
    • mypy: 0.910
    • SQLAlchemy2-stubs: 0.0.2a19

    Have a nice day!

    opened by kasium 5
  • Improve stubs of classes that have some method copied by create_proxy_methods

    Improve stubs of classes that have some method copied by create_proxy_methods

    In most cases a type only superclass can avoid repeating the definitions in one or more classes.

    Examples: Session|ScopedSession|AsyncSession; Connection|AsyncConnection

    bug enhancement 
    opened by CaselIT 5
  •  Incomplete typing for Engine.dispose's close parameter

    Incomplete typing for Engine.dispose's close parameter

    Describe the bug SQLAlchemy release 1.4.33 added a new optional close: bool = True parameter to Engine#dispose(). This is not declared in the type definition, at https://github.com/sqlalchemy/sqlalchemy2-stubs/blob/dd0e6cf7e1c61cc1c25cd1d8d72c9f322fa73d90/sqlalchemy-stubs/engine/base.pyi#L200

    Expected behavior The current type definition should declare the close parameter.

    To Reproduce Call Engine.dispose(close) and then run mypy on it with sqlalchemy2-stubs.

    engine.dispose(close=False)
    

    Error

    error: Too many arguments for "dispose" of "Engine"
    

    Versions.

    • OS: Darwin Kernel Version 21.6.0
    • Python: 3.7.10
    • SQLAlchemy: 1.4.39
    • mypy: 0.931
    • SQLAlchemy2-stubs: 0.0.2a29
    bug help wanted 
    opened by satyanash 1
  • Invalid base class

    Invalid base class "Base" when returned by a function

    Describe the bug mypy returns [Invald ](error: Invalid base class "Base" [misc]) when Base class is returned by a function.

    To Reproduce

    pip install sqlalchemy[mypy]==1.4.44
    mypy --config-file=mypy.ini test.py
    

    mypy.ini

    [mypy]
    plugins = sqlalchemy.ext.mypy.plugin
    

    test.py

    from sqlalchemy import String, select
    from sqlalchemy.orm import declarative_base
    from typing import Optional, Dict, Type
    import sqlalchemy
    from sqlalchemy.orm.ext import DeclarativeMeta
    
    def get_base() -> Type[DeclarativeMeta]:
        return declarative_base()
    
    Base: Type[DeclarativeMeta] = get_base()
    
    class User(Base):
        __tablename__ = "user"
    
        id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        name = sqlalchemy.Column(sqlalchemy.String)
    
    

    Error

    error: Invalid base class "Base"
    

    Versions.

    • OS: Ubuntu 22.04
    • Python: 3.8
    • SQLAlchemy: 1.4.44
    • mypy: 0.991
    • SQLAlchemy2-stubs: 0.0.2a29

    Have a nice day!

    bug expected behavior 
    opened by iskyd 6
  • Type error when attempting to use a Literal[True] with sa.and_()

    Type error when attempting to use a Literal[True] with sa.and_()

    Relevant block of code:

    sa.and_(
        tb.c.VERSION == version,
        tb.c.ISIN.in_(isins) if isins is not None else True,
        tb.c.ISIN != None,  # pylint: disable=singleton-comparison
         b.c.DATE.in_(dates))
    )
    

    Error I get from pyright is:

    error: Argument of type "ColumnElement[Boolean] | Literal[True]" cannot be assigned to parameter "clauses" of type "[email protected]" in function "and_"
        Type "ColumnElement[Boolean] | Literal[True]" cannot be assigned to type "ColumnElement[Boolean]"
          "Literal[True]" is incompatible with "ColumnElement[Boolean]" (reportGeneralTypeIssues)
    
    bug 
    opened by gandhis1 1
  • Using compiles leads to untyped decorator

    Using compiles leads to untyped decorator

    Describe the bug The compile decorator is not fully typed. Therefore mypy complains when using it

    Expected behavior Mypy doesn't complain

    To Reproduce Use compile as a decorator

    Error

    error: Untyped decorator makes function "foo" untyped  [misc]
    

    Versions.

    • OS: Linux
    • Python: 3.7.1
    • SQLAlchemy: 1.4.41
    • mypy: 0.982
    • SQLAlchemy2-stubs: 0.0.2a29

    I'm happy to give a PR a try

    bug missing type 
    opened by kasium 0
  • Make Column and relationship inherit from Mapped

    Make Column and relationship inherit from Mapped

    Is your feature request related to a problem? Please describe.

    A typical typed SQLAlchemy model looks like this:

    class Model(Base):
        name: Mapped[str] = Column(Unicode(100), nullable=True)
    

    This works fine with mypy, but triggers the following error with Pylance/Pyright

    Expression of type "Column[Unicode]" cannot be assigned to declared type "Mapped[str]"
    

    Same for relationship

    Describe the solution you'd like

    Make Column and relationship inherit from Mapped

    Additional context

    I can make a PR if you're okay with this.

    Have a nice day!

    bug missing type 
    opened by mehdigmira 5
Releases(v0.0.2a31)
Owner
SQLAlchemy
The Database Toolkit and Object Relational Mapper
SQLAlchemy
Flake8 extension to provide force-check option

flake8-force Flake8 extension to provide force-check option. When this option is enabled, flake8 performs all checks even if the target file cannot be

Kenichi Maehashi 9 Oct 29, 2022
Tool to check the completeness of MANIFEST.in for Python packages

check-manifest Are you a Python developer? Have you uploaded packages to the Python Package Index? Have you accidentally uploaded broken packages with

Marius Gedminas 270 Dec 26, 2022
Performant type-checking for python.

Pyre is a performant type checker for Python compliant with PEP 484. Pyre can analyze codebases with millions of lines of code incrementally – providi

Facebook 6.2k Jan 04, 2023
Mypy stubs for the PyQt5 framework

Mypy stubs for the PyQt5 framework This repository holds the stubs of the PyQt5 framework. It uses the stub files that are produced during compilation

62 Nov 22, 2022
Flake8 plugin to validate annotations complexity

flake8-annotations-complexity An extension for flake8 to report on too complex type annotations. Complex type annotations often means bad annotations

BestDoctor 41 Dec 28, 2022
mypy plugin for loguru

loguru-mypy A fancy plugin to boost up your logging with loguru mypy compatibility logoru-mypy should be compatible with mypy=0.770. Currently there

Tomasz Trębski 13 Nov 02, 2022
Silence mypy by adding or removing code comments

mypy-silent Automatically add or remove # type: ignore commends to silence mypy. Inspired by pylint-silent Why? Imagine you want to add type check for

Wu Haotian 8 Nov 30, 2022
The mypy playground. Try mypy with your web browser.

mypy-playground The mypy playground provides Web UI to run mypy in the sandbox: Features Web UI and sandbox for running mypy eas

Yusuke Miyazaki 57 Jan 02, 2023
MonkeyType as a pytest plugin.

MonkeyType as a pytest plugin.

Marius van Niekerk 36 Nov 24, 2022
A plugin for Flake8 that checks pandas code

pandas-vet pandas-vet is a plugin for flake8 that provides opinionated linting for pandas code. It began as a project during the PyCascades 2019 sprin

Jacob Deppen 146 Dec 28, 2022
flake8 plugin which checks that typing imports are properly guarded

flake8-typing-imports flake8 plugin which checks that typing imports are properly guarded installation pip install flake8-typing-imports flake8 codes

Anthony Sottile 50 Nov 01, 2022
docstring style checker

pydocstyle - docstring style checker pydocstyle is a static analysis tool for checking compliance with Python docstring conventions. pydocstyle suppor

Python Code Quality Authority 982 Jan 03, 2023
❄️ A flake8 plugin to help you write better list/set/dict comprehensions.

flake8-comprehensions A flake8 plugin that helps you write better list/set/dict comprehensions. Requirements Python 3.6 to 3.9 supported. Installation

Adam Johnson 398 Dec 23, 2022
Tool for pinpointing circular imports in Python. Find cyclic imports in any project

Pycycle: Find and fix circular imports in python projects Pycycle is an experimental project that aims to help python developers fix their circular de

Vadim Kravcenko 311 Dec 15, 2022
:sparkles: Surface lint errors during code review

✨ Linty Fresh ✨ Keep your codebase sparkly clean with the power of LINT! Linty Fresh parses lint errors and report them back to GitHub as comments on

Lyft 183 Dec 18, 2022
A python documentation linter which checks that the docstring description matches the definition.

Darglint A functional docstring linter which checks whether a docstring's description matches the actual function/method implementation. Darglint expe

Terrence Reilly 463 Dec 31, 2022
coala provides a unified command-line interface for linting and fixing all your code, regardless of the programming languages you use.

"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." ― John F. Woods coala provides a

coala development group 3.4k Dec 29, 2022
Flake8 extension for checking quotes in python

Flake8 Extension to lint for quotes. Major update in 2.0.0 We automatically encourage avoiding escaping quotes as per PEP 8. To disable this, use --no

Zachary Heller 157 Dec 13, 2022
An enhanced version of the Python typing library.

typingplus An enhanced version of the Python typing library that always uses the latest version of typing available, regardless of which version of Py

Contains 6 Mar 26, 2021
A simple program which checks Python source files for errors

Pyflakes A simple program which checks Python source files for errors. Pyflakes analyzes programs and detects various errors. It works by parsing the

Python Code Quality Authority 1.2k Dec 30, 2022