Pythonの静的解析ツールisortを使ってみよう
https://gyazo.com/c8883d3826d33871a05fc96fc8012721
isortについて
isort はimportをアルファベット順に並べ替えたり、セクションやタイプ別に自動的に分けたりする Python ユーティリティ/ライブラリです。isort は全ての import を素早くソートするためのコマンドラインツール、Python ライブラリ、様々なエディタ用プラグインを提供します。実行には Python 3.6以降が必要ですが、Python 2 コードのフォーマットもサポートしています。
重要度が低いと思われるかもしれませんが、コードを書く人による「揺らぎ」のないコードになることは重要です。
変換前:
code: python
from my_lib import Object
import os
from my_lib import Object3
from my_lib import Object2
import sys
from third_party import lib15, lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8, lib9, lib10, lib11, lib12, lib13, lib14
import sys
from __future__ import absolute_import
from third_party import lib3
print("Hey")
print("yo")
変換後:
code: python
from __future__ import absolute_import
import os
import sys
from third_party import (lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8,
lib9, lib10, lib11, lib12, lib13, lib14, lib15)
from my_lib import Object, Object2, Object3
print("Hey")
print("yo")
インストール
isort は pip コマンドでインストールすることができます。
code: bash
$ pip install isort
この場合は、requirements.txt に対応したisortをインストールします。
code: bash
isortをPipfileに対応させてインストールします。
code: bash
両方のフォーマットをサポートしたisortをインストールします。
code: bash
コマンドラインから使用する
特定のファイルに対して実行するためには、次のように isort を実行します。
code: bash
$ isort mypythonfile.py mypythonfile2.py
ディレクトリを指定すると、そのディレクトリ以下に再帰的に適用されます。
code: bash
$ isort .
globstarが有効な場合、isort . は以下と同等です。
code: bash
$ isort **/*.py
提案された変更を適用せずに表示するには、次のように --diffオプションを与えます。
code: bash
$ isort --diff mypythonfile.py
最後に、isortをプロジェクトに対してアトミックに実行し、シンタックスエラーが発生しない場合にのみ変更を適用します。
code: bash
$ isort --atomic .
注意:これは、異なるバージョンのPythonを使って書かれたコードに対してisortが実行されるのを防ぐため、デフォルトでは無効になっています)。
--helpオプションだけを与えて実行すると簡単なヘルプメッセージが出力されます。
code: bash
% isort --help
(以下略)
Pythonスクリプトの中から実行する
isort は python スクリプトの中から呼び出して実行することもできます。
code: python
import isort
isort.file("pythonfile.py")
もしくは次のように実行します。
code: python
import isort
sorted_code = isort.code("import b\nimport a\n")
テキストエディタkへのisortのインストール
様々なテキストエディタから isort を使用するためのプラグインがいくつか書かれています。これらのプラグインの一覧 は isort wiki にあります。また、他のテキストエディタ用のプラグインを含むプルリクエストを積極的に受け入れ、通知があればそれらのドキュメントを追加します。 マルチライン出力モード
"multi_line_output"という設定があります。この設定は、インポートデータが行数制限を超えたときに、どのように折り返すかを定義するもので、12種類の設定が可能です。
インデント
インデントの表示方法を変更するには、インデントのプロパティを以下のフォーマットで変更します。
スペースの数:4は、標準的な4スペースのインデントになります。
タブ
引用符で囲まれたそのままの文字列
例えば、以下のようになります。
code: python
" "
は4に相当します。
括弧を使用するインポートスタイルでは、最後のインポートの後に末尾のコンマを含めるかどうかを、include_trailing_commaオプションで制御できます(デフォルトはFalse)。
複数行のインポートをインテリジェントにバランスする
isort 3.1.0 では、バランスのとれた複数行のインポートをサポートしています。この機能を有効にすると、 isort はインポートの長さを動的に変更し、最もバランスの取れたグリッドを作成しますが、 定義された最大インポート長には達しません。
例えば、変換例をみてみあしょう。
変換前:
code: python
from __future__ import (absolute_import, division,
print_function, unicode_literals)
変換後:
code: python
from __future__ import (absolute_import, division, print_function,
unicode_literals)
これを有効にするには、設定でbalanced_wrappingをTrueに設定するか、コマンドラインユーティリティーに-e オプションを渡します。
カスタムセクションとオーダー
isort には、インポートファイルの構成、順序、セクションでのまとめ方など、ほぼすべての面で変更できる設定オプションがあります。
これらのオプションの概要はこちらをご覧ください。
インポートの処理をスキップする (設定外)
isort が単一のインポートを無視するには、インポート行の最後に# isort:skip というコメントを追加します。
code: python
import module # isort:skip
code: python
from xyz import (abc, # isort:skip
yo,
hey)
isort がファイル全体をスキップするには、モジュールの doc 文字列に isort:skip_file を追加します。
code: python
""" my_module.py
Best module ever
isort:skip_file
"""
import b
import a
アクションコメント
一つのファイルの中でisortの流れを設定する最も基本的な方法は、アクションコメントです。これらのコメントは、isort パーサーが解析時に読み取って解釈します。
isort: skip_file
isortにファイル全体をスキップするように指示します。
使用例
code: python
# !/bin/python3
# isort: skip_file
import os
import sys
...
これは、ファイルの中でできるだけ高い位置に配置する必要があります。isort はストリーミングアーキテクチャを採用しているので、 コメントに到達する前に既に作業が完了していることがあります。通常、これは問題ありませんが、 --diff やコマンドラインからの対話型オプションを使用している場合には、 混乱する可能性があります。
isort: skip
isort が import 文と同じ行に置かれた場合 (または import 文の続きに置かれた場合)、 isort はその import をソートしません。具体的には、isort が import 文を import として認識しないようにします。その結果、この行はコードとして扱われ、ファイルの import セクションの下に押し込まれます。
使用例
code: python
import b
import a # isort: skip <- this will now stay below b
注意: 可能であれば、# isort: off、# isort: on または # isort: split を使用することを推奨します。動作がより明確で予測可能になります。
isort: off
isort の解析をオフにします。isort: off の後のすべての行は、# isort: on のコメントがあるか、ファイルが終了するまで、変更されずに渡されます。
使用例
code: python
import e
import f
# isort: off
import b
import a
isort: on
isortの解析を再びオンにします。これは、ファイルの上位に # isort: off というコメントがある場合にのみ意味を持ちます。これにより、ソートされたインポートの周りに、ソートされていないインポートのブロックを置くことができます。
使用例
code: python
import e
import f
# isort: off
import b
import a
# isort: on
import c
import d
isort: split
isortに、現在のソートセクションが終了し、今後のインポートはすべて新しいソートグループに属することを伝えます。
使用例
code: python
import e
import f
# isort: split
import a
import b
import c
import d
また、インラインで使用することで、あるインポートが上下のインポートと位置を入れ替えることを防ぐことができます。
code: python
import c
import b # isort: split
import a
ヒント: isortの分割は、# isort: off のすぐ下に # isort: onを配置するのと全く同じです。
isort: dont-add-imports
--add-imports が設定されていても、isort が自動的にこのファイルにインポートを追加しないようにします。
isort: dont-add-imports: IMPORT_LINE
--add-imports が追加するように言っていても、特定のインポートを自動的に追加しないように isort に指示する。
複数のファイルからインポートを追加・削除する
isortは、インポートを自動的に追加/削除するように実行または設定することができます。
複数ファイルへのインポートの追加
isort では、インポートが正しく配置されていることを確認しながら、複数のファイルにインポートステートメントを簡単に追加することができます。
すべてのファイルにインポートを追加するには
code: bash
$ isort -a "from __future__ import print_function" *.py
すでにインポートがあるファイルにのみインポートを追加する場合。
code: bash
$ isort -a "from __future__ import print_function" --append-only *.py
複数のファイルからインポートを削除する
isortでは、元々のフォーマットを気にすることなく、複数のファイルからインポートを簡単に削除することができます。
コマンドラインから次のように実行する場合。
code: bash
$ isort --rm "os.system" *.py
black との互換性
Black との互換性は isort プロジェクトにとって非常に重要であり、バージョン 5 から組み込まれています。isortをblackと一緒に使うために必要なのは、isortのプロファイルを "black "に設定することだけです。
ヒント:プロファイル以外にも、skip_gitignore (isort は git のインストールが必要なのでデフォルトでは有効ではありません) や line_length を設定するのが一般的です。これは black のデフォルトである 88 から逸脱するためです。
コマンドライン
isort をコマンドラインから直接呼び出す際に profile オプションを使用するには、次のように --profile black を与えて実行します。
code: bash
$ isort --profile black *.py
.travis.yml での設定例です。
code: .travis.yml
language: python
python:
- "3.6"
- "3.7"
- "3.8"
install:
- pip install -r requirements-dev.txt
- pip install isort black
- pip install coveralls
script:
- pytest my-package
- isort --profile black my-package
- black --check --diff my-package
after_success:
- coveralls
詳細は「組み込みプロファイル」を参照してください。
設定ファイル (例えば .isort.cfg) の使用
isort と black の両方を公式に使用するプロジェクトでは、プロジェクトのリポジトリのルートにある設定ファイルで black のプロファイルを設定することをおすすめします。そうすれば、ユーザーがどのようにisortを呼び出すか(プリコミット、CLI、エディタ統合)に関わらず、ブラックプロファイルが自動的に適用されます。
例えば、pyproject.tomlファイルは以下のようになります。
code: pyproject.toml
profile = "black"
multi_line_output = 3
詳細は「設定ファイル」を参照してください。
pre-commitとの統合
isortをpre-commitに統合する際に、プロファイルを直接設定することもできます。
code: pre-commit
rev: 5.6.4
hooks:
- id: isort
これを利用して、プレコミットのgit hookを作成することができます。(「Gitフック」を参照)
これにより、プロジェクト全体で一定レベルのコード品質を確保することができます。
コードの検証にisortを使う
--check-only オプションを指定して実行すると、コードが正しくフォーマットされているかどうかを確認することができます。ソートされていない、あるいはフォーマットされていないインポートを含むファイルは、標準エラーに出力されます。
code: bash
$ isort **/*.py -c -v
SUCCESS: /home/timothy/Projects/Open_Source/isort/isort_kate_plugin.py Everything Looks Good!
ERROR: /home/timothy/Projects/Open_Source/isort/isort/isort.py Imports are incorrectly sorted.
設定ファイル
isort は、カスタマイズした内容をプロジェクトに迅速に組み込むことができるように、さまざまな標準コンフィグ形式をサポートしています。設定を適用する際、isort はサポートされている設定ファイルの中から最も近いものを探し、以下の順序で実行します。コマンドラインで --settings-path を指定すれば、設定ファイルやパスを手動で指定することができます。そうでない場合、isort は適切な設定ファイルを見つけるまで、最大 25 の親ディレクトリを辿ります。なお、isort は git や Mercurial リポジトリを離れないことに注意してください (.git や .hg のディレクトリを確認します)。ファイルが見つかるとすぐに探すのをやめてしまいます。設定ファイルの検索は、isort .またはファイルストリームが渡された場合はカレントディレクトリからの相対パス、複数のパスが渡された場合は最初に渡されたパスからの相対パスで行われます。
ヒント:i sort が決定した設定を調べて、どのコンフィグファイルを使用したかを知るには次のように実行します。
code: bash
$ isort . --show-config
.isort.cfg (好ましいフォーマット)
isort が最初に設定を探すのは、専用の .isort.cfg ファイルです。この種の設定ファイルの利点は、isort のために明示的に作成され、よく理解されたフォーマットに従っていることです。しかし、このような設定ファイルを使用すると、プロジェクト内に設定ファイルが一つ増えることになり、ファイル階層を汚染する可能性があります。
isortプロジェクトの設定ファイルの例を示します。
code: isort.cfg
profile=hug
src_paths=isort,test
pyproject.toml (推奨フォーマット)
isort が2番目に見る場所は、設定を置くのに同様に優れた選択肢である、pyproject.toml ファイル内です。この設定ファイルを使用する利点は、すべての Python ツールを設定するための標準的な場所になりつつあることです。つまり、他の開発者はここを見ることを知っているし、あなたはプロジェクトのルートをきれいに整理しておくことができます。唯一の欠点は、あなたが使っている他のツールがまだこのフォーマットをサポートしていないかもしれないということで、きれいさが損なわれてしまいます。
code: pyproject.toml
profile = "hug"
setup.cfg
setup.cfg は、pyproject.toml の前駆体と考えることができます。isort や新しいツールはどんどん pyproject.toml に移行していますが、この標準を使用している多くのツールに依存している場合、isort の設定をそこに置くのは自然なことでしょう。
code: setup.cfg
profile=hug
src_paths=isort,test
tox.ini
tox は、Python コミュニティで複数のテスト環境を指定するためによく使われるツールです。isort 検証は一般的にテストステップとして実行されるため、isort 設定を tox.ini ファイルの中に置くことを好む人もいます。
code: tox.ini
.editorconfig
最後に、isortはPythonソースファイルの設定を含む .editorconfig 設定を探します。EditorConfig は、テキスト編集の動作のための設定を一度に指定して、複数のコマンドラインツールやテキストエディタがそれを拾えるようにするためのプロジェクトです。isort はテキストエディタと同じ設定(行の長さなど)の多くを気にするので、これらのファイル内を探すのは理にかなっています。
code: .editorconfig
root = true
profile = hug
indent_style = space
indent_size = 4
skip = build,.tox,venv
src_paths=isort,test
カスタムコンフィグファイル
オプションとして、独自の名前で設定ファイルを作成したり、-settings-file を使って isort に優先順位の低い設定ファイルを直接指定したりすることもできます。これは例えば、.py ファイル用の設定と .pyx ファイル用の設定を用意し、設定ファイルをリポジトリのルートに置いておきたい場合などに便利です。
ヒント:カスタム設定ファイルでは、設定オプションを [isort] セクションに記述し、一般的な [settings] セクションには記述しないでください。これは、他のツールがその設定ファイルをどのように利用しているかを isort が知ることができないからです。
カスタムセクションと順序
isort には、インポートのセクション分けや、セクション内でのインポートの並べ方を設定するための多くの機能があります。
sectionsオプションでは、セクションの順序を好みの設定にすることができます。次の設定はデフォルトの順序と同じです。
sections=FUTURE,STDLIB,FIRSTPARTY,THIRDPARTY,LOCALFOLDER
sectionsオプションが定義されている場合、デフォルトのセクションを省略するとエラーになることがあります。
指定例
known_django=django
known_pandas=pandas,numpy
sections=FUTURE,STDLIB,DJANGO,THIRDPARTY,PANDAS,FIRSTPARTY,LOCALFOLDER
上記の設定をすると、指定された既知のモジュールを持つ2つの新しいセクションが作成されます。
no_lines_before オプションは、リストアップされたセクションが空行によって前のセクションから分割されるのを防ぎます。
指定例
sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
no_lines_before=LOCALFOLDER
この例の場合では、FIRSTPARTYとLOCALFOLDERの両方のモジュールを組み合わせたセクションができます。
重要な注意事項: 既知のセクションを設定する際には、歴史的な理由からネーミングが直接マッピングされないことを知っておくことが非常に重要です。カスタム設定の場合、唯一の違いは大文字か小文字か(known_custom=custom VS sections=CUSTOM`)で、その他の場合は以下のマッピングを参照してください。
known_standard_library : STANDARD_LIBRARY
extra_standard_library : STANDARD_LIBRARY # 既知の標準ライブラリと同じですが、置き換えではなく追加されます。
known_future_library : FUTURE
known_first_party: FIRSTPARTY
known_third_party: THIRDPARTY
known_local_folder : LOCALFOLDER
これは、isort 6.0.0以降で後方互換性のある方法で変更される予定です。
インポートセクションの自動コメント化
プロジェクトによっては、インポートセクションに独自のタイトルをつけて、目で見てすぐにセクションを特定できるようにしたい場合があります。isort はこれも自動化できます。これを行うには、自動コメントを付けたい各セクションの import_heading_{section_name} 設定を、希望するコメントに設定するだけです。
指定例
import_heading_stdlib=Standard Library
import_heading_firstparty=My Stuff
この場合、以下のような出力になります。
code: pythohn
# Standard Library
import os
import sys
import django.settings
# My Stuff
import myproject.test
インポートの長さで並べ変える
isortでは、length_sortオプションをTrueに設定するだけで、インポートの長さで並べ変えることができます。これにより、以下のような出力スタイルになります。
code: python
from evn.util import (
Pool,
Dict,
Options,
Constant,
DecayDict,
UnexpectedCodePath,
)
また、特定のセクションだけを対象に、インポートを長さでソートするように設定することも可能です。設定項目として、length_sort_ に続けてセクション名を使用します。
length_sort_stdlib=1
isort のインポートからのセクションを制御する
デフォルトでは、isort は直線的なインポート (import y) を fromでのインポート(from x import y)よりも上位に配置します。
code: pytohn
import b
from a import a
しかし、厳密なアルファベット順のソートを維持したい場合は、force_sort_within_sections をtrueに設定することができます。
code: python
from a import a # This will now appear at top because a appears in the alphabet before b
import b
isortに、デフォルトではfromを使ったインポートは下に配置するところを、from_firstにtrue 設定すると、常に上に配置するように指示することもできます。
code: python
from b import b # If from first is set to True, all from imports will be placed before non-from imports.
import a
Gitフック
isort は、コミットする前に Python コードをチェックするための Git pre-commitスクリプトに統合できるフック関数を提供しています。
isort のエラーがあった場合にコミットを失敗させる (strict モード) には、.git/hooks/pre-commit に次のように記述します。
code: python
import sys
from isort.hooks import git_hook
sys.exit(git_hook(strict=True, modify=True, lazy=True, settings_file=""))
警告を表示するだけでコミットはさせたいという場合は、git_hook() を strict 引数なしで呼び出します。警告を表示するだけでなくコードの修正もしたくない場合は、modify パラメータを指定せずに git_hook をコールします。lazy 引数は、ファイルを個別にインデックスに追加するのが "億劫" で、代わりに git commit -a を使うことが多いユーザーをサポートするためのものです。これを True にすると、追跡されたすべてのファイルが適切にソートされているかどうかを確認することができます。
フックに特定の設定ファイルを使いたい場合は、そのパスを settings_file に渡します。特にパスが指定されていない場合は、git_hook() は最初にステージングされたファイルのあるディレクトリから、git diff-index の順序に従って設定ファイルを探し始め、有効な設定ファイルが見つかるか MAX_CONFIG_SEARCH_DEPTH ディレクトリをチェックするまでディレクトリ構造をさかのぼっていきます。settings_file パラメータは、設定ファイルを他のすべてのファイルの親ではないディレクトリに置いているユーザーをサポートするために使用されます。
Githubアクション
使用方法
python-isort プラグインは、checkout アクションや setup-python アクションと組み合わせて実行するように設計されています。デフォルトでは、リンティング対象のリポジトリのルートから再帰的に実行され、コードが正しくソートされていない場合はエラーで終了します。 入力内容
isortVersion
オプションです。使用するisortのバージョン。デフォルトでは最新バージョンのisortを使用します。
sortPaths
オプションです。ソートするパスのリストで、プロジェクトのルートからの相対パスです。既定は .NET です。
configuration
オプションです。isort CLIに渡すisort構成オプションです。既定値は --check-only --diff です。
requirementsFiles
オプションです。isort を実行する前にインストールする python の要件ファイルへのパスを指定します。複数の要件ファイルを指定する場合は、スペースで区切らなければなりません。カスタムパッケージのインストールが必要な場合は、このアクションを実行する前に、別のステップで依存関係をインストールする必要があります。
ヒント:サードパーティのライブラリが適切に分類されるように、isortを実行する前にプロジェクトの依存関係をインストールしておくことが重要です。
出力
isort-result
isort コマンドラインツールの出力
使用例
code: YAML
name: Run isort
on:
- push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.8
- uses: jamescurtin/isort-action@master
with:
requirementsFiles: "requirements.txt requirements-test.txt"
マルチライン出力モード
設定オプションmulti_line_outputは、インポートデータがline_lengthの制限を超えたときに、どのように折り返すかを定義するもので、12種類の設定が可能です。
0 - Grid デフォルト
code: python
from third_party import (lib1, lib2, lib3,
lib4, lib5, ...)
1 - Vertical
code: python
from third_party import (lib1,
lib2,
lib3
lib4,
lib5,
...)
2 - Hanging Indent
code: python
from third_party import \
lib1, lib2, lib3, \
lib4, lib5, lib6
3 - Vertical Hanging Indent
code: python
from third_party import (
lib1,
lib2,
lib3,
lib4,
)
4 - Hanging Grid
code: python
from third_party import (
lib1, lib2, lib3, lib4,
lib5, ...)
5 - Hanging Grid Grouped
code: python
from third_party import (
lib1, lib2, lib3, lib4,
lib5, ...
)
6 - Hanging Grid Grouped
モード5と同じです。非推奨です。
7 - NOQA
code: pytohn
from third_party import lib1, lib2, lib3, ... # NOQA
また、force_single_line をTrueに設定すると(コマンドラインオプションでは-sl)、すべてのインポートが独立した行で表示されるようになります。
code: python
from third_party import lib1
from third_party import lib2
from third_party import lib3
...
8 - Vertical Hanging Indent Bracket
モード 3 - Vertical Hanging Indentと同じですが、最終行の閉じた括弧がインデントされます。
code: python
from third_party import (
lib1,
lib2,
lib3,
lib4,
)
9 - Vertical Prefix From Module Import
行が行長の制限よりも長い場合、同じ from MODULE import で新しい行を開始します。
code: python
from third_party import lib1, lib2, lib3
from third_party import lib4, lib5, lib6
10 - Hanging Indent With Parentheses
モード 2 - Hanging Indent と同じですが、長い行の折り返しにバックスラッシュの代わりに括弧を使用します。
code: python
from third_party import (
lib1, lib2, lib3,
lib4, lib5, lib6)
11 - Backslash Grid
モード 0 - Gridと同じですが、インポートのグループ化には括弧の代わりにバックスラッシュを使用します。
code: python
from third_party import lib1, lib2, lib3, \
lib4, lib5
isortの組み込みプロファイル
一般的なプロジェクトやコードスタイルとの相互運用を容易にするために、以下のプロファイルがisortに組み込まれています。
これらのプロファイルを使用するには、コマンドラインで --profile PROFILE_NAME オプションを与えるか、設定ファイルで profile=PROFILE_NAME を指定します。
black
multi_line_output: 3
include_trailing_comma: True
force_grid_wrap: 0
use_parentheses: True
ensure_newline_before_comments: True
line_length: 88
django
combine_as_imports: True
include_trailing_comma: True
multi_line_output: 5
line_length: 79
pycharm
multi_line_output: 3
force_grid_wrap: 2
lines_after_imports: 2
google
force_single_line: True
force_sort_within_sections: True
lexicographical: True
single_line_exclusions: ('typing',)
order_by_type: False
group_by_package: True
open_stack
force_single_line: True
force_sort_within_sections: True
lexicographical: True
plone
force_alphabetical_sort: True
force_single_line: True
lines_after_imports: 2
line_length: 200
attrs
atomic: True
force_grid_wrap: 0
include_trailing_comma: True
lines_after_imports: 2
lines_between_types: 1
multi_line_output: 3
use_parentheses: True
hug
multi_line_output: 3
include_trailing_comma: True
force_grid_wrap: 0
use_parentheses: True
line_length: 100
wemake
multi_line_output: 3
include_trailing_comma: True
use_parentheses: True
line_length: 80
appnexus
multi_line_output: 3
include_trailing_comma: True
force_grid_wrap: 0
use_parentheses: True
ensure_newline_before_comments: True
line_length: 88
force_sort_within_sections: True
order_by_type: False
case_sensitive: False
reverse_relative: True
sort_relative_in_force_sorted_sections: True
sections: ['FUTURE', 'STDLIB', 'THIRDPARTY', 'FIRSTPARTY', 'APPLICATION', 'LOCALFOLDER']
no_lines_before: 'LOCALFOLDER'
setuptoolsの統合
インストール時に、isort はプロジェクトで宣言された Python ファイルをチェックする setuptools コマンドを有効にします。
python setup.py isort をコマンドラインで実行すると、 py_modules と packages にリストアップされたファイルをチェックします。警告が出た場合、コマンドはエラーコードを表示して終了します。
code: bash
$ python setup.py isort
また、ユーザーが自分でisortをインストールしなくてもコマンドを使えるようにするために、setup() のsetup_requires にisortを以下のように追加してください。
code: setup.py
setup(
name="project",
setup_requires=[
"isort"
]
)