flake8-import-order-0.19.2/ 0000775 0001750 0001750 00000000000 15026506505 015326 5 ustar jrivero jrivero flake8-import-order-0.19.2/README.rst 0000664 0001750 0001750 00000016157 15026506505 017027 0 ustar jrivero jrivero flake8-import-order
===================
|Build Status|
A `flake8 `__ and `Pylama
`__ plugin that checks the ordering of
your imports. It does not check anything else about the
imports. Merely that they are grouped and ordered correctly.
In general stdlib comes first, then 3rd party, then local packages,
and that each group is individually alphabetized, however this depends
on the style used. Flake8-Import-Order supports a number of `styles
<#styles>`_ and is extensible allowing for `custom styles
<#extending-styles>`_.
This plugin was originally developed to match the style preferences of
the `cryptography `__ project,
with this style remaining the default.
Warnings
--------
This package adds 4 new flake8 warnings
- ``I100``: Your import statements are in the wrong order.
- ``I101``: The names in your from import are in the wrong order.
- ``I201``: Missing newline between import groups.
- ``I202``: Additional newline in a group of imports.
Styles
------
The following styles are directly supported,
* ``cryptography`` - see an `example `__
* ``google`` - style described in `Google Style Guidelines `__, see an `example `__
* ``smarkets`` - style as ``google`` only with `import` statements before `from X import ...` statements, see an `example `__
* ``appnexus`` - style as ``google`` only with `import` statements for packages local to your company or organisation coming after `import` statements for third-party packages, see an `example `__
* ``edited`` - see an `example `__
* ``pycharm`` - style as ``smarkets`` only with case sensitive sorting imported names
* ``pep8`` - style that only enforces groups without enforcing the order within the groups
You can also `add your own style <#extending-styles>`_ by extending ``Style``
class.
Configuration
-------------
You will want to set the ``application-import-names`` option to a
comma separated list of names that should be considered local to your
application. These will be used to help categorise your import
statements into the correct groups. Note that relative imports are
always considered local.
You will want to set the ``application-package-names`` option to a
comma separated list of names that should be considered local to your
company or organisation, but which are obtained using some sort of
package manager like Pip, Apt, or Yum. Typically, code representing
the values listed in this option is located in a different repository
than the code being developed. This option is only accepted in the
supported ``appnexus`` or ``edited`` styles or in any style that
accepts application package names.
The ``application-import-names`` and ``application-package-names`` can
contain namespaced packages or even exact nested module names. (This
is possible with 0.16 onwards).
``import-order-style`` controls what style the plugin follows
(``cryptography`` is the default).
Limitations
-----------
Currently these checks are limited to module scope imports only.
Conditional imports in module scope will be ignored except imports
under ```if TYPE_CHECKING:``` block.
Classification of an imported module is achieved by checking the
module against a stdlib list and then if there is no match against the
``application-import-names`` list and ``application-package-names`` if
the style accepts application-package names. Only if none of these
lists contain the imported module will it be classified as third
party.
These checks only consider an import against its previous import,
rather than considering all the imports together. This means that
``I100`` errors are only raised for the latter of adjacent imports out
of order. For example,
.. code-block:: python
import X.B
import X # I100
import X.A
only ``import X`` raises an ``I100`` error, yet ``import X.A`` is also
out of order compared with the ``import X.B``.
Imported modules are classified as stdlib if the module is in a
vendored list of stdlib modules. This list is based on the latest
release of Python and hence the results can be misleading. This list
is also the same for all Python versions because otherwise it would
be impossible to write programs that work under both Python 2 and 3
*and* pass the import order check.
The ``I202`` check will consider any blank line between imports to
count, even if the line is not contextually related to the
imports. For example,
.. code-block:: python
import logging
try:
from logging import NullHandler
except ImportError:
class NullHandler(logging.Handler):
"""Shim for version of Python < 2.7."""
def emit(self, record):
pass
import sys # I202 due to the blank line before the 'def emit'
will trigger a ``I202`` error despite the blank line not being
contextually related.
Extending styles
----------------
You can add your own style by extending ``flake8_import_order.styles.Style``
class. Here's an example:
.. code-block:: python
from flake8_import_order.styles import Cryptography
class ReversedCryptography(Cryptography):
# Note that Cryptography is a subclass of Style.
@staticmethod
def sorted_names(names):
return reversed(Cryptography.sorted_names(names))
By default there are five import groupings or sections; future,
stdlib, third party, application, and relative imports. A style can
choose to accept another grouping, application-package, by setting the
``Style`` class variable ``accepts_application_package_names`` to
True, e.g.
.. code-block:: python
class PackageNameCryptography(Cryptography):
accepts_application_package_names = True
To make flake8-import-order able to discover your extended style, you need to
register it as ``flake8_import_order.styles`` using setuptools' `entry points
`__
mechanism:
.. code-block:: python
# setup.py of your style package
setup(
name='flake8-import-order-reversed-cryptography',
...,
entry_points={
'flake8_import_order.styles': [
'reversed = reversedcryptography:ReversedCryptography',
# 'reversed' is a style name. You can pass it to
# --import-order-style option
# 'reversedcryptography:ReversedCryptography' is an import path
# of your extended style class.
]
}
)
.. |Build Status| image:: https://travis-ci.org/PyCQA/flake8-import-order.svg?branch=master
:target: https://travis-ci.org/PyCQA/flake8-import-order
flake8-import-order-0.19.2/pyproject.toml 0000664 0001750 0001750 00000001052 15026506505 020240 0 ustar jrivero jrivero [tool.black]
line-length = 78
target-version = ['py37']
exclude = '''
(
/(
\.eggs # exclude a few common directories in the
| \.git # root of the project
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| build
| dist
| venv
| tests\/test_cases
)/
)
'''
force-exclude = '''
(
/(
tests\/test_cases
)/
)
'''
[tool.mypy]
files = ["."]
exclude = [
"^docs/",
"^tests/",
]
[tool.isort]
profile = "black"
line_length = 78
force_single_line = true
skip = ["tests/test_cases/*"]
flake8-import-order-0.19.2/.github/ 0000775 0001750 0001750 00000000000 15026506505 016666 5 ustar jrivero jrivero flake8-import-order-0.19.2/.github/workflows/ 0000775 0001750 0001750 00000000000 15026506505 020723 5 ustar jrivero jrivero flake8-import-order-0.19.2/.github/workflows/tox.yml 0000664 0001750 0001750 00000002634 15026506505 022265 0 ustar jrivero jrivero name: tests
on:
pull_request:
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
env:
FORCE_COLOR: "1"
TOX_TESTENV_PASSENV: "FORCE_COLOR"
MIN_PYTHON_VERSION: "3.9"
DEFAULT_PYTHON_VERSION: "3.13"
jobs:
tests:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest] # [macos-latest, ubuntu-latest, windows-latest]
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ matrix.python-version }}
- run: pip install --upgrade pip
- run: pip install tox
- run: tox -e py
lint:
strategy:
fail-fast: false
matrix:
job: [pep8, release-check]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: 3.x
- run: pip install --upgrade pip
- run: pip install tox
- run: tox -e ${{ matrix.job }}
flake8-import-order-0.19.2/.github/workflows/publish.yml 0000664 0001750 0001750 00000004672 15026506505 023125 0 ustar jrivero jrivero name: Publish to PyPI
on:
push:
tags:
- "*"
permissions:
contents: read
jobs:
build:
name: "Build dists"
runs-on: "ubuntu-latest"
environment:
name: "publish"
outputs:
hashes: ${{ steps.hash.outputs.hashes }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1
with:
egress-policy: audit
- name: "Checkout repository"
uses: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683"
- name: "Setup Python"
uses: "actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065"
with:
python-version: "3.x"
- name: "Install dependencies"
run: python -m pip install build==0.8.0
- name: "Build dists"
run: |
SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) \
python -m build
- name: "Generate hashes"
id: hash
run: |
cd dist && echo "::set-output name=hashes::$(sha256sum * | base64 -w0)"
- name: "Upload dists"
uses: "actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02"
with:
name: "dist"
path: "dist/"
if-no-files-found: error
retention-days: 5
provenance:
needs: [build]
permissions:
actions: read
contents: write
id-token: write # Needed to access the workflow's OIDC identity.
uses: "slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0"
with:
base64-subjects: "${{ needs.build.outputs.hashes }}"
upload-assets: true
compile-generator: true # Workaround for https://github.com/slsa-framework/slsa-github-generator/issues/1163
publish:
name: "Publish"
if: startsWith(github.ref, 'refs/tags/')
needs: ["build", "provenance"]
permissions:
contents: write
id-token: write
runs-on: "ubuntu-latest"
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1
with:
egress-policy: audit
- name: "Download dists"
uses: "actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093"
with:
name: "dist"
path: "dist/"
- name: "Publish dists to PyPI"
uses: "pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc"
flake8-import-order-0.19.2/.github/dependabot.yml 0000664 0001750 0001750 00000000157 15026506505 021521 0 ustar jrivero jrivero version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
flake8-import-order-0.19.2/flake8_import_order/ 0000775 0001750 0001750 00000000000 15026506505 021265 5 ustar jrivero jrivero flake8-import-order-0.19.2/flake8_import_order/__init__.py 0000664 0001750 0001750 00000012105 15026506505 023375 0 ustar jrivero jrivero import ast
import sys
from collections import namedtuple
from enum import IntEnum
if sys.version_info >= (3, 10):
STDLIB_NAMES = sys.stdlib_module_names | {"__main__", "test"}
else:
from .stdlib_list import STDLIB_NAMES
from .__about__ import __author__
from .__about__ import __copyright__
from .__about__ import __email__
from .__about__ import __license__
from .__about__ import __summary__
from .__about__ import __title__
from .__about__ import __uri__
from .__about__ import __version__
__all__ = [
"__title__",
"__summary__",
"__uri__",
"__version__",
"__author__",
"__email__",
"__license__",
"__copyright__",
]
DEFAULT_IMPORT_ORDER_STYLE = "cryptography"
ClassifiedImport = namedtuple(
"ClassifiedImport",
[
"type",
"is_from",
"modules",
"names",
"lineno",
"end_lineno",
"level",
"package",
"type_checking",
],
)
NewLine = namedtuple("NewLine", ["lineno"])
class ImportType(IntEnum):
FUTURE = 0
STDLIB = 10
THIRD_PARTY = 20
APPLICATION_PACKAGE = 30
APPLICATION = 40
APPLICATION_RELATIVE = 50
MIXED = -1
def get_package_names(name):
tree = ast.parse(name)
parts = []
for node in ast.walk(tree):
if isinstance(node, ast.Attribute):
parts.append(node.attr)
if isinstance(node, ast.Name):
parts.append(node.id)
if not parts:
return []
last_package_name = parts.pop()
package_names = [last_package_name]
for part in reversed(parts):
last_package_name = f"{last_package_name}.{part}"
package_names.append(last_package_name)
return package_names
def root_package_name(name):
tree = ast.parse(name)
for node in ast.walk(tree):
if isinstance(node, ast.Name):
return node.id
else:
return None
class ImportVisitor(ast.NodeVisitor):
def __init__(self, application_import_names, application_package_names):
self.imports = []
self.application_import_names = frozenset(application_import_names)
self.application_package_names = frozenset(application_package_names)
def generic_visit(self, node):
for child in ast.iter_child_nodes(node):
child.parent = node
return super().generic_visit(node)
def visit_Import(self, node): # noqa: N802
if node.col_offset == 0 or self._type_checking_import(node):
modules = [alias.name for alias in node.names]
types_ = {self._classify_type(module) for module in modules}
if len(types_) == 1:
type_ = types_.pop()
else:
type_ = ImportType.MIXED
classified_import = ClassifiedImport(
type_,
False,
modules,
[],
node.lineno,
node.end_lineno,
0,
root_package_name(modules[0]),
self._type_checking_import(node),
)
self.imports.append(classified_import)
def visit_ImportFrom(self, node): # noqa: N802
if node.col_offset == 0 or self._type_checking_import(node):
module = node.module or ""
if node.level > 0:
type_ = ImportType.APPLICATION_RELATIVE
else:
type_ = self._classify_type(module)
names = [alias.name for alias in node.names]
classified_import = ClassifiedImport(
type_,
True,
[module],
names,
node.lineno,
node.end_lineno,
node.level,
root_package_name(module),
self._type_checking_import(node),
)
self.imports.append(classified_import)
def _type_checking_import(self, node):
return isinstance(node.parent, ast.If) and (
(
isinstance(node.parent.test, ast.Name)
and node.parent.test.id == "TYPE_CHECKING"
)
or (
isinstance(node.parent.test, ast.Attribute)
and isinstance(node.parent.test.value, ast.Name)
and node.parent.test.value.id in {"t", "typing"}
and getattr(node.parent.test, "attr", "") == "TYPE_CHECKING"
)
)
def _classify_type(self, module):
package_names = get_package_names(module)
# Walk through package names from most-specific to least-specific,
# taking the first match found.
for package in reversed(package_names):
if package == "__future__":
return ImportType.FUTURE
elif package in self.application_import_names:
return ImportType.APPLICATION
elif package in self.application_package_names:
return ImportType.APPLICATION_PACKAGE
elif package in STDLIB_NAMES:
return ImportType.STDLIB
# Not future, stdlib or an application import.
# Must be 3rd party.
return ImportType.THIRD_PARTY
flake8-import-order-0.19.2/flake8_import_order/stdlib_list.py 0000664 0001750 0001750 00000011224 15026506505 024153 0 ustar jrivero jrivero STDLIB_NAMES = {
"AL",
"BaseHTTPServer",
"Bastion",
"Binary",
"Boolean",
"CGIHTTPServer",
"ColorPicker",
"ConfigParser",
"Cookie",
"DEVICE",
"DocXMLRPCServer",
"EasyDialogs",
"FL",
"FrameWork",
"GL",
"HTMLParser",
"MacOS",
"Mapping",
"MimeWriter",
"MiniAEFrame",
"Numeric",
"Queue",
"SUNAUDIODEV",
"ScrolledText",
"Sequence",
"Set",
"SimpleHTTPServer",
"SimpleXMLRPCServer",
"SocketServer",
"StringIO",
"Text",
"Tix",
"Tkinter",
"UserDict",
"UserList",
"UserString",
"__builtin__",
"__future__",
"__main__",
"_dummy_thread",
"_thread",
"_threading_local",
"_winapi",
"abc",
"aepack",
"aetools",
"aetypes",
"aifc",
"al",
"anydbm",
"argparse",
"array",
"ast",
"asynchat",
"asyncio",
"asyncore",
"atexit",
"audioop",
"autoGIL",
"base64",
"bdb",
"binascii",
"binhex",
"bisect",
"bsddb",
"builtins",
"bz2",
"cPickle",
"cProfile",
"cStringIO",
"calendar",
"cd",
"cgi",
"cgitb",
"chunk",
"cmath",
"cmd",
"code",
"codecs",
"codeop",
"collections",
"colorsys",
"commands",
"compileall",
"concurrent",
"configparser",
"contextlib",
"contextvars",
"cookielib",
"copy",
"copy_reg",
"copyreg",
"crypt",
"csv",
"ctypes",
"curses",
"dataclasses",
"datetime",
"dbhash",
"dbm",
"decimal",
"difflib",
"dircache",
"dis",
"distutils",
"dl",
"doctest",
"dumbdbm",
"dummy_thread",
"dummy_threading",
"email",
"encodings",
"ensurepip",
"enum",
"errno",
"faulthandler",
"fcntl",
"filecmp",
"fileinput",
"findertools",
"fl",
"flp",
"fm",
"fnmatch",
"formatter",
"fpectl",
"fpformat",
"fractions",
"ftplib",
"functools",
"future_builtins",
"gc",
"gdbm",
"gensuitemodule",
"getopt",
"getpass",
"gettext",
"gl",
"glob",
"grp",
"gzip",
"hashlib",
"heapq",
"hmac",
"hotshot",
"html",
"htmlentitydefs",
"htmllib",
"http",
"httplib",
"ic",
"imageop",
"imaplib",
"imgfile",
"imghdr",
"imp",
"importlib",
"imputil",
"inspect",
"io",
"ipaddress",
"itertools",
"jpeg",
"json",
"keyword",
"lib2to3",
"linecache",
"locale",
"logging",
"lzma",
"macostools",
"macpath",
"macurl2path",
"mailbox",
"mailcap",
"marshal",
"math",
"md5",
"mhlib",
"mimetools",
"mimetypes",
"mimify",
"mmap",
"modulefinder",
"msilib",
"multifile",
"multiprocessing",
"mutex",
"netrc",
"new",
"nis",
"nntplib",
"ntpath",
"nturl2path",
"numbers",
"operator",
"optparse",
"os",
"os2emxpath",
"ossaudiodev",
"parser",
"pathlib",
"pdb",
"pickle",
"pickletools",
"pipes",
"pkgutil",
"platform",
"plistlib",
"popen2",
"poplib",
"posix",
"posixfile",
"posixpath",
"pprint",
"profile",
"pstats",
"pty",
"pwd",
"py_compile",
"pyclbr",
"pydoc",
"pyexpat",
"queue",
"quopri",
"random",
"re",
"readline",
"repr",
"reprlib",
"resource",
"rexec",
"rfc822",
"rlcompleter",
"robotparser",
"runpy",
"sched",
"secrets",
"select",
"selectors",
"sets",
"sgmllib",
"sha",
"shelve",
"shlex",
"shutil",
"signal",
"site",
"smtpd",
"smtplib",
"sndhdr",
"socket",
"socketserver",
"spwd",
"sqlite3",
"ssl",
"stat",
"statistics",
"statvfs",
"string",
"stringprep",
"struct",
"subprocess",
"sunau",
"sunaudiodev",
"symbol",
"symtable",
"sys",
"sysconfig",
"syslog",
"tabnanny",
"tarfile",
"telnetlib",
"tempfile",
"termios",
"test",
"textwrap",
"thread",
"threading",
"time",
"timeit",
"tkinter",
"token",
"tokenize",
"trace",
"traceback",
"tracemalloc",
"ttk",
"tty",
"turtle",
"turtledemo",
"types",
"typing",
"unicodedata",
"unittest",
"urllib",
"urllib2",
"urlparse",
"user",
"uu",
"uuid",
"venv",
"warnings",
"wave",
"weakref",
"webbrowser",
"whichdb",
"winsound",
"wsgiref",
"xdrlib",
"xml",
"xmlrpc",
"xmlrpclib",
"zipapp",
"zipfile",
"zipimport",
"zlib",
"zoneinfo",
}
flake8-import-order-0.19.2/flake8_import_order/flake8_linter.py 0000664 0001750 0001750 00000006351 15026506505 024373 0 ustar jrivero jrivero import optparse
from flake8_import_order import __version__
from flake8_import_order.checker import DEFAULT_IMPORT_ORDER_STYLE
from flake8_import_order.checker import ImportOrderChecker
from flake8_import_order.styles import list_entry_points
from flake8_import_order.styles import lookup_entry_point
class Linter(ImportOrderChecker):
name = "import-order"
version = __version__
def __init__(self, tree, filename, lines=None):
super().__init__(filename, tree)
self.lines = lines
@classmethod
def add_options(cls, parser):
# List of application import names. They go last.
register_opt(
parser,
"--application-import-names",
default="",
action="store",
type=str,
help="Import names to consider as application-specific",
parse_from_config=True,
comma_separated_list=True,
)
register_opt(
parser,
"--application-package-names",
default="",
action="store",
type=str,
help=(
"Package names to consider as company-specific "
"(used only by 'appnexus' style)"
),
parse_from_config=True,
comma_separated_list=True,
)
register_opt(
parser,
"--import-order-style",
default=DEFAULT_IMPORT_ORDER_STYLE,
action="store",
type=str,
help=(
"Style to follow. Available: "
", ".join(cls.list_available_styles())
),
parse_from_config=True,
)
@staticmethod
def list_available_styles():
entry_points = list_entry_points()
return sorted(entry_point.name for entry_point in entry_points)
@classmethod
def parse_options(cls, options):
optdict = {}
names = options.application_import_names
if not isinstance(names, list):
names = options.application_import_names.split(",")
pkg_names = options.application_package_names
if not isinstance(pkg_names, list):
pkg_names = options.application_package_names.split(",")
style_entry_point = lookup_entry_point(options.import_order_style)
optdict = dict(
application_import_names=[n.strip() for n in names],
application_package_names=[p.strip() for p in pkg_names],
import_order_style=style_entry_point,
)
cls.options = optdict
def error(self, error):
return (
error.lineno,
0,
f"{error.code} {error.message}",
Linter,
)
def run(self):
yield from self.check_order()
def register_opt(parser, *args, **kwargs):
try:
# Flake8 3.x registration
parser.add_option(*args, **kwargs)
except (optparse.OptionError, TypeError):
# Flake8 2.x registration
parse_from_config = kwargs.pop("parse_from_config", False)
kwargs.pop("comma_separated_list", False)
kwargs.pop("normalize_paths", False)
parser.add_option(*args, **kwargs)
if parse_from_config:
parser.config_options.append(args[-1].lstrip("-"))
flake8-import-order-0.19.2/flake8_import_order/pylama_linter.py 0000664 0001750 0001750 00000001772 15026506505 024506 0 ustar jrivero jrivero from pylama.lint import Linter as BaseLinter
from flake8_import_order import __version__
from flake8_import_order.checker import DEFAULT_IMPORT_ORDER_STYLE
from flake8_import_order.checker import ImportOrderChecker
from flake8_import_order.styles import lookup_entry_point
class Linter(ImportOrderChecker, BaseLinter):
name = "import-order"
version = __version__
def __init__(self):
super().__init__(None, None)
def allow(self, path):
return path.endswith(".py")
def error(self, error):
return {
"lnum": error.lineno,
"col": 0,
"text": error.message,
"type": error.code,
}
def run(self, path, **meta):
self.filename = path
self.ast_tree = None
meta.setdefault("import_order_style", DEFAULT_IMPORT_ORDER_STYLE)
meta["import_order_style"] = lookup_entry_point(
meta["import_order_style"]
)
self.options = meta
yield from self.check_order()
flake8-import-order-0.19.2/flake8_import_order/__about__.py 0000664 0001750 0001750 00000001230 15026506505 023541 0 ustar jrivero jrivero __all__ = [
"__title__",
"__summary__",
"__uri__",
"__version__",
"__author__",
"__email__",
"__license__",
"__copyright__",
"__maintainer__",
"__maintainer_email__",
]
__title__ = "flake8-import-order"
__summary__ = (
"Flake8 and pylama plugin that checks the ordering of import statements."
)
__uri__ = "https://github.com/PyCQA/flake8-import-order"
__version__ = "0.19.2"
__author__ = "Alex Stapleton"
__email__ = "alexs@prol.etari.at"
__maintainer__ = "Phil Jones"
__maintainer_email__ = "philip.graham.jones+flake8-import@gmail.com"
__license__ = "LGPLv3"
__copyright__ = "Copyright 2013-2016 %s" % __author__
flake8-import-order-0.19.2/flake8_import_order/styles.py 0000664 0001750 0001750 00000023234 15026506505 023166 0 ustar jrivero jrivero import importlib.metadata
from collections import namedtuple
from flake8_import_order import ClassifiedImport
from flake8_import_order import ImportType
from flake8_import_order import NewLine
Error = namedtuple("Error", ["lineno", "code", "message"])
def list_entry_points():
entry_points = importlib.metadata.entry_points()
if not hasattr(entry_points, "select"):
return entry_points.get("flake8_import_order.styles", [])
return entry_points.select(group="flake8_import_order.styles")
def lookup_entry_point(name):
for style in list_entry_points():
if style.name == name:
return style
raise LookupError(f"Unknown style {name}")
class Style:
accepts_application_package_names = False
def __init__(self, nodes):
self.nodes = nodes
def check(self):
previous = None
previous_import = None
for current in self.nodes:
if isinstance(current, ClassifiedImport):
yield from self._check(previous_import, previous, current)
previous_import = current
previous = current
def _check(self, previous_import, previous, current_import):
yield from self._check_I666(current_import)
yield from self._check_I101(current_import)
if (
previous_import is not None
and not previous_import.type_checking
and current_import.type_checking
):
yield from self._check_I300(previous_import, current_import)
previous_import = None
if previous_import is not None:
yield from self._check_I100(previous_import, current_import)
yield from self._check_I201(
previous_import, previous, current_import
)
yield from self._check_I202(
previous_import, previous, current_import
)
def _check_I666(self, current_import): # noqa: N802
if current_import.type == ImportType.MIXED:
yield Error(
current_import.lineno,
"I666",
"Import statement mixes groups",
)
def _check_I101(self, current_import): # noqa: N802
correct_names = self.sorted_names(current_import.names)
if correct_names != current_import.names:
corrected = ", ".join(correct_names)
yield Error(
current_import.lineno,
"I101",
"Imported names are in the wrong order. "
"Should be {}".format(corrected),
)
def _check_I300(self, previous_import, current_import): # noqa: N802
if current_import.lineno - previous_import.end_lineno != 3:
yield Error(
current_import.lineno,
"I300",
"TYPE_CHECKING block should have one newline above.",
)
def _check_I100(self, previous_import, current_import): # noqa: N802
previous_key = self.import_key(previous_import)
current_key = self.import_key(current_import)
if previous_key > current_key:
message = (
"Import statements are in the wrong order. "
"'{}' should be before '{}'"
).format(
self._explain_import(current_import),
self._explain_import(previous_import),
)
same_section = self.same_section(
previous_import,
current_import,
)
if not same_section:
message = f"{message} and in a different group."
yield Error(current_import.lineno, "I100", message)
def _check_I201( # noqa: N802
self, previous_import, previous, current_import
):
same_section = self.same_section(previous_import, current_import)
has_newline = isinstance(previous, NewLine)
if not same_section and not has_newline:
yield Error(
current_import.lineno,
"I201",
"Missing newline between import groups. {}".format(
self._explain_grouping(
current_import,
previous_import,
)
),
)
def _check_I202( # noqa: N802
self, previous_import, previous, current_import
):
same_section = self.same_section(previous_import, current_import)
has_newline = isinstance(previous, NewLine)
if same_section and has_newline:
yield Error(
current_import.lineno,
"I202",
"Additional newline in a group of imports. {}".format(
self._explain_grouping(
current_import,
previous_import,
)
),
)
@staticmethod
def sorted_names(names):
return names
@staticmethod
def import_key(import_):
return (import_.type,)
@staticmethod
def same_section(previous, current):
same_type = current.type == previous.type
both_first = {previous.type, current.type} <= {
ImportType.APPLICATION,
ImportType.APPLICATION_RELATIVE,
}
return same_type or both_first
@staticmethod
def _explain_import(import_):
if import_.is_from:
return "from {}{} import {}".format(
import_.level * ".",
", ".join(import_.modules),
", ".join(import_.names),
)
else:
return "import {}".format(", ".join(import_.modules))
@staticmethod
def _explain_grouping(current_import, previous_import):
return (
"'{}' is identified as {} and " "'{}' is identified as {}."
).format(
Style._explain_import(current_import),
current_import.type.name.title().replace("_", " "),
Style._explain_import(previous_import),
previous_import.type.name.title().replace("_", " "),
)
class PEP8(Style):
pass
class Google(Style):
@staticmethod
def sorted_names(names):
return sorted(names, key=Google.name_key)
@staticmethod
def name_key(name):
return (name.lower(), name)
@staticmethod
def import_key(import_):
modules = [Google.name_key(module) for module in import_.modules]
names = [Google.name_key(name) for name in import_.names]
return (import_.type, import_.level, modules, names)
class AppNexus(Google):
accepts_application_package_names = True
class Smarkets(Style):
@staticmethod
def sorted_names(names):
return sorted(names, key=Smarkets.name_key)
@staticmethod
def name_key(name):
return (name.lower(), name)
@staticmethod
def import_key(import_):
modules = [Smarkets.name_key(module) for module in import_.modules]
names = [Smarkets.name_key(name) for name in import_.names]
return (import_.type, import_.is_from, import_.level, modules, names)
class Edited(Smarkets):
accepts_application_package_names = True
def _check_I202( # noqa: N802
self, previous_import, previous, current_import
):
same_section = self.same_section(previous_import, current_import)
has_newline = isinstance(previous, NewLine)
optional_split = (
current_import.is_from and not previous_import.is_from
)
if same_section and has_newline and not optional_split:
yield Error(
current_import.lineno,
"I202",
"Additional newline in a group of imports. {}".format(
self._explain_grouping(
current_import,
previous_import,
)
),
)
@staticmethod
def same_section(previous, current):
return current.type == previous.type
class PyCharm(Smarkets):
@staticmethod
def sorted_names(names):
return sorted(names)
@staticmethod
def import_key(import_):
return (
import_.type,
import_.is_from,
import_.level,
import_.modules,
import_.names,
)
class ISort(PyCharm):
@staticmethod
def name_key(name):
# Group by CONSTANT, Class, func.
group = 0 if name.isupper() else 2 if name.islower() else 1
return (group, name)
@staticmethod
def sorted_names(names):
return sorted(names, key=ISort.name_key)
class Cryptography(Style):
@staticmethod
def sorted_names(names):
return sorted(names)
@staticmethod
def import_key(import_):
if import_.type in {ImportType.THIRD_PARTY, ImportType.APPLICATION}:
return (
import_.type,
import_.package,
import_.is_from,
import_.level,
import_.modules,
import_.names,
)
else:
return (
import_.type,
"",
import_.is_from,
import_.level,
import_.modules,
import_.names,
)
@staticmethod
def same_section(previous, current):
app_or_third = current.type in {
ImportType.THIRD_PARTY,
ImportType.APPLICATION,
}
same_type = current.type == previous.type
both_relative = (
previous.type == current.type == ImportType.APPLICATION_RELATIVE
)
same_package = previous.package == current.package
return (not app_or_third and same_type or both_relative) or (
app_or_third and same_package
)
flake8-import-order-0.19.2/flake8_import_order/checker.py 0000664 0001750 0001750 00000006375 15026506505 023256 0 ustar jrivero jrivero import ast
import re
from itertools import chain
import pycodestyle
from flake8_import_order import ImportVisitor
from flake8_import_order import NewLine
from flake8_import_order.styles import lookup_entry_point
DEFAULT_IMPORT_ORDER_STYLE = "cryptography"
NOQA_INLINE_REGEXP = re.compile(
# We're looking for items that look like this:
# ``# noqa``
# ``# noqa: E123``
# ``# noqa: E123,W451,F921``
# ``# NoQA: E123,W451,F921``
# ``# NOQA: E123,W451,F921``
# We do not care about the ``: `` that follows ``noqa``
# We do not care about the casing of ``noqa``
# We want a comma-separated list of errors
r"# noqa(?:: (?P([A-Z][0-9]+(?:[,\s]+)?)+))?",
re.IGNORECASE,
)
COMMA_SEPARATED_LIST_RE = re.compile(r"[,\s]")
BLANK_LINE_RE = re.compile(r"\s*\n")
class ImportOrderChecker:
visitor_class = ImportVisitor
options = None
def __init__(self, filename, tree):
self.tree = tree
self.filename = filename
self.lines = None
def load_file(self):
if self.filename in ("stdin", "-", None):
self.filename = "stdin"
self.lines = pycodestyle.stdin_get_value().splitlines(True)
else:
self.lines = pycodestyle.readlines(self.filename)
if self.tree is None:
self.tree = ast.parse("".join(self.lines))
def error(self, error):
return error
def check_order(self):
if not self.tree or not self.lines:
self.load_file()
try:
style_entry_point = self.options["import_order_style"]
except KeyError:
style_entry_point = lookup_entry_point(DEFAULT_IMPORT_ORDER_STYLE)
style_cls = style_entry_point.load()
if style_cls.accepts_application_package_names:
visitor = self.visitor_class(
self.options.get("application_import_names", []),
self.options.get("application_package_names", []),
)
else:
visitor = self.visitor_class(
self.options.get("application_import_names", []),
[],
)
visitor.visit(self.tree)
newlines = [
NewLine(lineno) # Lines are ordinal, no zero line
for lineno, line in enumerate(self.lines, start=1)
if BLANK_LINE_RE.match(line)
]
# Replace the below with heapq merge, when Python2 is dropped.
combined = sorted(
chain(newlines, visitor.imports),
key=lambda element: element.lineno,
)
style = style_cls(combined)
for error in style.check():
if not self.error_is_ignored(error):
yield self.error(error)
def error_is_ignored(self, error):
noqa_match = NOQA_INLINE_REGEXP.search(self.lines[error.lineno - 1])
if noqa_match is None:
return False
codes_str = noqa_match.group("codes")
if codes_str is None:
return True
codes = parse_comma_separated_list(codes_str)
if error.code in codes:
return True
return False
def parse_comma_separated_list(value):
value = COMMA_SEPARATED_LIST_RE.split(value)
item_gen = (item.strip() for item in value)
return {item for item in item_gen if item}
flake8-import-order-0.19.2/setup.py 0000664 0001750 0001750 00000000105 15026506505 017034 0 ustar jrivero jrivero from setuptools import setup
if __name__ == "__main__":
setup()
flake8-import-order-0.19.2/tox.ini 0000664 0001750 0001750 00000001376 15026506505 016650 0 ustar jrivero jrivero [tox]
envlist = py3{9,10,11,12,13},pypy3,pep8,release-check
[testenv]
deps =
flake8
pytest
pytest-cov
commands =
pytest --cov --capture=no --strict-markers {posargs}
[testenv:pep8]
deps =
flake8
flake8-import-order
pep8-naming
commands = flake8 flake8_import_order/ tests/
[testenv:setuppy]
deps =
docutils
Pygments
commands =
python setup.py check \
--metadata \
--restructuredtext
[testenv:manifest]
deps = check-manifest
commands = check-manifest
[testenv:release-check]
deps =
build
twine
commands =
python -m build
twine check dist/*
[testenv:release]
deps =
build
twine
commands =
python -m build
twine check dist/*
twine upload {posargs:--skip-existing} dist/*
flake8-import-order-0.19.2/setup.cfg 0000664 0001750 0001750 00000003765 15026506505 017162 0 ustar jrivero jrivero [metadata]
name = flake8_import_order
version = attr: flake8_import_order.__about__.__version__
description = Flake8 and pylama plugin that checks the ordering of import statements.
long_description = file: README.rst
long_description_content_type = text/x-rst
url = https://github.com/PyCQA/flake8-import-order
author = Alex Stapleton
author_email = alexs@prol.etari.at
maintainer = Phil Jones
maintainer_email = philip.graham.jones+flake8-import@gmail.com
license = LGPLv3
classifiers =
Development Status :: 4 - Beta
Framework :: Flake8
Intended Audience :: Developers
Operating System :: OS Independent
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: Implementation :: PyPy
Topic :: Software Development :: Libraries :: Python Modules
Topic :: Software Development :: Quality Assurance
[options]
packages = find:
py_modules = flake8_import_order
install_requires =
pycodestyle
setuptools
python_requires > = 3.9
tests_require =
pytest
flake8
pycodestyle
pylama
zip_safe = False
[options.packages.find]
exclude =
tests
tests.*
[options.entry_points]
flake8.extension =
I = flake8_import_order.flake8_linter:Linter
flake8_import_order.styles =
cryptography = flake8_import_order.styles:Cryptography
google = flake8_import_order.styles:Google
isort = flake8_import_order.styles:ISort
pep8 = flake8_import_order.styles:PEP8
smarkets = flake8_import_order.styles:Smarkets
appnexus = flake8_import_order.styles:AppNexus
edited = flake8_import_order.styles:Edited
pycharm = flake8_import_order.styles:PyCharm
pylama.linter =
import_order = flake8_import_order.pylama_linter:Linter
[check-manifest]
ignore = tox.ini
[flake8]
exclude = .tox,*.egg,tests/test_cases/
select = E,W,F,N,I
ignore = W503
application-import-names = flake8_import_order,tests
max-line-length = 88
max-complexity = 10
[coverage:run]
source = flake8_import_order
[coverage:report]
show_missing = True
flake8-import-order-0.19.2/COPYING 0000664 0001750 0001750 00000016743 15026506505 016374 0 ustar jrivero jrivero GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
flake8-import-order-0.19.2/CHANGELOG.rst 0000664 0001750 0001750 00000013153 15026506505 017352 0 ustar jrivero jrivero 0.19.2 2025-06-24
-----------------
* Fix ``AttributeError`` in code for checking the order of imports in a
``TYPE_CHECKING`` block.
* Yank 0.19.0 from PyPI to avoid aforementioned users on older versions
of Python accidentally receiving 0.19.0
0.19.1 2025-06-20
-----------------
* Fix bug in code for checking the order of imports in a
``TYPE_CHECKING`` block.
* Fix ``python_requires`` missing from 0.19.0 to allow folks using
vulnerable and unmaintained versions of Python to continue running
0.18.x with pip selecting the correct version for them.
0.19.0 2025-06-12
-----------------
* Drop deprecated Python versions 3.7 and 3.8
* Drop unsupported pypy3.9
* Use ``sys.stdlib_module_names`` where available to determine whether a
module is in the standard library or not.
* Replace usage of ``pkg_resources`` from setuptools with
``importlib.metadata``.
* Move package to PyCQA PyPI organization
* Add support for checking ordering in a ``TYPE_CHECKING`` block. This
will support the following variants:
* ``if TYPE_CHECKING:`` (where there was a prior ``from typing import
TYPE_CHECKING``).
* ``if t.TYPE_CHECKING:`` (where there was a prior ``import typing as
t``).
* ``if typing.TYPE_CHECKING:``
0.18.2 2022-11-26
-----------------
* Add ``zoneinfo`` to list of standard library modules
* Fix registering of options with Flake8 >= 6.0
0.18.1 2019-03-04
-----------------
* Fix case-sensitive related I100 errors for the pycharm style
* Fix noqa regexp
0.18 2018-07-08
---------------
* Add new Python 3.7 modules to the stdlib list, and support 3.7.
0.17.1 2018-03-05
-----------------
* Rebuild of 0.17 with the latest setuptools to fix an enum34
dependency bug.
0.17 2018-02-11
---------------
* Add all Python3 modules to stdlib list (should be no more missing
modules).
* Clarify the error messages (more context).
* Allow styles to override specific checks.
* Correct the edited style to match the actual edited style guide.
* Add pycharm style, to match the pycharm auto formatter.
0.16 2017-11-26
---------------
* Change spacing determination to consider only blank newlines as a
space. This adds NewLine nodes to the checker and hence could break
custom styles (that use the nodes directly). This also drops the
asttokens dependency as it is no longer required.
* Understand the existence of namespaced packages, thereby allowing
different namespaced packages to be defined as local or third party.
0.15 2017-11-06
---------------
* Drop Python 3.3 support, as Python 3.3 is beyond it's end of lfe.
* Correct the flake8 entrypoint to report all ``I`` errors, this may
result in ``I2XX`` errors being reported that were absent
previously.
* Support in-line ``# noqa`` comments specifying only the error codes
to be ignored, e.g., ``# noqa: I101``.
* Accept only ``# noqa`` directives on the line reporting the error,
see limitations.
0.14.3 2017-11-01
-----------------
* Bug fix, allow for noqa directives to work with I202.
0.14.2 2017-10-30
-----------------
* Bug fix, ensure the plugin is invoked by flake8.
0.14.1 2017-10-27
-----------------
* Bug fix, cope with multi-line imports when considering I202.
0.14 2017-10-24
---------------
* Fixed I201 error raising for cryptography style.
* Added I202 error when there is an additional newline in a section of
imports.
* Added ``ntpath`` and ``os2emxpath`` to stdlib list.
0.13 2017-07-29
---------------
* Added ``secrets`` to stdlib list.
* Allow for any style to use application-package grouping.
0.12 2017-02-11
---------------
* Added new Edited style, this is equivalent to the Smarkets style
except that values specified in the ``application-package-names``
option must be imported after third-party import statements
* Added ability to extend a style using an entrypoint.
* Fix ambiguous I100 error, now lists correct packages.
0.11 2016-11-09
---------------
* Enforce lexicographic ordering for Google, Smarkets and AppNexus
styles. This may introduce warnings not present in previous
releases relating to case sensitivity.
* Fix I100 case sensitivity for ungrouped imports, again enforcing
lexicographic ordering.
0.10 2016-10-16
---------------
* Added new AppNexus style, this is equivalent to the google style
except that values specified in the `application-package-names`
option must be imported after third-party import statements
* Fixed ungrouped ordering bug whereby I100 wasn't triggered.
0.9.2 2016-08-05
----------------
* Fix error when checking from stdin using flake8 3.0.
0.9.1 2016-07-27
----------------
* Fix case sensitivity bug for Google and Smarkets style.
0.9 2016-07-26
--------------
* Drop pep8 requirement and replace with pycodestyle.
* Support Flake8 3.0 (alongside Flake8 2.X).
* Drop Python2.6 compatibility.
* Fixed a bug where intermixed 1st and 3rd party imports cause an
error with the PEP8 style.
* Fixed a bug whereby the I101 recommended ordering wasn't a valid
ordering in the cryptography style.
0.8
---
* Added profile, cProfile, pstats and typing to stdlib list.
* Added new PEP8 style, that enforces grouping of importes but allows
any ordering within the groups.
0.7
---
* Added new Smarkets style, this is equivalent to the google style
except that any `import X` statements must come before any `from X
import y` statements.
0.6.2
-----
* Fixed a bug where I101 messages were not suggesting the correct order in the
default style. The output message now outputs a message that matches the
selected style.
0.6.1
-----
* Fixed a bug where I101 messages were not suggesting the correct order.
* Extended test harness to be able to check error messages as well as codes.
flake8-import-order-0.19.2/MANIFEST.in 0000664 0001750 0001750 00000000223 15026506505 017061 0 ustar jrivero jrivero include .pre-commit-config.yaml
include CHANGELOG.rst
include COPYING
include README.md
recursive-include tests *
recursive-exclude tests *.py[co]
flake8-import-order-0.19.2/.gitignore 0000664 0001750 0001750 00000000103 15026506505 017310 0 ustar jrivero jrivero *.pyc
*.pyo
__pycache__
*.egg-info
*~
.coverage
.tox/
build/
dist/
flake8-import-order-0.19.2/tests/ 0000775 0001750 0001750 00000000000 15026506505 016470 5 ustar jrivero jrivero flake8-import-order-0.19.2/tests/__init__.py 0000664 0001750 0001750 00000000000 15026506505 020567 0 ustar jrivero jrivero flake8-import-order-0.19.2/tests/test_stdlib.py 0000664 0001750 0001750 00000001430 15026506505 021360 0 ustar jrivero jrivero import ast
# isort: off
import pycodestyle
import pytest
# isort: on
from flake8_import_order import STDLIB_NAMES
from flake8_import_order.checker import ImportOrderChecker
def _load_test_cases():
test_cases = []
for name in STDLIB_NAMES:
if not name.startswith("__"):
test_cases.append(name)
return test_cases
def _checker(data):
pycodestyle.stdin_get_value = lambda: data
tree = ast.parse(data)
checker = ImportOrderChecker(None, tree)
checker.options = {}
return checker
@pytest.mark.parametrize("import_name", _load_test_cases())
def test_styles(import_name):
data = f"import {import_name}\nimport zoneinfo\n"
checker = _checker(data)
codes = [error.code for error in checker.check_order()]
assert codes == []
flake8-import-order-0.19.2/tests/test_style_cases.py 0000664 0001750 0001750 00000004370 15026506505 022423 0 ustar jrivero jrivero import ast
import glob
import os
import re
import sys
import pytest
from flake8_import_order.checker import ImportOrderChecker
from flake8_import_order.styles import lookup_entry_point
ERROR_RX = re.compile("# ((I[0-9]{3} ?)+) ?.*$")
def _extract_expected_errors(data):
lines = data.splitlines()
expected_codes = []
for line in lines:
match = ERROR_RX.search(line)
if match is not None:
codes = match.group(1).split()
expected_codes.extend(codes)
return expected_codes
def _load_test_cases():
base_path = os.path.dirname(__file__)
test_cases = []
test_case_path = os.path.join(base_path, "test_cases")
wildcard_path = os.path.join(test_case_path, "*.py")
for filename in glob.glob(wildcard_path):
# The namespace.py test only works with Python3
if filename.endswith("namespace.py") and sys.version_info.major < 3:
continue
fullpath = os.path.join(test_case_path, filename)
with open(fullpath) as file_:
data = file_.read()
styles = data.splitlines()[0].lstrip("#").strip().split()
codes = _extract_expected_errors(data)
tree = ast.parse(data, fullpath)
for style_name in styles:
style_entry_point = lookup_entry_point(style_name)
test_cases.append((filename, tree, style_entry_point, codes))
return test_cases
def _checker(filename, tree, style_entry_point):
options = {
"application_import_names": [
"flake8_import_order",
"namespace.package_b",
"tests",
],
"application_package_names": ["localpackage"],
"import_order_style": style_entry_point,
}
checker = ImportOrderChecker(filename, tree)
checker.options = options
return checker
@pytest.mark.parametrize(
"filename, tree, style, expected_codes",
_load_test_cases(),
)
def test_styles(filename, tree, style, expected_codes):
checker = _checker(filename, tree, style)
codes = [
(filename, error.lineno, error.code)
for error in checker.check_order()
]
assert [i[2] for i in codes] == expected_codes, codes
def test_unknown_style():
with pytest.raises(LookupError):
lookup_entry_point("Unknown")
flake8-import-order-0.19.2/tests/test_cases/ 0000775 0001750 0001750 00000000000 15026506505 020625 5 ustar jrivero jrivero flake8-import-order-0.19.2/tests/test_cases/complete_cryptography_alt1.py 0000664 0001750 0001750 00000002555 15026506505 026552 0 ustar jrivero jrivero # cryptography
import ast
import os
import sys
from functools import *
from os import path
import X
from X import *
from X import A
from X import B, C, D
import Y
from Y import *
from Y import A
from Y import B, C, D
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
import flake8_import_order
from flake8_import_order import *
from flake8_import_order import A
from flake8_import_order import B
import tests
from tests import A
from tests import B
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if t.TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import X
from X import *
from X import A
from X import B, C, D
import Y
from Y import *
from Y import A
from Y import B, C, D
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
import flake8_import_order
from flake8_import_order import *
from flake8_import_order import A
from flake8_import_order import B
import tests
from tests import A
from tests import B
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/wrong_from_import_order.py 0000664 0001750 0001750 00000000335 15026506505 026144 0 ustar jrivero jrivero # appnexus edited google smarkets
from A import a, A # I101
from B import b, A # I101
from C import b, a # I101
if TYPE_CHECKING:
from A import a, A # I101
from B import b, A # I101
from C import b, a # I101
flake8-import-order-0.19.2/tests/test_cases/bug_212_regression.py 0000664 0001750 0001750 00000066052 15026506505 024611 0 ustar jrivero jrivero # google
# testing/plugin/pytestplugin.py
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
#
#
# This module is part of SQLAlchemy and is released under
# the MIT License: https://www.opensource.org/licenses/mit-license.php
# mypy: ignore-errors
from __future__ import annotations
import argparse
import collections
from functools import update_wrapper
import inspect
import itertools
import operator
import os
import re
import sys
from typing import TYPE_CHECKING
import uuid
import pytest
try:
# installed by bootstrap.py
if not TYPE_CHECKING:
import sqla_plugin_base as plugin_base
except ImportError:
# assume we're a package, use traditional import
from . import plugin_base
def pytest_addoption(parser):
group = parser.getgroup("sqlalchemy")
def make_option(name, **kw):
callback_ = kw.pop("callback", None)
if callback_:
class CallableAction(argparse.Action):
def __call__(
self, parser, namespace, values, option_string=None
):
callback_(option_string, values, parser)
kw["action"] = CallableAction
zeroarg_callback = kw.pop("zeroarg_callback", None)
if zeroarg_callback:
class CallableAction(argparse.Action):
def __init__(
self,
option_strings,
dest,
default=False,
required=False,
help=None, # noqa
):
super().__init__(
option_strings=option_strings,
dest=dest,
nargs=0,
const=True,
default=default,
required=required,
help=help,
)
def __call__(
self, parser, namespace, values, option_string=None
):
zeroarg_callback(option_string, values, parser)
kw["action"] = CallableAction
group.addoption(name, **kw)
plugin_base.setup_options(make_option)
def pytest_configure(config: pytest.Config):
plugin_base.read_config(config.rootpath)
if plugin_base.exclude_tags or plugin_base.include_tags:
new_expr = " and ".join(
list(plugin_base.include_tags)
+ [f"not {tag}" for tag in plugin_base.exclude_tags]
)
if config.option.markexpr:
config.option.markexpr += f" and {new_expr}"
else:
config.option.markexpr = new_expr
if config.pluginmanager.hasplugin("xdist"):
config.pluginmanager.register(XDistHooks())
if hasattr(config, "workerinput"):
plugin_base.restore_important_follower_config(config.workerinput)
plugin_base.configure_follower(config.workerinput["follower_ident"])
else:
if config.option.write_idents and os.path.exists(
config.option.write_idents
):
os.remove(config.option.write_idents)
plugin_base.pre_begin(config.option)
plugin_base.set_coverage_flag(
bool(getattr(config.option, "cov_source", False))
)
plugin_base.set_fixture_functions(PytestFixtureFunctions)
if config.option.dump_pyannotate:
global DUMP_PYANNOTATE
DUMP_PYANNOTATE = True
DUMP_PYANNOTATE = False
@pytest.fixture(autouse=True)
def collect_types_fixture():
if DUMP_PYANNOTATE:
from pyannotate_runtime import collect_types
collect_types.start()
yield
if DUMP_PYANNOTATE:
collect_types.stop()
def _log_sqlalchemy_info(session):
import sqlalchemy
from sqlalchemy import __version__
from sqlalchemy.util import has_compiled_ext
from sqlalchemy.util._has_cython import _CYEXTENSION_MSG
greet = "sqlalchemy installation"
site = "no user site" if sys.flags.no_user_site else "user site loaded"
msgs = [
f"SQLAlchemy {__version__} ({site})",
f"Path: {sqlalchemy.__file__}",
]
if has_compiled_ext():
from sqlalchemy.engine import _util_cy
msgs.append(f"compiled extension enabled, e.g. {_util_cy.__file__} ")
else:
msgs.append(f"compiled extension not enabled; {_CYEXTENSION_MSG}")
pm = session.config.pluginmanager.get_plugin("terminalreporter")
if pm:
pm.write_sep("=", greet)
for m in msgs:
pm.write_line(m)
else:
# fancy pants reporter not found, fallback to plain print
print("=" * 25, greet, "=" * 25)
for m in msgs:
print(m)
def pytest_sessionstart(session):
from sqlalchemy.testing import asyncio
_log_sqlalchemy_info(session)
asyncio._assume_async(plugin_base.post_begin)
def pytest_sessionfinish(session):
from sqlalchemy.testing import asyncio
asyncio._maybe_async_provisioning(plugin_base.final_process_cleanup)
if session.config.option.dump_pyannotate:
from pyannotate_runtime import collect_types
collect_types.dump_stats(session.config.option.dump_pyannotate)
def pytest_unconfigure(config):
from sqlalchemy.testing import asyncio
asyncio._shutdown()
def pytest_collection_finish(session):
if session.config.option.dump_pyannotate:
from pyannotate_runtime import collect_types
lib_sqlalchemy = os.path.abspath("lib/sqlalchemy")
def _filter(filename):
filename = os.path.normpath(os.path.abspath(filename))
if "lib/sqlalchemy" not in os.path.commonpath(
[filename, lib_sqlalchemy]
):
return None
if "testing" in filename:
return None
return filename
collect_types.init_types_collection(filter_filename=_filter)
class XDistHooks:
def pytest_configure_node(self, node):
from sqlalchemy.testing import provision
from sqlalchemy.testing import asyncio
# the master for each node fills workerinput dictionary
# which pytest-xdist will transfer to the subprocess
plugin_base.memoize_important_follower_config(node.workerinput)
node.workerinput["follower_ident"] = (
"test_%s" % uuid.uuid4().hex[0:12]
)
asyncio._maybe_async_provisioning(
provision.create_follower_db, node.workerinput["follower_ident"]
)
def pytest_testnodedown(self, node, error):
from sqlalchemy.testing import provision
from sqlalchemy.testing import asyncio
asyncio._maybe_async_provisioning(
provision.drop_follower_db, node.workerinput["follower_ident"]
)
def pytest_collection_modifyitems(session, config, items):
# look for all those classes that specify __backend__ and
# expand them out into per-database test cases.
# this is much easier to do within pytest_pycollect_makeitem, however
# pytest is iterating through cls.__dict__ as makeitem is
# called which causes a "dictionary changed size" error on py3k.
# I'd submit a pullreq for them to turn it into a list first, but
# it's to suit the rather odd use case here which is that we are adding
# new classes to a module on the fly.
from sqlalchemy.testing import asyncio
rebuilt_items = collections.defaultdict(
lambda: collections.defaultdict(list)
)
items[:] = [
item
for item in items
if item.getparent(pytest.Class) is not None
and not item.getparent(pytest.Class).name.startswith("_")
]
test_classes = {item.getparent(pytest.Class) for item in items}
def collect(element):
for inst_or_fn in element.collect():
if isinstance(inst_or_fn, pytest.Collector):
yield from collect(inst_or_fn)
else:
yield inst_or_fn
def setup_test_classes():
for test_class in test_classes:
# transfer legacy __backend__ and __sparse_backend__ symbols
# to be markers
if getattr(test_class.cls, "__backend__", False) or getattr(
test_class.cls, "__only_on__", False
):
add_markers = {"backend"}
elif getattr(test_class.cls, "__sparse_backend__", False):
add_markers = {"sparse_backend"}
else:
add_markers = frozenset()
existing_markers = {
mark.name for mark in test_class.iter_markers()
}
add_markers = add_markers - existing_markers
all_markers = existing_markers.union(add_markers)
for marker in add_markers:
test_class.add_marker(marker)
for sub_cls in plugin_base.generate_sub_tests(
test_class.cls, test_class.module, all_markers
):
if sub_cls is not test_class.cls:
per_cls_dict = rebuilt_items[test_class.cls]
module = test_class.getparent(pytest.Module)
new_cls = pytest.Class.from_parent(
name=sub_cls.__name__, parent=module
)
for marker in add_markers:
new_cls.add_marker(marker)
for fn in collect(new_cls):
per_cls_dict[fn.name].append(fn)
# class requirements will sometimes need to access the DB to check
# capabilities, so need to do this for async
asyncio._maybe_async_provisioning(setup_test_classes)
newitems = []
for item in items:
cls_ = item.cls
if cls_ in rebuilt_items:
newitems.extend(rebuilt_items[cls_][item.name])
else:
newitems.append(item)
# seems like the functions attached to a test class aren't sorted already?
# is that true and why's that? (when using unittest, they're sorted)
items[:] = sorted(
newitems,
key=lambda item: (
item.getparent(pytest.Module).name,
item.getparent(pytest.Class).name,
item.name,
),
)
def pytest_pycollect_makeitem(collector, name, obj):
if inspect.isclass(obj) and plugin_base.want_class(name, obj):
from sqlalchemy.testing import config
if config.any_async:
obj = _apply_maybe_async(obj)
return [
pytest.Class.from_parent(
name=parametrize_cls.__name__, parent=collector
)
for parametrize_cls in _parametrize_cls(collector.module, obj)
]
elif (
inspect.isfunction(obj)
and collector.cls is not None
and plugin_base.want_method(collector.cls, obj)
):
# None means, fall back to default logic, which includes
# method-level parametrize
return None
else:
# empty list means skip this item
return []
def _is_wrapped_coroutine_function(fn):
while hasattr(fn, "__wrapped__"):
fn = fn.__wrapped__
return inspect.iscoroutinefunction(fn)
def _apply_maybe_async(obj, recurse=True):
from sqlalchemy.testing import asyncio
for name, value in vars(obj).items():
if (
(callable(value) or isinstance(value, classmethod))
and not getattr(value, "_maybe_async_applied", False)
and (name.startswith("test_"))
and not _is_wrapped_coroutine_function(value)
):
is_classmethod = False
if isinstance(value, classmethod):
value = value.__func__
is_classmethod = True
@_pytest_fn_decorator
def make_async(fn, *args, **kwargs):
return asyncio._maybe_async(fn, *args, **kwargs)
do_async = make_async(value)
if is_classmethod:
do_async = classmethod(do_async)
do_async._maybe_async_applied = True
setattr(obj, name, do_async)
if recurse:
for cls in obj.mro()[1:]:
if cls != object:
_apply_maybe_async(cls, False)
return obj
def _parametrize_cls(module, cls):
"""implement a class-based version of pytest parametrize."""
if "_sa_parametrize" not in cls.__dict__:
return [cls]
_sa_parametrize = cls._sa_parametrize
classes = []
for full_param_set in itertools.product(
*[params for argname, params in _sa_parametrize]
):
cls_variables = {}
for argname, param in zip(
[_sa_param[0] for _sa_param in _sa_parametrize], full_param_set
):
if not argname:
raise TypeError("need argnames for class-based combinations")
argname_split = re.split(r",\s*", argname)
for arg, val in zip(argname_split, param.values):
cls_variables[arg] = val
parametrized_name = "_".join(
re.sub(r"\W", "", token)
for param in full_param_set
for token in param.id.split("-")
)
name = "%s_%s" % (cls.__name__, parametrized_name)
newcls = type.__new__(type, name, (cls,), cls_variables)
setattr(module, name, newcls)
classes.append(newcls)
return classes
_current_class = None
def pytest_runtest_setup(item):
from sqlalchemy.testing import asyncio
# pytest_runtest_setup runs *before* pytest fixtures with scope="class".
# plugin_base.start_test_class_outside_fixtures may opt to raise SkipTest
# for the whole class and has to run things that are across all current
# databases, so we run this outside of the pytest fixture system altogether
# and ensure asyncio greenlet if any engines are async
global _current_class
if isinstance(item, pytest.Function) and _current_class is None:
asyncio._maybe_async_provisioning(
plugin_base.start_test_class_outside_fixtures,
item.cls,
)
_current_class = item.getparent(pytest.Class)
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_teardown(item, nextitem):
# runs inside of pytest function fixture scope
# after test function runs
from sqlalchemy.testing import asyncio
asyncio._maybe_async(plugin_base.after_test, item)
yield
# this is now after all the fixture teardown have run, the class can be
# finalized. Since pytest v7 this finalizer can no longer be added in
# pytest_runtest_setup since the class has not yet been setup at that
# time.
# See https://github.com/pytest-dev/pytest/issues/9343
global _current_class, _current_report
if _current_class is not None and (
# last test or a new class
nextitem is None
or nextitem.getparent(pytest.Class) is not _current_class
):
_current_class = None
try:
asyncio._maybe_async_provisioning(
plugin_base.stop_test_class_outside_fixtures, item.cls
)
except Exception as e:
# in case of an exception during teardown attach the original
# error to the exception message, otherwise it will get lost
if _current_report.failed:
if not e.args:
e.args = (
"__Original test failure__:\n"
+ _current_report.longreprtext,
)
elif e.args[-1] and isinstance(e.args[-1], str):
args = list(e.args)
args[-1] += (
"\n__Original test failure__:\n"
+ _current_report.longreprtext
)
e.args = tuple(args)
else:
e.args += (
"__Original test failure__",
_current_report.longreprtext,
)
raise
finally:
_current_report = None
def pytest_runtest_call(item):
# runs inside of pytest function fixture scope
# before test function runs
from sqlalchemy.testing import asyncio
asyncio._maybe_async(
plugin_base.before_test,
item,
item.module.__name__,
item.cls,
item.name,
)
_current_report = None
def pytest_runtest_logreport(report):
global _current_report
if report.when == "call":
_current_report = report
@pytest.fixture(scope="class")
def setup_class_methods(request):
from sqlalchemy.testing import asyncio
cls = request.cls
if hasattr(cls, "setup_test_class"):
asyncio._maybe_async(cls.setup_test_class)
yield
if hasattr(cls, "teardown_test_class"):
asyncio._maybe_async(cls.teardown_test_class)
asyncio._maybe_async(plugin_base.stop_test_class, cls)
@pytest.fixture(scope="function")
def setup_test_methods(request):
from sqlalchemy.testing import asyncio
# called for each test
self = request.instance
# before this fixture runs:
# 1. function level "autouse" fixtures under py3k (examples: TablesTest
# define tables / data, MappedTest define tables / mappers / data)
# 2. was for p2k. no longer applies
# 3. run outer xdist-style setup
if hasattr(self, "setup_test"):
asyncio._maybe_async(self.setup_test)
# alembic test suite is using setUp and tearDown
# xdist methods; support these in the test suite
# for the near term
if hasattr(self, "setUp"):
asyncio._maybe_async(self.setUp)
# inside the yield:
# 4. function level fixtures defined on test functions themselves,
# e.g. "connection", "metadata" run next
# 5. pytest hook pytest_runtest_call then runs
# 6. test itself runs
yield
# yield finishes:
# 7. function level fixtures defined on test functions
# themselves, e.g. "connection" rolls back the transaction, "metadata"
# emits drop all
# 8. pytest hook pytest_runtest_teardown hook runs, this is associated
# with fixtures close all sessions, provisioning.stop_test_class(),
# engines.testing_reaper -> ensure all connection pool connections
# are returned, engines created by testing_engine that aren't the
# config engine are disposed
asyncio._maybe_async(plugin_base.after_test_fixtures, self)
# 10. run xdist-style teardown
if hasattr(self, "tearDown"):
asyncio._maybe_async(self.tearDown)
if hasattr(self, "teardown_test"):
asyncio._maybe_async(self.teardown_test)
# 11. was for p2k. no longer applies
# 12. function level "autouse" fixtures under py3k (examples: TablesTest /
# MappedTest delete table data, possibly drop tables and clear mappers
# depending on the flags defined by the test class)
def _pytest_fn_decorator(target):
"""Port of langhelpers.decorator with pytest-specific tricks."""
from sqlalchemy.util.langhelpers import format_argspec_plus
from sqlalchemy.util.compat import inspect_getfullargspec
def _exec_code_in_env(code, env, fn_name):
# note this is affected by "from __future__ import annotations" at
# the top; exec'ed code will use non-evaluated annotations
# which allows us to be more flexible with code rendering
# in format_argpsec_plus()
exec(code, env)
return env[fn_name]
def decorate(fn, add_positional_parameters=()):
spec = inspect_getfullargspec(fn)
if add_positional_parameters:
spec.args.extend(add_positional_parameters)
metadata = dict(
__target_fn="__target_fn", __orig_fn="__orig_fn", name=fn.__name__
)
metadata.update(format_argspec_plus(spec, grouped=False))
code = (
"""\
def %(name)s%(grouped_args)s:
return %(__target_fn)s(%(__orig_fn)s, %(apply_kw)s)
"""
% metadata
)
decorated = _exec_code_in_env(
code, {"__target_fn": target, "__orig_fn": fn}, fn.__name__
)
if not add_positional_parameters:
decorated.__defaults__ = getattr(fn, "__func__", fn).__defaults__
decorated.__wrapped__ = fn
return update_wrapper(decorated, fn)
else:
# this is the pytest hacky part. don't do a full update wrapper
# because pytest is really being sneaky about finding the args
# for the wrapped function
decorated.__module__ = fn.__module__
decorated.__name__ = fn.__name__
if hasattr(fn, "pytestmark"):
decorated.pytestmark = fn.pytestmark
return decorated
return decorate
class PytestFixtureFunctions(plugin_base.FixtureFunctions):
def skip_test_exception(self, *arg, **kw):
return pytest.skip.Exception(*arg, **kw)
@property
def add_to_marker(self):
return pytest.mark
def mark_base_test_class(self):
return pytest.mark.usefixtures(
"setup_class_methods", "setup_test_methods"
)
_combination_id_fns = {
"i": lambda obj: obj,
"r": repr,
"s": str,
"n": lambda obj: (
obj.__name__ if hasattr(obj, "__name__") else type(obj).__name__
),
}
def combinations(self, *arg_sets, **kw):
"""Facade for pytest.mark.parametrize.
Automatically derives argument names from the callable which in our
case is always a method on a class with positional arguments.
ids for parameter sets are derived using an optional template.
"""
from sqlalchemy.testing import exclusions
if len(arg_sets) == 1 and hasattr(arg_sets[0], "__next__"):
arg_sets = list(arg_sets[0])
argnames = kw.pop("argnames", None)
def _filter_exclusions(args):
result = []
gathered_exclusions = []
for a in args:
if isinstance(a, exclusions.compound):
gathered_exclusions.append(a)
else:
result.append(a)
return result, gathered_exclusions
id_ = kw.pop("id_", None)
tobuild_pytest_params = []
has_exclusions = False
if id_:
_combination_id_fns = self._combination_id_fns
# because itemgetter is not consistent for one argument vs.
# multiple, make it multiple in all cases and use a slice
# to omit the first argument
_arg_getter = operator.itemgetter(
0,
*[
idx
for idx, char in enumerate(id_)
if char in ("n", "r", "s", "a")
],
)
fns = [
(operator.itemgetter(idx), _combination_id_fns[char])
for idx, char in enumerate(id_)
if char in _combination_id_fns
]
for arg in arg_sets:
if not isinstance(arg, tuple):
arg = (arg,)
fn_params, param_exclusions = _filter_exclusions(arg)
parameters = _arg_getter(fn_params)[1:]
if param_exclusions:
has_exclusions = True
tobuild_pytest_params.append(
(
parameters,
param_exclusions,
"-".join(
comb_fn(getter(arg)) for getter, comb_fn in fns
),
)
)
else:
for arg in arg_sets:
if not isinstance(arg, tuple):
arg = (arg,)
fn_params, param_exclusions = _filter_exclusions(arg)
if param_exclusions:
has_exclusions = True
tobuild_pytest_params.append(
(fn_params, param_exclusions, None)
)
pytest_params = []
for parameters, param_exclusions, id_ in tobuild_pytest_params:
if has_exclusions:
parameters += (param_exclusions,)
param = pytest.param(*parameters, id=id_)
pytest_params.append(param)
def decorate(fn):
if inspect.isclass(fn):
if has_exclusions:
raise NotImplementedError(
"exclusions not supported for class level combinations"
)
if "_sa_parametrize" not in fn.__dict__:
fn._sa_parametrize = []
fn._sa_parametrize.append((argnames, pytest_params))
return fn
else:
_fn_argnames = inspect.getfullargspec(fn).args[1:]
if argnames is None:
_argnames = _fn_argnames
else:
_argnames = re.split(r", *", argnames)
if has_exclusions:
existing_exl = sum(
1 for n in _fn_argnames if n.startswith("_exclusions")
)
current_exclusion_name = f"_exclusions_{existing_exl}"
_argnames += [current_exclusion_name]
@_pytest_fn_decorator
def check_exclusions(fn, *args, **kw):
_exclusions = args[-1]
if _exclusions:
exlu = exclusions.compound().add(*_exclusions)
fn = exlu(fn)
return fn(*args[:-1], **kw)
fn = check_exclusions(
fn,
add_positional_parameters=(current_exclusion_name,),
)
return pytest.mark.parametrize(_argnames, pytest_params)(fn)
return decorate
def param_ident(self, *parameters):
ident = parameters[0]
return pytest.param(*parameters[1:], id=ident)
def fixture(self, *arg, **kw):
from sqlalchemy.testing import config
from sqlalchemy.testing import asyncio
# wrapping pytest.fixture function. determine if
# decorator was called as @fixture or @fixture().
if len(arg) > 0 and callable(arg[0]):
# was called as @fixture(), we have the function to wrap.
fn = arg[0]
arg = arg[1:]
else:
# was called as @fixture, don't have the function yet.
fn = None
# create a pytest.fixture marker. because the fn is not being
# passed, this is always a pytest.FixtureFunctionMarker()
# object (or whatever pytest is calling it when you read this)
# that is waiting for a function.
fixture = pytest.fixture(*arg, **kw)
# now apply wrappers to the function, including fixture itself
def wrap(fn):
if config.any_async:
fn = asyncio._maybe_async_wrapper(fn)
# other wrappers may be added here
# now apply FixtureFunctionMarker
fn = fixture(fn)
return fn
if fn:
return wrap(fn)
else:
return wrap
def get_current_test_name(self):
return os.environ.get("PYTEST_CURRENT_TEST")
def async_test(self, fn):
from sqlalchemy.testing import asyncio
@_pytest_fn_decorator
def decorate(fn, *args, **kwargs):
asyncio._run_coroutine_function(fn, *args, **kwargs)
return decorate(fn)
flake8-import-order-0.19.2/tests/test_cases/missing_newline.py 0000664 0001750 0001750 00000000474 15026506505 024376 0 ustar jrivero jrivero # smarkets
import ast
# This comment should not prevent the I201 below, it is not a newline.
import X # I201
import flake8_import_order # I201
if TYPE_CHECKING:
import ast # I300
# This comment should not prevent the I201 below, it is not a newline.
import X # I201
import flake8_import_order # I201
flake8-import-order-0.19.2/tests/test_cases/wrong_relative_order.py 0000664 0001750 0001750 00000000232 15026506505 025416 0 ustar jrivero jrivero # appnexus cryptography edited google smarkets
from .. import A
from . import B # I100
if TYPE_CHECKING:
from .. import A
from . import B # I100
flake8-import-order-0.19.2/tests/test_cases/namespace.py 0000664 0001750 0001750 00000000413 15026506505 023131 0 ustar jrivero jrivero # appnexus edited google smarkets
import namespace
import namespace.package_a
import flake8_import_order
import namespace.package_b
if TYPE_CHECKING:
import namespace
import namespace.package_a
import flake8_import_order
import namespace.package_b
flake8-import-order-0.19.2/tests/test_cases/complete_cryptography_alt0.py 0000664 0001750 0001750 00000002562 15026506505 026547 0 ustar jrivero jrivero # cryptography
import ast
import os
import sys
from functools import *
from os import path
import X
from X import *
from X import A
from X import B, C, D
import Y
from Y import *
from Y import A
from Y import B, C, D
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
import flake8_import_order
from flake8_import_order import *
from flake8_import_order import A
from flake8_import_order import B
import tests
from tests import A
from tests import B
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if typing.TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import X
from X import *
from X import A
from X import B, C, D
import Y
from Y import *
from Y import A
from Y import B, C, D
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
import flake8_import_order
from flake8_import_order import *
from flake8_import_order import A
from flake8_import_order import B
import tests
from tests import A
from tests import B
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/complete_appnexus_alt0.py 0000664 0001750 0001750 00000002236 15026506505 025655 0 ustar jrivero jrivero # appnexus
import ast
from functools import *
import os
from os import path
import sys
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if typing.TYPE_CHECKING:
import ast
from functools import *
import os
from os import path
import sys
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/wrong_import_order_cryptography.py 0000664 0001750 0001750 00000000166 15026506505 027736 0 ustar jrivero jrivero # cryptography
import A
import a
import B # I100
if TYPE_CHECKING:
import A
import a
import B # I100
flake8-import-order-0.19.2/tests/test_cases/missing_newline_cryptography.py 0000664 0001750 0001750 00000000210 15026506505 027175 0 ustar jrivero jrivero # cryptography
import flake8_import_order
import tests # I201
if TYPE_CHECKING:
import flake8_import_order
import tests # I201
flake8-import-order-0.19.2/tests/test_cases/additional_newline_edited.py 0000664 0001750 0001750 00000001316 15026506505 026347 0 ustar jrivero jrivero # edited
import ast
# This comment should not trigger a I202 (not a newline)
import os
import signal # I202
import X
from X import B, b, \
C, d
from Y import A # I202
from Y import (
B, b,
C, d,
)
from Z import A
import flake8_import_order
import tests # I202
from . import A
from . import B # I202
if TYPE_CHECKING:
import ast
# This comment should not trigger a I202 (not a newline)
import os
import signal # I202
import X
from X import B, b, \
C, d
from Y import A # I202
from Y import (
B, b,
C, d,
)
from Z import A
import flake8_import_order
import tests # I202
from . import A
from . import B # I202
flake8-import-order-0.19.2/tests/test_cases/additional_newline_cryptography.py 0000664 0001750 0001750 00000000524 15026506505 027644 0 ustar jrivero jrivero # cryptography
import ast
import signal # I202
import X
import Y
import flake8_import_order
import tests
from . import A
from . import B # I202
if TYPE_CHECKING:
import ast
import signal # I202
import X
import Y
import flake8_import_order
import tests
from . import A
from . import B # I202
flake8-import-order-0.19.2/tests/test_cases/additional_newline.py 0000664 0001750 0001750 00000001447 15026506505 025036 0 ustar jrivero jrivero # appnexus google pep8 smarkets
import ast
# This comment should not trigger a I202 (not a newline)
import os
import signal # I202
import X
from X import B, b, \
C, d
from Y import A # I202
from Y import (
B, b,
C, d,
)
from Z import A
import flake8_import_order
import tests # I202
from . import A
from . import B # I202
from .Z import (
A,
B,
C,
D,
E,
F,
G,
)
if TYPE_CHECKING:
import ast
# This comment should not trigger a I202 (not a newline)
import os
import signal # I202
import X
from X import B, b, \
C, d
from Y import A # I202
from Y import (
B, b,
C, d,
)
from Z import A
import flake8_import_order
import tests # I202
from . import A
from . import B # I202
flake8-import-order-0.19.2/tests/test_cases/wrong_section.py 0000664 0001750 0001750 00000000342 15026506505 024056 0 ustar jrivero jrivero # cryptography edited google pep8 smarkets
import ast
import flake8_import_order # I100
import A
import os # I100
if TYPE_CHECKING:
import ast
import flake8_import_order # I100
import A
import os # I100
flake8-import-order-0.19.2/tests/test_cases/wrong_section_appnexus.py 0000664 0001750 0001750 00000000371 15026506505 026003 0 ustar jrivero jrivero # appnexus edited
import ast
import flake8_import_order # I201 I100
import localpackage # I201 I100
import X # I201
if TYPE_CHECKING:
import ast
import flake8_import_order # I201 I100
import localpackage # I201 I100
import X # I201
flake8-import-order-0.19.2/tests/test_cases/complete_cryptography.py 0000664 0001750 0001750 00000002553 15026506505 025627 0 ustar jrivero jrivero # cryptography
import ast
import os
import sys
from functools import *
from os import path
import X
from X import *
from X import A
from X import B, C, D
import Y
from Y import *
from Y import A
from Y import B, C, D
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
import flake8_import_order
from flake8_import_order import *
from flake8_import_order import A
from flake8_import_order import B
import tests
from tests import A
from tests import B
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import X
from X import *
from X import A
from X import B, C, D
import Y
from Y import *
from Y import A
from Y import B, C, D
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
import flake8_import_order
from flake8_import_order import *
from flake8_import_order import A
from flake8_import_order import B
import tests
from tests import A
from tests import B
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/complete_edited_alt0.py 0000664 0001750 0001750 00000002307 15026506505 025247 0 ustar jrivero jrivero # edited
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if t.TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/complete_pep8.py 0000664 0001750 0001750 00000002126 15026506505 023744 0 ustar jrivero jrivero # pep8
import sys
from os import path
import os
from functools import *
import ast
import localpackage
import X
from X import A, d
from X import *
import Z
from Z import A
from Z.A.B import A
from Z.A import A
import Y
from Y import *
from Y import B
from Y import A, C, D
import flake8_import_order
from flake8_import_order import *
from . import B
from . import A
from .B import B
from .A import A
from .. import B
from .. import A
from ..B import B
from ..A import A
if TYPE_CHECKING:
import sys
from os import path
import os
from functools import *
import ast
import localpackage
import X
from X import A, d
from X import *
import Z
from Z import A
from Z.A.B import A
from Z.A import A
import Y
from Y import *
from Y import B
from Y import A, C, D
import flake8_import_order
from flake8_import_order import *
from . import B
from . import A
from .B import B
from .A import A
from .. import B
from .. import A
from ..B import B
from ..A import A
if not TYPE_CHECKING:
from ..c import c
flake8-import-order-0.19.2/tests/test_cases/complete_pycharm.py 0000664 0001750 0001750 00000002200 15026506505 024524 0 ustar jrivero jrivero # pycharm
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
import localpackage
from X import *
from X import A
from X import B, C, b, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
import localpackage
from X import *
from X import A
from X import B, C, b, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/complete_smarkets.py 0000664 0001750 0001750 00000002201 15026506505 024713 0 ustar jrivero jrivero # smarkets
import ast
import os
import sys
from functools import *
from os import path
import localpackage
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import localpackage
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/complete_edited.py 0000664 0001750 0001750 00000002305 15026506505 024325 0 ustar jrivero jrivero # edited
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/wrong_from_import_same.py 0000664 0001750 0001750 00000000214 15026506505 025752 0 ustar jrivero jrivero # cryptography
from os import system
from os import path # I100
if TYPE_CHECKING:
from os import system
from os import path # I100
flake8-import-order-0.19.2/tests/test_cases/complete_google.py 0000664 0001750 0001750 00000002313 15026506505 024342 0 ustar jrivero jrivero # google
import ast
from functools import *
import os
from os import path
import sys
import localpackage
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
from ..Z import (
A,
B,
C,
D,
E,
F,
G,
H,
)
if TYPE_CHECKING:
import ast
from functools import *
import os
from os import path
import sys
import localpackage
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/mixed_groups.py 0000664 0001750 0001750 00000000235 15026506505 023704 0 ustar jrivero jrivero # appnexus cryptography edited google pep8 smarkets
import ast, X, flake_import_order # I666
if TYPE_CHECKING:
import ast, X, flake_import_order # I666
flake8-import-order-0.19.2/tests/test_cases/complete_appnexus_alt1.py 0000664 0001750 0001750 00000002231 15026506505 025651 0 ustar jrivero jrivero # appnexus
import ast
from functools import *
import os
from os import path
import sys
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if t.TYPE_CHECKING:
import ast
from functools import *
import os
from os import path
import sys
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/complete_edited_alt1.py 0000664 0001750 0001750 00000002307 15026506505 025250 0 ustar jrivero jrivero # edited
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if t.TYPE_CHECKING:
import ast
import os
import sys
from functools import *
from os import path
import X
import Y
import Z
from X import *
from X import A
from X import B, b, C, d
from Y import *
from Y import A
from Y import B, C, D
from Y import e
from Z import A
from Z.A import A
from Z.A.B import A
import localpackage
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/complete_appnexus.py 0000664 0001750 0001750 00000002227 15026506505 024735 0 ustar jrivero jrivero # appnexus
import ast
from functools import *
import os
from os import path
import sys
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
if TYPE_CHECKING:
import ast
from functools import *
import os
from os import path
import sys
import X
from X import *
from X import A
from X import B, b, C, d
import Y
from Y import *
from Y import A
from Y import B, C, D
from Y import e
import Z
from Z import A
from Z.A import A
from Z.A.B import A
from localpackage import A, b
import flake8_import_order
from flake8_import_order import *
from . import A
from . import B
from .A import A
from .B import B
from .. import A
from .. import B
from ..A import A
from ..B import B
flake8-import-order-0.19.2/tests/test_cases/stdlib_shadowing.py 0000664 0001750 0001750 00000000334 15026506505 024523 0 ustar jrivero jrivero # appnexus cryptography google pep8 smarkets
from .filesystem import FilesystemStorage
from os import path # I100 I201
if TYPE_CHECKING:
from .filesystem import FilesystemStorage
from os import path # I100 I201
flake8-import-order-0.19.2/tests/test_cases/wrong_from_import_order_cryptography.py 0000664 0001750 0001750 00000000324 15026506505 030755 0 ustar jrivero jrivero # cryptography
from A import a, A # I101
from B import A, a, B # I101
from C import b, a # I101
if TYPE_CHECKING:
from A import a, A # I101
from B import A, a, B # I101
from C import b, a # I101
flake8-import-order-0.19.2/tests/test_cases/noqa.py 0000664 0001750 0001750 00000000543 15026506505 022137 0 ustar jrivero jrivero # appnexus cryptography edited google pep8 smarkets
import ast
import sys # noqa: I202
import os # noqa
import unittest
import X # noqa
from . import B, C, A # I201 # noqa: I101
if TYPE_CHECKING:
import ast
import sys # noqa: I202
import os # noqa
import unittest
import X # noqa
from . import B, C, A # I201 # noqa: I101
flake8-import-order-0.19.2/tests/test_cases/wrong_import_order.py 0000664 0001750 0001750 00000000157 15026506505 025123 0 ustar jrivero jrivero # appnexus edited google smarkets
import a
import A # I100
if TYPE_CHECKING:
import a
import A # I100
flake8-import-order-0.19.2/tests/test_pylama_linter.py 0000664 0001750 0001750 00000000754 15026506505 022747 0 ustar jrivero jrivero import pytest
@pytest.mark.skip("pylama seems unmaintained")
def test_linter(tmpdir):
from flake8_import_order.pylama_linter import Linter
file_ = tmpdir.join("flake8_import_order.py")
file_.write("import ast\nimport flake8_import_order\n")
options = {
"application-import-names": ["flake8_import_order"],
}
checker = Linter()
assert checker.allow(str(file_))
for error in checker.run(str(file_), **options):
assert error["type"] == "I201"
flake8-import-order-0.19.2/tests/test_flake8_linter.py 0000664 0001750 0001750 00000002654 15026506505 022637 0 ustar jrivero jrivero import ast
import pycodestyle
from flake8_import_order.flake8_linter import Linter
from flake8_import_order.styles import Google
def test_parsing():
style = "google"
import_names = ["flake8_import_order", "tests"]
package_names = ["local_package"]
argv = [
"--application-import-names={}".format(",".join(import_names)),
f"--import-order-style={style}",
"--application-package-names={}".format(",".join(package_names)),
]
parser = pycodestyle.get_parser("", "")
Linter.add_options(parser)
options, args = parser.parse_args(argv)
Linter.parse_options(options)
assert Linter.options["import_order_style"].name == style
assert Linter.options["import_order_style"].load() is Google
assert Linter.options["application_import_names"] == import_names
assert Linter.options["application_package_names"] == package_names
def test_linter():
argv = ["--application-import-names=flake8_import_order"]
parser = pycodestyle.get_parser("", "")
Linter.add_options(parser)
options, args = parser.parse_args(argv)
Linter.parse_options(options)
data = "import ast\nimport flake8_import_order\n"
pycodestyle.stdin_get_value = lambda: data
tree = ast.parse(data)
checker = Linter(tree, None)
for lineno, col_offset, msg, instance in checker.run():
assert msg.startswith(
"I201 Missing newline between import groups.",
)
flake8-import-order-0.19.2/.pre-commit-config.yaml 0000664 0001750 0001750 00000003224 15026506505 021610 0 ustar jrivero jrivero # To enable this pre-commit hook run:
# `pip install pre-commit` or `brew install pre-commit`
# Then run `pre-commit install`
exclude: 'tests\/test_cases'
# Learn more about this config here: https://pre-commit.com/
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-added-large-files
- id: check-toml
types: [toml]
- id: check-yaml
types: [yaml]
- id: end-of-file-fixer
types: [text]
stages: [pre-commit, pre-push, manual]
- id: trailing-whitespace
types: [text]
stages: [pre-commit, pre-push, manual]
- id: detect-private-key
- id: mixed-line-ending
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell
additional_dependencies:
- tomli
- repo: https://github.com/asottile/pyupgrade
rev: v3.20.0
hooks:
- id: pyupgrade
args: [--py39-plus]
- repo: https://github.com/PyCQA/isort
rev: 6.0.1
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
# - repo: https://github.com/pre-commit/mirrors-mypy
# rev: v1.16.0
# hooks:
# - id: mypy
# additional_dependencies:
# - types-python-dateutil
# - types-requests
# exclude: ^(docs/|tests/)
# - repo: https://github.com/jorisroovers/gitlint
# rev: v0.19.1
# hooks:
# - id: gitlint
#
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.8.0
hooks:
- id: setup-cfg-fmt
args: [--min-py3-version, '3.9']
- repo: https://github.com/gitleaks/gitleaks
rev: v8.27.2
hooks:
- id: gitleaks