設計からテストまで全部vscodeでできるpythonの環境を作る

# 作ったもの
　設計からテストまで全部vscodeで完結しているpythonの環境。及び、その環境構築のバッチ化。

# 目的
　設計はスプレッドシート、実装はvscodeとすると、コードをちょっと直すたびにスプレッドシートを直さなければならず、複数画面でもないとあっちこっち開き直すのが非常に面倒と感じたため。
　なるべくvscode1つで完結し、かつ、自動化を図った環境を目指す。また、設定する項目が非常に多岐に渡るため、それらを自動で設定するためのバッチファイルの作成を行う。

# 環境
　OS: windows11
　python: 3.12.0
　vscode: 1.83.1

# 事前準備
　使用するPC内にvscodeとpythonをインストールしておく。
　pythonのパスは通しておく。

# 使用ツール
|  目的  |  使用ツール  |  vscode拡張機能  | pip |
| ---- | ---- | ---- | ----|
|  事前設定  | Python<br>Pylance | Python<br>Pylance | - |
|  設計(非コード)  |  draw.io<br>(diagram.net)  |  Draw.io Integration |  -  |
|  設計(docstring)  |  Sphinx  |  Extension Pack for reStructuredText  |  sphinx<br> sphinx-rtd-theme<br> sphinx auto-build  |
|  実装  |  PEP8  |  Flake8  |  flake8  |
|  テスト  |  pytest  |  -  |  pytest  | 

　あらかじめvscode拡張機能の方はインストールしておくこと。

　ここでいう設計(非コード)とは、いわゆるシステムアーキテクチャ図やER図などのUML図である。
　また、設計(docstring)とは、ソースコードのdocstringから自動的に作成されるドキュメントである。

# フォルダ階層
　拡張子がない文字列はフォルダ、拡張子がある文字列はファイルである。
 　下記に示すバッチファイルを実行すれば、以下のようなフォルダ構成になる。
```フォルダ階層
ワークスペースルート
|
| - .vscode/ (設定ファイルやタスクファイル)
|    | - settings.json
|    | - tasks.json
|
| - data/ (データ関連のファイル)
|    | - data.xlsx (例)
|    | - ...
|
| - docs/ (設計書の管理)
|    | - design/ (Draw.io Integrationで作成する設計書)
|    |    | - 1_system_architecture.drawio.png
|    |    | - ...
|    |
|    | - sphinx_src/ (docstringから作成する設計書)
|    |    | - build/
|    |    |    | - index.html
|    |    |    | - ...
|    |    |
|    |    | - source/
|    |    |    | - _static/
|    |    |    | - _templates/
|    |    |    | - conf.py
|    |    |    | - index.rst
|    |    |    | - ...
|    |    |
|    |    | - make.bat
|    |    | - MakeFile
|
| - env/ (仮想環境)
|    | - Include/
|    |    | - ...
|    |
|    | - Lib/
|    |    | - ...
|    |
|    | - Scripts/
|    |    | - ...
|    |
|    | - pyvenv.cfg
|
| - src/ (ソースコード)
|    | - __init__.py
|    | - main.py
|    | - ...
|
| - tests/ (テスト用コード)
|    | - __init__.py
|    | - test_main.py
|    | - ...
|
| - .gitignore
| - pytest.ini
| - README.md
| - requirements.txt
```

# 参考画像
![vscode_init.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584218/a3006c74-141f-5a0c-0199-06f70c07c979.png)


# バッチファイル作成
　今回作成した環境は様々な設定やpipを用いてのインストール等があるので、それをプロジェクトごとに毎回行うのは非常に手間であると判断した。
　よって、最初にプロジェクト名のみを入力することで、下記に記す設定をすべて一括で行ってくれるバッチファイルを作成した。~~ありがとうChatGPT~~


