Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/asottile/reorder-python-imports
Rewrites source to reorder python imports
https://github.com/asottile/reorder-python-imports
linter pre-commit python refactoring
Last synced: about 14 hours ago
JSON representation
Rewrites source to reorder python imports
- Host: GitHub
- URL: https://github.com/asottile/reorder-python-imports
- Owner: asottile
- License: mit
- Created: 2015-01-01T19:30:10.000Z (almost 10 years ago)
- Default Branch: main
- Last Pushed: 2024-10-29T01:21:58.000Z (about 1 month ago)
- Last Synced: 2024-11-26T11:09:23.677Z (16 days ago)
- Topics: linter, pre-commit, python, refactoring
- Language: Python
- Size: 501 KB
- Stars: 741
- Watchers: 9
- Forks: 55
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- jimsghstars - asottile/reorder-python-imports - Rewrites source to reorder python imports (Python)
README
[![build status](https://github.com/asottile/reorder-python-imports/actions/workflows/main.yml/badge.svg)](https://github.com/asottile/reorder-python-imports/actions/workflows/main.yml)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/asottile/reorder-python-imports/main.svg)](https://results.pre-commit.ci/latest/github/asottile/reorder-python-imports/main)reorder-python-imports
======================Tool for automatically reordering python imports. Similar to `isort` but
uses static analysis more.## Installation
```bash
pip install reorder-python-imports
```## Console scripts
Consult `reorder-python-imports --help` for the full set of options.
`reorder-python-imports` takes filenames as positional arguments
Common options:
- `--py##-plus`: [see below](#removing-obsolete-__future__-imports).
- `--add-import` / `--remove-import`: [see below](#adding--removing-imports).
- `--replace-import`: [see below](#replacing-imports).
- `--application-directories`: by default, `reorder-python-imports` assumes
your project is rooted at `.`. If this isn't true, tell it where your
import roots live. For example, when using the popular `./src` layout you'd
use `--application-directories=.:src` (note: multiple paths are separated
using a `:`).
- `--unclassifiable-application-module`: (may be specified multiple times)
modules names that are considered application modules. this setting is
intended to be used for things like C modules which may not always appear on
the filesystem.## As a pre-commit hook
See [pre-commit](https://github.com/pre-commit/pre-commit) for instructions
Sample `.pre-commit-config.yaml`
```yaml
- repo: https://github.com/asottile/reorder-python-imports
rev: v3.14.0
hooks:
- id: reorder-python-imports
```## What does it do?
### Separates imports into three sections
```python
import sys
import pyramid
import reorder_python_imports
```becomes (stdlib, third party, first party)
```python
import sysimport pyramid
import reorder_python_imports
```### `import` imports before `from` imports
```python
from os import path
import sys
```becomes
```python
import sys
from os import path
```### Splits `from` imports
```python
from os.path import abspath, exists
```becomes
```python
from os.path import abspath
from os.path import exists
```### Removes duplicate imports
```python
import os
import os.path
import sys
import sys
```becomes
```python
import os.path
import sys
```## Using `# noreorder`
Lines containing and after lines which contain a `# noreorder` comment will
be ignored. Additionally any imports that appear after non-whitespace
non-comment lines will be ignored.For instance, these will not be changed:
```python
import systry: # not import, not whitespace
import foo
except ImportError:
pass
``````python
import sysimport reorder_python_imports
import matplotlib # noreorder
matplotlib.use('Agg')
import matplotlib.pyplot as plt
``````python
# noreorder
import sys
import pyramid
import reorder_python_imports
```## why this style?
The style chosen by `reorder-python-imports` has a single aim: reduce merge
conflicts.By having a single import per line, multiple contributors can
add / remove imports from a single module without resulting in a conflict.Consider the following example which causes a merge conflict:
```diff
# developer 1
-from typing import Dict, List
+from typing import Any, Dict, List
``````diff
# developer 2
-from typing import Dict, List
+from typing import Dict, List, Tuple
```no conflict with the style enforced by `reorder-python-imports`:
```diff
+from typing import Any
from typing import Dict
from typing import List
+from typing import Tuple
```## Adding / Removing Imports
Let's say I want to enforce `absolute_import` across my codebase. I can use:
`--add-import 'from __future__ import absolute_import'`.```console
$ cat test.py
print('Hello world')
$ reorder-python-imports --add-import 'from __future__ import absolute_import' test.py
Reordering imports in test.py
$ cat test.py
from __future__ import absolute_import
print('Hello world')
```Let's say I no longer care about supporting Python 2.5, I can remove
`from __future__ import with_statement` with
`--remove-import 'from __future__ import with_statement'````console
$ cat test.py
from __future__ import with_statement
with open('foo.txt', 'w') as foo_f:
foo_f.write('hello world')
$ reorder-python-imports --remove-import 'from __future__ import with_statement' test.py
Reordering imports in test.py
$ cat test.py
with open('foo.txt', 'w') as foo_f:
foo_f.write('hello world')
```## Replacing imports
Imports can be replaced with others automatically (if they provide the same
names). This can be useful for factoring out compatibility libraries such
as `six` (see below for automated `six` rewriting).This rewrite avoids `NameError`s as such it only occurs when:
- the imported symbol is the same before and after
- the import is a `from` importThe argument is specified as `orig.mod=new.mod` or with an optional
checked attribute `orig.mod=new.mod:attr`. The checked attribute is useful
for renaming some imports from a module instead of a full module.For example:
```bash
# full module move
--replace-import six.moves.queue=queue
# specific attribute move
--replace-import six.moves=io:StringIO
```## Removing obsolete `__future__` imports
The cli provides a few options to help "burn the bridges" with old python
versions by removing `__future__` imports automatically. Each option implies
all older versions.- `--py22-plus`: `nested_scopes`
- `--py23-plus`: `generators`
- `--py26-plus`: `with_statement`
- `--py3-plus`: `division`, `absolute_import`, `print_function`,
`unicode_literals`
- `--py37-plus`: `generator_stop`## Removing / rewriting obsolete `six` imports
With `--py3-plus`, `reorder-python-imports` will also remove / rewrite imports
from `six`. Rewrites follow the same rules as
[replacing imports](#replacing-imports) above.For example:
```diff
+import queue
+from io import StringIO
+from urllib.parse import quote_plus
+
import six.moves.urllib.parse
-from six.moves import queue
-from six.moves import range
-from six.moves import StringIO
-from six.moves.urllib.parse import quote_plus
```## Rewriting mock imports
With `--py3-plus`, `reorder-python-imports` will also rewrite various `mock` imports:
```diff
-from mock import patch
+from unittest.mock import patch
```## Rewriting `mypy_extensions` and `typing_extension` imports
With `--py36-plus` and higher, `reorder-python-imports` will also rewrite
`mypy_extensions` and `typing_extensions` imports ported to `typing`.```diff
-from mypy_extensions import TypedDict
+from typing import TypedDict
```## Rewriting pep 585 typing imports
With `--py39-plus` and higher, `reorder-python-imports` will replace imports
which were moved out of the typing module in [pep 585].```diff
-from typing import Sequence
+from collections.abc import Sequence
```[pep 585]: https://www.python.org/dev/peps/pep-0585/