```create_project.bat<br>
@echo off
setlocal enabledelayedexpansion

:: Input project file name
set /p project_name="Enter the project name: "

:: Create a new directory for the project and navigate to it
mkdir %project_name%
cd %project_name%

:: Create README.md
echo # %project_name%>README.md

:: Create a virtual environment and activate it
python -m venv env
call env\Scripts\activate.bat

:: Add pytest, flake8, sphinx, esbonio, and setuptools to requirements.txt and install dependencies
python.exe -m pip install --upgrade pip
pip install --upgrade setuptools
echo pytest>requirements.txt
echo flake8>>requirements.txt
echo sphinx>>requirements.txt
echo sphinx-rtd-theme>>requirements.txt
echo sphinx-autobuild>>requirements.txt
echo esbonio>>requirements.txt
pip install -r requirements.txt

:: Create src, data, tests, and more directories
mkdir src
mkdir data
mkdir tests
mkdir docs
mkdir docs\design
mkdir docs\sphinx_src

:: drawio file create
cd docs\design
for %%f in (
    1_system_architecture
    2_class
    3_sequence
    4_data_flow
    5_entity_relationship
    6_use_case
    7_activity
    8_state
) do (
    if not exist %%f.drawio (
        type nul > %%f.drawio.png
    )
)
cd ..\..

:: Sphinx init
cd docs\sphinx_src
sphinx-quickstart -q -p "%project_name%" -a "Your Name" -v "0.0.1" --sep --ext-autodoc --ext-viewcode
cd ..\..

:: Create .vscode directory if it does not exist
if not exist .vscode mkdir .vscode

echo { >> .vscode/settings.json
echo     "iis.configDir": "", >> .vscode/settings.json
echo     "esbonio.sphinx.confDir": "${workspaceFolder}\\docs\\sphinx_src\\source" >> .vscode/settings.json
echo } >> .vscode/settings.json

echo { >> .vscode/tasks.json
echo     "version": "2.0.0", >> .vscode/tasks.json
echo     "tasks": [ >> .vscode/tasks.json
echo         { >> .vscode/tasks.json
echo             "label": "sphinx-autobuild", >> .vscode/tasks.json
echo             "type": "shell", >> .vscode/tasks.json
echo             "command": ".\\env\\Scripts\\activate; sphinx-autobuild --watch src docs/sphinx_src/source docs/sphinx_src/build", >> .vscode/tasks.json
echo             "problemMatcher": [], >> .vscode/tasks.json
echo             "isBackground": true, >> .vscode/tasks.json
echo             "presentation": { >> .vscode/tasks.json
echo                 "reveal": "always", >> .vscode/tasks.json
echo                 "panel": "dedicated" >> .vscode/tasks.json
echo             }, >> .vscode/tasks.json
echo             "runOptions": { >> .vscode/tasks.json
echo                 "runOn": "folderOpen" >> .vscode/tasks.json
echo             } >> .vscode/tasks.json
echo         } >> .vscode/tasks.json
echo     ] >> .vscode/tasks.json
echo } >> .vscode/tasks.json


:: Set up .gitignore to ignore unwanted files and directories
echo env/>>.gitignore
echo __pycache__/>>.gitignore
echo .pytest_cache/>>.gitignore
echo .vscode/>>.gitignore
echo *.pyc>>.gitignore
echo *.pyo>>.gitignore
echo *.egg-info/>>.gitignore
echo exe/>>.gitignore
echo data/>>.gitignore
echo docs/>>.gitignore

echo [pytest]>>pytest.ini
echo pythonpath = src>>pytest.ini

cd src
type nul > __init__.py
cd ..

cd tests
type nul > __init__.py
cd ..

pause
```

:::note info
バッチファイルの実行箇所
そのプロジェクトファイルのルートディレクトリを設置したい階層で実行する。
:::


# バッチファイル解説

### :: Input project file name
　ユーザーにプロジェクト名の入力を促す。
```
set /p project_name="Enter the project name: "
```

### :: Create a new directory for the project and navigate to it
　入力されたプロジェクト名でフォルダを作成し、そこにcdコマンドで入る。
　このフォルダがvscodeでいう、ワークスペースフォルダとなる。
```
mkdir %project_name%
cd %project_name%
```

### :: Create README.md
　README.mdの作成。中身はプロジェクト名が記されているだけなので、後々記述を自分で追加すること。
　もちろんバッチファイルの方を修正して、自分好みにカスタマイズするのも良い。
```
echo # %project_name%>README.md
```

### :: Create a virtual environment and activate it
　仮想環境の作成とアクティベートを行う。
```
python -m venv env
call env\Scripts\activate.bat
```

### :: Add pytest, flake8, sphinx, esbonio, and setuptools to requirements.txt and install dependencies
　pipでインストールするものをrequirements.txtに記載し、その後にモジュールのインストールを行う。
　追加で入れておきたいモジュールがある場合、ここに追記する。
```
python.exe -m pip install --upgrade pip
pip install --upgrade setuptools
echo pytest>requirements.txt
echo flake8>>requirements.txt
echo sphinx>>requirements.txt
echo sphinx-rtd-theme>>requirements.txt
echo sphinx-autobuild>>requirements.txt
echo esbonio>>requirements.txt
pip install -r requirements.txt
```

### :: Create src, data, tests, and more directories
　ワークスペースフォルダの中に、ソースファイルを入れるフォルダや、設計書を入れるフォルダなどを切る。フォルダの詳細は[フォルダ階層](#フォルダ階層)項目にて説明している。
```
mkdir src
mkdir data
mkdir tests
mkdir docs
mkdir docs\design
mkdir docs\sphinx_src
```

### :: drawio file create
　ソースコードに関係ない設計ファイルの初期作成を行う。
　中身としては空の画像が作られるイメージ。
　バッチではUML図のよく使われるであろうものだけ作成するようにしている。詳細は以下。
　もちろんここも追加でほしい設計書があるならば追記を自由に行える。
```
cd docs\design
for %%f in (
    1_system_architecture
    2_class
    3_sequence
    4_data_flow
    5_entity_relationship
    6_use_case
    7_activity
    8_state
) do (
    if not exist %%f.drawio (
        type nul > %%f.drawio.png
    )
)
cd ..\..
```

| ファイル名 | UML図 | 
|:-----------|:------------|
| 1_system_architecture.drawio.png | システムアーキテクチャ図 |
| 2_class.drawio.png | クラス図 |
| 3_sequence.drawio.png | シーケンス図 |
| 4_data_flow.drawio.png | データフロー図 |
| 5_entity_relationship.drawio.png | ER図 |
| 6_use_case.drawio.png | ユースケース図 |
| 7_activity.drawio.png | アクティビティ図 |
| 8_state.drawio.png | ステート図 |

### :: Sphinx init

　ここでdocstringから自動で設計書を作ってくれるsphinxというモジュールの設定を行う。
```
cd docs\sphinx_src
sphinx-quickstart -q -p "%project_name%" -a "Your Name" -v "0.0.1" --sep --ext-autodoc --ext-viewcode
cd ..\..
```

・Sphinxの説明
>Sphinx makes it easy to create intelligent and beautiful documentation.

引用元：[Sphinx[1]](https://www.sphinx-doc.org/ja/master/ "Sphinx")

　
　以下ChatGPTに聞いてみたSphinxの概要

 <details><summary>ChatGPTによるSphinxの概要</summary>

##### Sphinxとは - ドキュメント作成の魔法
　プログラムのコードは、その機能だけでなく、その使い方や設計理念を伝えるドキュメントがなければ完全とは言えません。ドキュメントはコードの「取扱説明書」であり、他の開発者が理解し、使用し、さらには貢献するための基盤を提供します。ここで重要な役割を果たすのが、Sphinxです。

　SphinxはPythonで書かれたドキュメント生成ツールで、reStructuredText（reST）を使用して記述されたテキストから、HTMLやPDF、ePubなど様々なフォーマットのドキュメントを生成することができます。元々はPythonの公式ドキュメント用に作られたツールですが、その柔軟性と拡張性の高さから、今ではPython界隈に留まらず、多くのプログラミング言語やプロジェクトのドキュメント作成に利用されています。

##### Sphinxの特徴
　拡張性: さまざまな拡張機能によって、コードから直接ドキュメントを生成したり、ドキュメント内に動的な内容を組み込むことができます。
　多様な出力形式: HTMLやLaTeX（PDF）、manページ、テキスト形式など、多彩な出力オプションを提供します。
　国際化: ドキュメントの国際化（i18n）をサポートし、多言語でのドキュメント作成を容易にします。
　テーマとスタイル: 複数の組み込みテーマを使用したり、CSSをカスタマイズして、見た目を自由に変更することができます。
　インデックスと検索: 自動的に索引を生成し、ドキュメント内の検索機能を強化します。

##### Sphinxを使うメリット
　Sphinxを使う最大のメリットは、ドキュメント作成の効率化と品質の向上です。reSTのマークアップ言語は学習コストが低く、直感的な記述が可能です。さらに、ドキュメントのメンテナンスが容易になるため、プロジェクトが進化してもドキュメントを迅速に更新できます。

　また、Sphinxの「自動ドキュメント生成機能」は、特にAPIドキュメントを扱う際にその真価を発揮します。ドキュメントをコードと一緒に管理することで、コードの変更がドキュメントにリアルタイムで反映され、常に最新の情報を保つことができます。

##### まとめ
　ドキュメントは、プロジェクトの顔とも言える大切な要素です。Sphinxを活用することで、その品質とメンテナンスの容易さを確保し、開発者がより価値あるコードの創造に集中できるようになります。Sphinxは、ドキュメント作成のプロセスを魔法のように変えるツールです。

　概要以上
 </details>

 　今回、ドキュメント作成において、対抗馬としてはDoxygenなどがあったが、自動化という一点において、比較的簡単に実現できそうだったのでSphinxを採用した。

・バッチファイルで実行しているコマンドについての解説

```
sphinx-quickstart -q -p "%project_name%" -a "Your Name" -v "0.0.1" --sep --ext-autodoc --ext-viewcode
```

　[sphinx-quickstart[2]](https://www.sphinx-doc.org/ja/master/man/sphinx-quickstart.html "sphinx-quickstart")でも説明されている通り、まずsphinxを使えるようにするためには、quickstartコマンドを実行し、いくつかの質問に答えなくてはならない。
 　以下でオプションについて記載する。

| オプション | 説明 | 
|:-----------|:------------|
| -q | 本来行う対話をしないようにする。<br>その代わり、-p、-a、-vオプションが必須となる。 |
| -p | プロジェクト名。今回は最初に入力したものを使う。 |
| -a | 著者名。 今回は固定値"Your Name"を使う。<br>あとで変更はいくらでも可能である。|
| -v | バージョン。適当に設定。 |
| --sep | 記述した場合、ソースとビルドのディレクトリを分割する。 |
| --ext-autodoc | 拡張機能 sphinx.ext.autodocを有効にする。<br>これがdocstringから自動的にドキュメントをつくる部分。 |
| --ext-viewcode | 拡張機能 sphinx.ext.viewcodeを有効にする。 |

:::note info
docstringの形式について
自分が利用をする際は、[Googleスタイル[3]](https://qiita.com/11ohina017/items/118b3b42b612e527dc1d "GoogleスタイルのPython Docstringの入門")で統一している。
:::

### :: Create .vscode directory if it does not exist
```
if not exist .vscode mkdir .vscode

echo { >> .vscode/settings.json
echo     "iis.configDir": "", >> .vscode/settings.json
echo     "esbonio.sphinx.confDir": "${workspaceFolder}\\docs\\sphinx_src\\source" >> .vscode/settings.json
echo } >> .vscode/settings.json

echo { >> .vscode/tasks.json
echo     "version": "2.0.0", >> .vscode/tasks.json
echo     "tasks": [ >> .vscode/tasks.json
echo         { >> .vscode/tasks.json
echo             "label": "sphinx-autobuild", >> .vscode/tasks.json
echo             "type": "shell", >> .vscode/tasks.json
echo             "command": ".\\env\\Scripts\\activate; sphinx-autobuild --watch src docs/sphinx_src/source docs/sphinx_src/build", >> .vscode/tasks.json
echo             "problemMatcher": [], >> .vscode/tasks.json
echo             "isBackground": true, >> .vscode/tasks.json
echo             "presentation": { >> .vscode/tasks.json
echo                 "reveal": "always", >> .vscode/tasks.json
echo                 "panel": "dedicated" >> .vscode/tasks.json
echo             }, >> .vscode/tasks.json
echo             "runOptions": { >> .vscode/tasks.json
echo                 "runOn": "folderOpen" >> .vscode/tasks.json
echo             } >> .vscode/tasks.json
echo         } >> .vscode/tasks.json
echo     ] >> .vscode/tasks.json
echo } >> .vscode/tasks.json
```
　プロジェクトごとの設定ファイルを入れるためのフォルダがない場合は作成をする。このフォルダはふとした拍子に作られることがあるので、if文を使い、判断をさせるようにした。
　このフォルダの中に、settings.json、tasks.jsonを作り、各々設定を行う。

　1.settings.jsonの設定
　　大きなものでいうと、明示的にsphinxのconf.pyはここにあるという設定を行った。

　2.tasks.jsonの設定
　　ここが今回の設定で一番大事なところ。srcフォルダにあるファイルを保存したときに、sphinx autobuildが自動で走るように設定する。もしこの設定がないと、いちいち手作業でビルドコマンドを打つしかなくなる。

```
sphinx-autobuild --watch src docs/sphinx_src/source docs/sphinx_src/build
```

　このコマンドについて以下で解説を行う。

　[autobuild[4]](https://pypi.org/project/sphinx-autobuild/ "sphinx-autobuild")についてのページを見ると、以下のような追加の引数についての説明がある。
 
>Command line options
sphinx-autobuild accepts the same arguments as sphinx-build (these get passed to sphinx-build on each build). It also has a few additional options, which can seen by running sphinx-autobuild --help:
>
>$ sphinx-autobuild --help
usage: sphinx-autobuild [-h] [--port PORT] [--host HOST] [--re-ignore RE_IGNORE] [--ignore IGNORE] [--no-initial] [--open-browser]
                        [--delay DELAY] [--watch DIR] [--pre-build COMMAND] [--version]
                        sourcedir outdir [filenames [filenames ...]]
>
>positional arguments:
  sourcedir             source directory
  outdir                output directory for built documentation
  filenames             specific files to rebuild on each run (default: None)
>
>optional arguments:
  -h, --help            show this help message and exit
  --port PORT           port to serve documentation on. 0 means find and use a free port (default: 8000)
  --host HOST           hostname to serve documentation on (default: 127.0.0.1)
  --re-ignore RE_IGNORE
                        regular expression for files to ignore, when watching for changes (default: [])
  --ignore IGNORE       glob expression for files to ignore, when watching for changes (default: [])
  --no-initial          skip the initial build (default: False)
  --open-browser        open the browser after building documentation (default: False)
  --delay DELAY         how long to wait before opening the browser (default: 5)
  --watch DIR           additional directories to watch (default: [])
  --pre-build COMMAND   additional command(s) to run prior to building the documentation (default: [])
  --version             show program's version number and exit
>
>sphinx's arguments:
  The following arguments are forwarded as-is to Sphinx. Please look at `sphinx --help` for more information.
    -b=builder, -a, -E, -d=path, -j=N, -c=path, -C, -D=setting=value, -t=tag, -A=name=value, -n, -v, -q,

　よく他のページなどで説明されていたのは、いわゆる最小構成であり、コマンドとしては以下のような形が多くあった。
```
sphinx-autobuild docs docs/_build/html  # docsフォルダの中身をdocs/_build/htmlフォルダにビルドする
```
　引数としてはビルドするディレクトリや、ビルドされたものの保存箇所を指定するのみであったが、実際に引用部分を見てみるといろんな設定ができることがわかる。

　このうち、**--watch**引数に目をつけ、翻訳してみると以下のことが書いてあった。

```
--watch DIR 監視する追加ディレクトリ (デフォルト: [])
```

　通常のコマンド(sphinx-autobuild docs docs/_build/html)では、docsフォルダの中身が変更されないと、自動ビルドが走らない。しかし、この--watch引数を使うことで、そのビルドを走らせる条件に、指定したフォルダの中身が変更された時、という条件を追加する事ができる。

　ここで、今回指定したコマンドについてもう一度確認する。

```
sphinx-autobuild --watch src docs/sphinx_src/source docs/sphinx_src/build
```

　--watch引数にsrcという今回ソースファイルを入れるフォルダを指定している。それ以外は通常のコマンドと変わりない。この--watch引数を指定してやったことによって、srcフォルダ内のファイルが更新されたときに、自動でビルドが走り、srcフォルダ内で更新したdocstringが即座にドキュメントに反映されるということが叶っている。
 
　3.ビルドされたファイルの確認

 　　シンプルブラウザーを用いて確認をしている。

　　Ctrl + Shift + Pキーを入力し、その後Simple Browser: Showを選択し、URLに以下を入力する。

```
http://127.0.0.1:8000
```

　　ビルドが正しく行われていれば、docstringを元にしたSphinxのドキュメントが作成されている。

### :: Set up .gitignore to ignore unwanted files and directories
```
echo env/>>.gitignore
echo __pycache__/>>.gitignore
echo .pytest_cache/>>.gitignore
echo .vscode/>>.gitignore
echo *.pyc>>.gitignore
echo *.pyo>>.gitignore
echo *.egg-info/>>.gitignore
echo exe/>>.gitignore
echo data/>>.gitignore
echo docs/>>.gitignore
```
　ここで作成したプロジェクトファイルはGit管理をしているので、その設定を行っている。今回Gitに送るファイルはsrcフォルダの中身とtestsフォルダの中身のみであり、それ以外を除外している。

### それ以降の設定について
```
echo [pytest]>>pytest.ini
echo pythonpath = src>>pytest.ini

cd src
type nul > __init__.py
cd ..

cd tests
type nul > __init__.py
cd ..

```
#### pytest.ini
　pytestにおいて、ロジックを記したファイルがどこに有るかの明示的な指定。これがないと、testsフォルダのコードでsrcフォルダに書いたモジュールを読み込むことができず、不便である。

#### type nul > \_\_init__.py
　\_\_init__.pyという空ファイルを作成することで、testsフォルダからsrcフォルダが見れるようにといった事ができるようになる。


# まとめ
　・設計からテストまでvscodeで完結する環境を作成した。また、それを全自動で作成してくれるバッチファイルも作成した。
　・Sphinx autobuildで、ソースコードのdocstringを編集したときに自動でビルドが走り、成果物が出力できるような設定方法について解説した。

 :::note info
今回作成したバッチファイルそのものの権利関係について
MITライセンスにしておきます。
Copyright (c) 2023 Cycrube
Released under the MIT license
https://opensource.org/licenses/mit-license.php
:::

# 引用
以下のサイト、及びQiita記事を引用した。それぞれの著者に深い感謝を。
[1] Sphinx Sphinxの概要ページ https://www.sphinx-doc.org/ja/master/
[2] sphinx-quickstart sphinx-quickstartコマンドの説明ページ https://www.sphinx-doc.org/ja/master/man/sphinx-quickstart.html
[3] GoogleスタイルのPython Docstringの入門 https://qiita.com/11ohina017/items/118b3b42b612e527dc1d
[4] sphinx-autobuild 2021.3.14 sphinx-autobuildの概要ページ https://pypi.org/project/sphinx-autobuild/