OmniAICreator/Qiita-1.07M huggingface dataset:
VirtualboxのNATネットワークをVagrantから設定する

# 設定内容

忙しい人向けに最初にやったことを書きます。諸々は後ほど。
Vagranfileでmodifyvmを使って設定します。

```text:Vagrantfile
Vagrant.configure("2") do |config|
　(中略)
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--nic1", "natnetwork"]
    vb.customize ["modifyvm", :id, "--nat-network1", "NatNetwork"]
  end
　(中略)
end
```
Virtualboxのnic1の設定にNAT ネットワークを指定して、
そのNATネットワークはNatNetworkを使用する設定になります。


# はじめに
Virtualboxに対してVagrantを使って検証用の仮想サーバを色々立てたりしてると、
複数サーバ間の通信をやりたくなったり諸々の理由でNATネットワークを指定したくなりました。
Vagrantfileの書き方を調べてみるも、NATに関する記述はあっても、NATネットワークになると途端に見つからず…
調べては挫折し、挫折しては挫折しを繰り返していました。
今回再度何の気なしに調べてみたらすんなり解決できてしまい、ちょっと嬉しかったので久々に投稿します。

環境は下記です。

## Virtualbox

```
c:\> VBoxManage.exe --version
6.1.16r140961
```

## Vagrant

```
c:\> vagrant -v
Vagrant 2.2.14
```

## Windows

![SnapCrab_NoName_2021-2-2_20-5-27_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51498/c9fadaaf-1b9c-5c0c-e96b-40032139b728.png)

# 設定内容(再掲)と解説

```text:Vagrantfile
Vagrant.configure("2") do |config|
　(中略)
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--nic1", "natnetwork"]
    vb.customize ["modifyvm", :id, "--nat-network1", "NatNetwork"]
  end
　(中略)
end
```
肝は、

```
    vb.customize ["modifyvm", :id, "--nic1", "natnetwork"]
    vb.customize ["modifyvm", :id, "--nat-network1", "NatNetwork"]
```
です。
項目ごとに説明すると下記のような感じです。

* `vb.customize`はVBoxManage.exeを呼び出します
* `modifyvm`はVBoxManage.exeのオプションでVMイメージの設定を変更します(そのまま)
* `:id`はイメージIDを指定するのですが、ここはVagrantがよしなにやってくれます
* `--nic1`は1つ目のNICの設定をするという意味です
    * 後ろの数字は1-4まで設定でき(ると思い)ます
    * 調べていませんがGUIでは4つまでなのできっと他の数字を指定するとエラーになるのかなと…
* `natnetwork`はNATネットワークを指定します(そのまま)
    * ちなみに設定項目としては`none|null|nat|natnetwork|bridged|intnet|hostonly|generic`だけあります
    * GUIの設定項目と同じですね
* `--nat-network1`はNIC1に対して設定したNATネットワークのオプションでどのNATネットワークにするかを指定します
* `NatNetwork`は、事前に設定したNATネットワークを指定します
    * GUIで言う`ファイル->環境設定->ネットワーク`で表示されるNATネットワーク名です

# さいごに

結局のところ公式サイトに書いてありました。
日本語にこだわって探すと良くないですね。再認識しました。
それにしても日本語で書かれていなかったのはもしかして…

* 外に繋ぐならNAT + 内部ネットワークで良いから…?
* あまりNATネットワークって良くなかったりとかある…?

みたいなのがあるのでしょうか。
個人的にはポート周りがひと目で分かって良いので多用していますが…


# 参考にしたもの

* 公式サイト(何故これまでじっくり読まなかったのか…)
    * https://www.virtualbox.org/manual/ch08.html#vboxmanage-modifyvm
LPIC 101 オンライン受験記録(Pearson onVue)

# LPIC 101 オンライン受験記録(Pearson onVue)
LPICのオンライン受験情報が少なかったので(2021/02/02時点)、備忘を兼ねて公開記録する。
なお、当初は他のOnVue試験と異なる手順を踏むかと推測していたが、そんなことはなかったので、他の資格試験のOnVue試験体験記でも参考になる。
※注意事項: 必ず最新の公式情報をご確認し、本ページは信頼できない他人のメモ程度にご認識頂けますと幸いです。

## ID作成
LPIとピアソンVUE(PearsonVUE)のIDが必要なため作成する。
後述の通り、[学易さん](https://gakuyasu.byaku.jp/)のバウチャーを使用したため、バウチャーお届けメールにおまけで記載されている案内に従い、原則、ローマ字ベースで入力していく。
なお、緒事情により、名前はローマ字入力で事足りたので、特段気にしなかったが、ピアソンVUEではローカルの設定を漢字で記載できたので、身分証明書との一致は確認できると推測。(LPIの試験監督は英語のみで、どこまで確認されるかは未知数)

## 受験申し込み
ピアソンVUEのLPI用画面にログイン後、[試験を表示]を押下すると、101-500(オフライン試験)と並んで、101-500v(オンライン試験)が選択できる。わかりやすくて良い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/818500/85d5fc3e-47f5-f0bc-388d-1b84f7085b06.png)
選択を進めていくと、オフライン同様、日程を選択、支払いへ進むことになる。
支払い時、デフォルトでクレカ情報入力画面になるが、上部にてバウチャー使用を選択できる。学易さんの案内に従いバウチャーコードを入力し、かなり長い処理時間を経て予約が確定する。

なお、時間帯の選択肢は多く、かつ変動が激しい印象を受けた。
2/1の14時頃に確認した際、2/2は全体が丸々空いていたのに対し、17時頃になるとかなり歯抜けになっていた。
また、深夜や早朝の選択肢もあり、非常にありがたいが、誤って早朝の時間帯を選択しないようにしたい。

## 事前準備
#### 1. システムテスト(Perform a system test)
申込完了画面にてシステムテストを案内されるので、記載に従う。
Mac(ARM M1)での受験だったので、テスト用アプリの権限を変更する必要があったが、一度目のテスト時には操作がロックされていたため、権限を変更できなかった。
テスト画面が終了してから権限を変更し、もう一度システムテストの手続きを行い、権限に関するアラートが出ないことを確認した。
ただし、この時点でショートカットボタンが効かなかった(__E__nd(Eは下線付き)が表示されている画面でEキーを押しても何も反応しない)。  

#### 2. 部屋の環境確認(Find your testing space)
システムテスト時にプラウザなどを閉じることになるので、申し込み完了画面が二度と見られない罠があるが、メールでもLPI用の事前準備用のページが案内される。
事前準備ページには、システムテストの他、部屋の環境に関する注意事項と、身分証明書の準備について記載されている。
部屋の環境に関する注意事項は、最新版をご覧いただきたいが、2021/02/01時点では飲み物は許可されていた…が、スタッフに、手が届く場所には置かないよう、注意された…と思う(英語力不足で聞き取れず)。

#### 3. 身分証明書の準備(Get your ID ready)
顔写真、登録した名前が記載されている、国家機関が発行した証明書が必要となる。

## 当日
スクショ取りそこねたが、概ね一本道であった。事前にはわからなかったが、どうも他のOnVue試験と共通な気がする。

#### 1. チェックイン
試験開始時刻より25分ほど早めに、ピアソンVUEのメールの案内に従いサインイン。
時間の無駄かと思ったが、全然そんなことなく、予定開始時刻ちょうどくらいまで認証作業に費やすこととなった。
なお、アラートメールなどは来なかったので、すっぽかさないように注意すること。
また、システムテスト同様にIDが割り振られてアプリを起動することになるが、システムテスト時にダウンロードしたアプリをそのまま使用できた。

#### 2. スマートフォンによる撮影
アプリの案内に従い進むと、電話番号を国番号(日本+81、その後は080から入力した)から入力するよう指示される。(違う選択肢もあり)
スマートフォンへSMSを送信し、作業用のリンクへアクセスして、顔や身分証明書、試験環境を撮影するよう指示される。
自分のスマートフォンが古かったためか、ここで2件トラブルがあった。
1件目は、身分証明書撮影の際、ブラウザが黒一色で、カメラプレビューが機能しなかった。
画面遷移した際に一瞬映るのと、撮影ボタンを押下してプレビューできたため、なんとかそれっぽい写真を撮ってアップロードした。
2件目は、環境撮影の際、ネットが寸断されかけた。
特に対応せず、2分くらい待つと息を吹き返してアップロードが進んだ。

#### 3. テストアプリの起動と試験監督(人)による確認
スマートフォンによる作業が完了してから、PCの画面に戻ると、画面更新して先に進むことができた。
試験用アプリが起動し、試験監督と音声/文字チャットでつながる。自分の試験監督さんはインド辺りだったと思う。
当然英語でしかやりとりできないが、そもそも通信環境が悪く、あまり発言が聞き取れない。聞き取る能力もさしてないが…
自分が依頼された作業は以下のとおり。
 - 身分証明書の再確認(名前、有効期限)
 - 試験環境の撮影(ノーパソだったので、持ち上げてぐるっとする、机上も写す)
 - 机上の物の整理(身分証明書やティッシュをどかされた…確かにメモ書けちゃう。飲み物も、特にいらないかと思ってどけた)

#### 4. 試験開始
上記の確認が終わると、試験が始めるからしばし待つよう、指示されたと思う(正直7割は聞き取れなかった)。
最後に、なにか質問がないかも確認される。親切。
チャットだけの画面を前にしてぼーと待っていると、同意画面から試験が開始する。
コマンド入力の際に気づいたが、日本語入力が強制になっているのか、切り替えを忘れたためか、ひらがな入力の状態から切り替えができず、若干苦労した。

#### 5. 試験終了
全ての問題を解き終わると見直し画面に遷移し、それから試験終了を選択することができる。
終了を押したらすぐにスコアや分野毎の正答率が表示される。
その後アプリが終了し、メールでも結果の通知が来る。
🐳【すぐ開発を始めたい人向け】DockerをMacにインストールする手順🐳

# Docker Desktopのインストール（macOS）
この記事では、Dockerを使うことができるように、Docker Desktopのインストール方法を解説した記事です。対象のOSは**Mac**になります。

Windowsの方はインストール方法が異なりますので以下の記事をご覧ください。

- [🐳WindowsでDockerを始める手順🐳](https://qiita.com/techpit-jp/private/f4a1319a909dd508f372)
- [🐳Docker Toolboxのインストール🐳](https://qiita.com/techpit-jp/private/1fed1325bdbc62d216d3)

他にもプログラミング学習に役立つような情報を発信しています！[アカウントをフォロー](https://qiita.com/techpit-jp)してお待ちください！

## Docker Desktop for Macをダウンロード
[Docker公式サイト](https://www.docker.com/)にアクセスしてください。

「Get Started」ボタンをクリックしてください。

<img width="900" alt="スクリーンショット 2020-09-18 6 43 53" src="https://user-images.githubusercontent.com/25563739/93790586-2d9baa80-fc6e-11ea-8acc-6475181c3681.png">

「Download for Mac」ボタンをクリックしてください。

<img width="800" alt="スクリーンショット 2020-09-18 6 46 27" src="https://user-images.githubusercontent.com/25563739/93790687-499f4c00-fc6e-11ea-8c95-804e011ce9f3.png">

任意のディレクトリに保存してください。

<img width="890" alt="スクリーンショット 2020-09-18 6 53 31" src="https://user-images.githubusercontent.com/25563739/93790796-68054780-fc6e-11ea-8050-f8295d7da145.png">


## Docker Desktop for Macをインストール

ダウンロードが完了したら、`Docker.dmg`ファイルを実行してください。

以下のような画面が表示されるので、DockerアイコンをApplicationsディレクトリのアイコンへドラック&ドロップしてください。

![](https://i.gyazo.com/5701425273f0d6c9b574842e67cee80c.gif)


## Docker Desktop for Macを起動
Finderからアプリケーションディレクトリを開き、Dockerを実行してください。

<img width="817" alt="スクリーンショット 2020-09-22 0 45 47" src="https://user-images.githubusercontent.com/25563739/93790910-8703d980-fc6e-11ea-986f-58d61199baa6.png">

Macの画面右上部にDockerアイコンが表示されていれば、起動完了です。

<img width="506" alt="スクリーンショット 2020-09-22 0 49 48" src="https://user-images.githubusercontent.com/25563739/93791047-b0246a00-fc6e-11ea-865d-291c87b11065.png">

ダウンロードした`Docker.dmg`ファイルは削除しても構いません。

以上で、Docker Desktopのインストールは完了です。
AWS RDSのPostgresSQL DB インスタンスに接続・ローカルから移行

1. AWS RDSのDBインスタンスのページを開いてエンドポイントを確認

![スクリーンショット 2021-02-02 19.45.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637360/b16b10f1-9909-a41d-426b-e1ae2ee1c003.png)

2.ターミナルで以下を実行。

```
psql --host=<エンドポイント> --port=５４３２ --username=<DBインスタンスを作成したときのusername> --password --dbname=<DBインスタンスを作成したときに名付けたDB名>

```
3.パスワードの入力を求めれので、DBインスタンスを作成したときに指定したパスワードを入力すると接続完了

4.RDSインスタンスにデータが入っている場合は念のため、すべてのテーブルを削除

```sql
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
```

5.ローカルPostgresのバックアップファイルを作成。RDSのDBインスタンス接続をきり、ターミナルで以下を実行

```
pg_dump -U postgres -h localhost -p 5432 <DB名> -f <ダンプファイル名>
```

6.作成したダンプファイルをRDSのDBインスタンスにリストア

```
psql -U postgres -h <エンドポイント> -d <DBインスタンスを作成したときに名付けたDB名>
 -p 5432 -f <作成したダンプファイル名>
```
これで移行完了！
CodeBuildのプロビジョニングフェーズでPublic ECRが設定できる

# Public ECRが使えるようになった
[CodeBuildのプロビジョニングフェーズでdocker pullの制限を回避する](https://qiita.com/python_spameggs/items/4611f5bad3749ffc2e7e)
これを書いたときには設定できなかったが出来るようになっていた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27949/2447eb3f-c956-0447-f35d-3123e9223b1e.png)
適当に埋めましたがあとは更新するだけで使えるようになるはずです

## aws-cliで更新する
* 現在の設定を取得

```
aws codebuild batch-get-projects --names PROJECT_NAME > project_name.json
```

* environmentのimageを使いたいPublic ECRのパスに置き換える

```
"environment": {
    "image": "public.ecr.aws/aws-ec2/amazon-ec2-metadata-mock:v1.8.1",
       .
       .
       .
```

* 更新する

```
aws codebuild update-project --cli-input-json file://project_name.json
```

* これで完了です

# おわり
前の記事を書いた時にまだかなって思っていましたが忘れた頃に使えるようになっていました
これでSecret Managerを使わずに済むので設定が簡単になりました
axios.get()で"TypeError: Cannot use 'in' operator to search for 'validateStatus' in x"

#概要

`vuex`で`axios.get()`する際に以下のコードで実装したらタイトルのエラーにぶち当たったのでその解決策を起筆します。

```.vue
<script>
export default {
    props:{
        postId: String //postId = x;
    },
    mounted(){
        this.$store.dispatch('individual/getIndividual', this.postId);
    }
}
</script>
```
```.js
const actions = {
    getIndividual(context, data){
        axios.get('/api/individual',data).then((result)=>{
        //省略
        }).catch(error=>{
        //省略
        })
    }
};
```

#原因
`axios.get()`をする時には、第二引数に直接パラメータを記述するのではなく、送りたいパラメータを`params`として指定してあげる必要があります。

#解決策
```.js
const actions = {
    getIndividual(context, data){
        axios.get('/api/individual',data).then((result)=>{
        //省略
        }).catch(error=>{
        //省略
        })
    }
};
```
ではなく、

```.js
const actions = {
    getIndividual(context, data){
        axios.get('/api/individual',{
            params:{
                post_id: data
            }
        }).then((result)=>{
            //省略
        }).catch(error=>{
            //省略
        })
    }
};

```

#参考文献
[公式GitHub](https://github.com/axios/axios#example)
[axiosのパラメータ指定方法まとめ](https://qiita.com/taroc/items/f22f7dd5d6d5443c72a4)
【Python】len関数を使ってシート数を数える。

pythonを使用してExcelファイルの操作を勉強しています。
本日の気づき(復習)は、len関数に関してです。
pythonでExcelを操作するため、openpyxlというパッケージを使用しています。

「sheet1」「sheet2」「sheet3」という名前のシートを持つブックの
シート数を数えるとします。

### Worakbook.sheetnames属性
openpyxlには、残念ながらブックのシート数を取得する属性はないそうです。
そこで、Worakbook.sheetnames属性を使用します。

sheetnames属性は、ブックのシート名をリストで返します。

```python:例
print(wb.sheetnames) --> ['sheet1','sheet2','sheet3']
```
上記のように返します。
こちらに「len関数」を組み合わせます。

### len関数
len 関数は引数に指定したオブジェクトの長さや要素の数を取得するそうです。
len 関数の書式は次の通りです。

```python:len関数の書式
len(S)
```

引数には文字列やバイト列、リスト、タプル、辞書などのオブジェクトを指定できます。

```python:len関数の返す値
⓵len("Hello") --> 5

⓶len(["red", "blue", "green"]) --> 3

⓷len({"s":150, "m":160, "l":170, "xl":180}) --> 4
```
組み合わせると

```python
len(wb.sheetnames) --> 3
```
シート数を取得できました！

今回、len関数を調べていく中で、バイト列・タプルなど
勉強していく内容が増えてきました。
ひとつずつ調べてものにしていきたいですね！
【備忘録】react-reduxでオブジェクトのstateを更新する

#stateの構造

```js
state = {
  user: {
    name: string,
    address: string,
    phoneNumber: string
  },
  isPremiun: boolean
}
```

# reducerの記述

```js
initialState = {
  user: {
    name: "",
    address: "",
    phoneNumber: ""
  },
  isPremiun: false
}
const userReducer = (state = initialState, action) => {
  const { type, payload } = action;
  switch (type) {
    case user/updateProfile:
      return {...state, user: {...state.user, ...payload}};
    default:
      return state;
  }
}
```

このようにしておくと、userの情報を更新したいときにname, address, phoneNumberの情報全てを送信する必要がない。
{name: "hoge"}という情報をactionのpayloadに渡すとその部分だけ更新される。
STLINK-V3SETを使ってLチカを行ってみる

#あらすじ
以前に秋月で購入したSTLINK-V3SETが使わずじまいで部屋に転がっていたので，一念発起して使用することにしました．
また，STLINK-V3SETに関する日本語の記事がほとんど見つからなかったため，今後使用したい方の為にもCubeIDEを使ってのLチカ手順を記事としてまとめておくことにしました．
[STLINK-V3SET](https://www.st.com/ja/development-tools/stlink-v3set.html)
[秋月 購入ページ](https://akizukidenshi.com/catalog/g/gM-14361/)


# 開発環境
| OS | MCU |
|:-:|:-:|
|Ubuntu 18.04|STM32F303K8|

[使用したMCU](https://akizukidenshi.com/catalog/g/gI-10790/)


# STLink-V3SETについて
![図1. STLINK-V3SET](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320997/c52528fc-df02-f0c7-7b64-a67abbeda457.jpeg)
図1. STLINK-V3SET
(画像はSTMicroelectronics社のHPより抜粋)

STM8及びSTM32マイコン向けのデバッガ/プログラマであり，プログラムを書き込む際に使用します．
普段使用しているNucleoシリーズにはプログラムを書き込むためのSTLINKがボードに付随しているため
USB接続しバイナリファイルをD&Dすることでプログラムを書き込むことが出来ますが，
MCU（図2）単体の場合，別途プログラムを書き込む装置（STLINK）が必要となります．



# MCUとの接続
今回はSWDでマイコンと通信を行います．（JTAGは使用しません）
（SWD? JTAG? なにそれ美味しいの？って方は以下のサイトを参照すると良いかも）
http://rx.tokudenkairo.co.jp/cmsisdap/jtagswd.html

SWDはSWDIO, SWCLKの2本の通信線を使用しますので，MCUとSTLINK-V3SETのそれぞれのデータシートから対応するピンをまず探します．

#### STM32F303K8のピン
下記リンクからSTM32F303K8のデータシートを入手し，ピン割当を調査します．
[STM32F303K8 データシート](
https://www.st.com/ja/microcontrollers-microprocessors/stm32f303k8.html)

35ページ〜40ページにかけて「pin definitions」が記載してあります．今回使用するのは「LQF32」タイプのMCUなので，SWDで使用するピンは何処か探してみると...

![Screenshot from 2021-02-02 18-55-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320997/06014a8c-be8a-ae10-400e-10a921df5dd4.png)

ありました．
**SWDAT**(SWDIOと同じ意味)が**Pin24**，**SWCLK**が**Pin25**のようですね．
また，**VCCはPin1/Pin17**，**VSSはPin16/Pin32**にあることも確認できました．


#### STLINK-V3SETのピン
先程と同様に下記リンクからデータシートをDLして，SWDに必要なピンを探し出します．
[STLINK-V3SET データシート]
(https://www.st.com/ja/development-tools/stlink-v3set.html)


STLINK-V3SETには本体の他にもう一つ基板が付属し，この基板を装着することで様々な機能が拡張されるようになっています．
今回は，本体に付いている1.27mmピッチのピンヘッダに適合するジャンパピンを持っていなかったので基板を装着しCN6のピンヘッダとMCUをジャンパ線で接続させました．
（基板の接続方法はデータシートを参照のこと．）


前述したMCUとSTLINK-V3SETの対応するピン同士を結合させ，CUbeIDEからLチカのプログラムをSWDで書き込みます．

**このときの注意点として，3.3Vは別途用意する必要があります．
どうやらUSBから電源を取ってきてくれないようです．**
（データシートの7ページ目の下に「*The STLINK-V3SET product does not provide the power supply to the target application.*」と記載があります．
また，VCCピンの注意書きにも「*Input for STLINK-V3SET.*」とあるので，全てのピンは別途電源が必要なようです...どうせならUSBから電源を取れるようにして欲しかった）

# プログラムの作成・書き込み
CubeIDEの操作方法については下記の記事がとても丁寧に解説してくださっているのでここでは割愛します．
[@yoshihisa様 STM32入門 環境構築「CubeIDEのインストールとSTM32F446でLチカ」]
(https://qiita.com/yosihisa/items/136bcc09c466227303a2)


SWDで書き込んだ結果，無事にLチカを行うことが出来ました．
今回3.3Vは別のマイコン（F767ZI）から供給させています．

![Lチカ_STLINK.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320997/838298ed-5375-6a1b-c7da-8b1cf59796a8.jpeg)
Overleafを用いた論文のrebuttalの書き方

# はじめに

論文を投稿してreferee comment が帰ってきた場合、コメントに対応する場所を修正し、行番号と修正場所を反論として記載するが、修正によって行がずれるので管理が大変になる。また、修正場所も再度書き出すと、同じ文章をふたつ書かないといけないので修正が大変である。ここでは、論文のrebuttal時に便利なコマンドを紹介する。

# Reply to the referees

Refereeに対する返答部分には

-refereeのコメント
-それに対する返事
-修正したポイント（行番号："修正したテキスト"）

の３点を書き出す必要がある。また、修正した部分をハイライトするように求められる場合も多いが、最終稿ではハイライトを外す必要がある。

#パッケージ定義

冒頭のパッケージ定義部分に以下を追加する。ハイライトを外す場合はコマンドを再定義する。

```LaTeX
\usepackage{lineno}
\usepackage{soul}
\usepackage{framed} % to add frames around comments
%\renewcommand{\hl}{} %uncomment this to remove highlight
```

#本文中の修正
本文中の修正部分は以下のようにする。

```LaTeX
\linelabel{ApicalMovement}\newcommand{\ApicalMovement}{\hl{Most undifferentiated stem cells reside at the superficial side of the seminiferous tubule, where they produce daughter cells that gradually move to the deep (luminal) side as differentiation proceeds (Fig. \mbox{\ref{FigIntroduction}}a). }}\ApicalMovement
```

まず、修正する場所に名前をつける。この場合は「ApicalMovement」とする。

次に、業番号のラベルを指定する。\linelabel{ApicalMovement}は修正した場所のラベルを表す。

さらに、修正する文章をコマンドとして定義してしまう。

```LaTeX
\newcommand{\ApicalMovement}{\hl{Most undifferentiated stem cells reside at the superficial side of the seminiferous tubule, where they produce daughter cells that gradually move to the deep (luminal) side as differentiation proceeds (Fig. \mbox{\ref{FigIntroduction}}a). }}
```


は、文章をコマンドと指定定義している。\hlはハイライト表示を表す。また、この定義内で\ref{}等のコマンドを用いる場合は、\mbox{}で囲まないとエラーが出る。

![Highlight.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178269/6bfdeb66-3338-bda4-5262-fe7bfcafe5d0.jpeg)



#Reply to the referee

レフリーのコメントはフレームに入れて表示する（色を変えていた時期もあったが、同じ色の方が読みやすい）

```LaTeX
\begin{framed}
The paper could be improved for non specialist readers by a much clearer description of the process of spermatid differentiation, starting with the sequence of differentiation events.   
Sperm differentiation takes place in a radial direction. The spermatogonia are located at the wall of the tubule and the spermatids are formed in the centre. This basal to apical direction needs better explanation. 
The relationship between the differentiation cycle and the wave of spermatogenesis needs better explanation as does the origin of the cellular associations needs better explanation.
Some mechanistic insight could help. 
\end{framed}
```

![RefereCOmment.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178269/7175e9e6-18c5-9c18-eafc-ba1c59b09c87.jpeg)



レフリーへの返答は通常の本文として記述する。

```LaTeX
According to the referee's suggestion, we reorganized the introduction, added a 
description of the differentiation movement and pattern in the figure and text 
to increase the readability for nonspecialist readers.
```

修正点と行番号は最後に箇条書きで列記する。行番号は\lineref{ApicalMovement}、内容はコマンド\ ApicalMovementで表示される

```LaTeX
\begin{itemize}
    \item Line \lineref{ApicalMovement}: \ApicalMovement
\end{itemize}
```

![Reply.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178269/f0740b38-9962-8a61-5433-e7dff14dbba2.jpeg)
STSでGradleを使う

STSは標準でMavenは使えるようになっていますが、Gradleはインストールしないと使えません。そこで、今回はGradleをインストールしてプロジェクト作成まで行います。

# 環境
macOS Big Sur バージョン11.1
Spring Tool Suite 4 Version: 4.9.0.RELEASE

# Gradleインストール
1, Help→Install New Software
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/591fa972-8cf1-7f91-c844-01dee609dd55.png)
2, 「http\://download.eclipse.org/buildship/updates/e46/releases/2.x/」を入力し、該当バージョンをチェックし、Next>を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/2d44723e-ded9-d1d3-998f-7d5155d80d3a.png)
インストールの詳細を確認してNext>を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/bfcadde4-c8e0-a87c-875a-b6e0d48d2472.png)
ライセンスに同意してFinishを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/2f108f95-7622-d830-e527-e37dcbaa1009.png)
インストールが終了するとSTSの再起動を促すダイアログが表示されるので、Restart Nowを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/0d06e5f1-fda1-7772-e9d8-f6d69520a5dc.png)

# プロジェクト作成
再起動されたら、Pakage ExplorerからCreate new Spring Starter Projectを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/3e2970f8-3219-e3b4-e474-ad60818d0bf1.png)
以下のように入力し、Next>を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/2b33c7e5-485f-e076-b195-96e3eecb6a2e.png)
Spring Webのみ追加し、Next>を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/e3608fd7-c89d-f089-a5d8-8ba2f131cc04.png)
Finishを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/59c875fb-0daf-ca04-4426-f9b6f5ac06c8.png)

# 実行
Run→Run As→5 Spring Boot Appで実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/8172ba35-5ccf-044f-ff1f-2f043e9636d1.png)
コンソールに以下のように表示され、エラーが出なければ成功！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/eda1c694-04c3-f520-54b7-45f04b5a1392.png)

# 終わりに
次回からはコード書いて、何かしらのアプリを作ってみます！

# 参考書籍
SpringBoot2 プログラミング入門　著者：掌田 津耶乃
Pythonで16進数文字列を符号付き整数に変換する

# Pythonで16進数文字列を符号付き整数に変換する

組込み関数で符号なし整数に変換し、指定したビット数の最後のビットで符号を判断しています。

## コード

※ python初心者のため、例外処理がわかりません。あしからず。

```py:
# エラー用
class ExceededMaxValue(Exception):
    pass

## 16進数文字列を指定したビットの範囲で符号付き整数に変換する
def Hex2Dec(x:str,bit):
    dec = int(x, 16)
    
    # 指定したビットの範囲より大きい16進数文字列が入った場合に
    # エラーとする
    if dec >= (1 << bit):
        raise ExceededMaxValue
        # or
        # return 0
    
    # 指定したビット以上の値を捨てる
    dec = dec & ((1 << bit) -1)
    
    ## 指定したビットの範囲でマイナスかどうか
    if dec & (1 << (bit-1)) != 0:
        return ((1 << bit) - dec) * -1
    else:
        return dec 
```

---

## 簡略化したコード ※追記（2021/02/03）


コメントで@shiracamus 様から、上記のコードを簡略化してくださいました。
とてもすっきりして使いやすいです！ 普段使用する際は、こちらのコードをぜひ！

```python
def hex2dec(x: str, bit: int) -> str:
    """16進数文字列xをビット数bit内の符号付き整数に変換する"""
    dec = int(x, 16)
    if dec >> bit:
        raise ValueError
    return dec - (dec >> (bit - 1) << bit)


print(hex2dec("00", 8))
print(hex2dec("7f", 8))
print(hex2dec("80", 8))
print(hex2dec("ff", 8))
print(hex2dec("100", 8))
```

```:実行結果
0
127
-128
-1
Traceback (most recent call last):
  File "hex2dec.py", line 13, in <module>
    print(hex2dec("100", 8))
  File "hex2dec.py", line 5, in hex2dec
    raise ValueError
ValueError
```

# 追記(2022/03/28)

@fujitanozomu 様

編集リクエストを受信していたことに今気づきました、、、 遅くなってしまいすみませんでした。。。
Javascriptのif文条件判定におけるtrue/falseの結果について

#Javascriptの真偽判定

いつもifの条件判定で、
`true/false`の結果を忘れてしまうので、
メモとして残す目的で、徒然なるままに継ぎ足してゆく。

変数を表すものとしては、`var x` と置く

```javascript
var x = 下の表における値を代入
if(x){
    console.log(true);
} else {
    console.log(false);
}
```

※上記のif文のxに下記のValueを入れた時に、その結果をBoolean列に表示

| Value | Boolean | Description |
|:----------:|:------------:|:------------:|
| 1       | true        | Boolean プリミティブ |
| 0     | false      | Boolean プリミティブ |
| -0     | false      | Boolean プリミティブ |
| ''       | false        | Boolean プリミティブ |
| ""       | false        | Boolean プリミティブ |
| '0'       | true        | Boolean プリミティブ |
| 'aaa'         | true          | Boolean プリミティブ |
| 'false'         | true          | Boolean プリミティブ |
| null       | false       | Boolean プリミティブ |
| 'undefined'    | true     | Boolean プリミティブ |
| undefined    | false     | Boolean プリミティブ |
| NaN    | false     | Boolean プリミティブ |
| [].length    | false     | length == 0 |
| []    | true     | オブジェクト自体はあるからtrue |
| {}    | true     | オブジェクト自体はあるからtrue |
| Object.keys({}).length    | false     | length == 0 |
| new Boolean(false)    | true     | Boolean オブジェクト |
| Boolean(new Boolean(false))    | true     | Boolean オブジェクト |



###※注意点としては
・Booleanオブジェクトを論理値ではない値から論理値への変換に使うと想定しない挙動になる。
・代わりにBoolean関数を使ったり、二重否定演算子を使用したりすることで回避する。

```
var x = Boolean(val);     // 推奨
var x = !!(val);          // 推奨
var x = new Boolean(val); // 使わない
```

#階層の深いオブジェクトの真偽判定でハマるポイント
頭の中では以下のオブジェクトのように思い描いて、
「よし！zzzの値は、`aaa.xxx.yyy`と指定すれば、値を取り出せるぞー！」
と思ったとしても、

```javascript
{
  aaa: {
    xxx: {
      yyy: zzz
    }
  },
  bbb: ccc 
}
```
この場合に、実際のオブジェクトが持っている値自体が
以下のようになってしまっていると、
（xxxのプロパティ自体が存在していない状態）

```javascript
{
  aaa: undefined
  bbb: ccc
}
```
`xxx`がそもそも`undefined`または`null`なので、
`aaa.xxx.yyy` と指定しても、

`Cannot read property yyy of undefined`

と怒られてしまう。。。
ちゃんと`xxx`が定義されて、値を持っているかを確認することが大切。


ちなみに、`aaa`が`undefined`であることを判定したい場合は、

```javascript
if(typeof aaa == 'undefined'){
  // 処理内容
}
```
みたいな形で判定ができる。
【Automation Anywhere】Automation360「デバイスのログイン資格情報」の調べ方 - はじめてのAA

#はじめに

[Automation360](https://qiita.com/IQ_Bocchi/items/e5c95bd74cae45d1c586)でBotを実行するには、管理サーバーであるControl Roomに、デバイス（＝実行端末や開発端末）の資格情報を設定する必要があります。

この記事では、デバイスの資格情報の設定方法や調べ方を解説します。

#デバイスの資格情報を設定する画面

デバイスの資格情報を設定する画面は、バージョンによって違いがあります。

下記のいずれも、同じ情報を設定するための画面です。

＜最新バージョン（2021.12.28時点）＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/6732436f-01f9-e0d4-32cd-58ee8c485840.png)

＜ちょっと古いバージョンと、さらに古いバージョン＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/5c606c67-faaa-ed1b-b425-b4018d783186.png)

#何を入力すればいいの？

上記の①②には、それぞれ以下の情報を入力します。

| No.| 項目名 | 必須／任意 |　入力内容 　|
|:-----------:|:------------|:------------|:------------|
| ① | デバイスユーザー名 | 必須 | 基本的には、入力欄の右端にある更新マークをクリックすると、自動的に設定されます。<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/f9ddf40f-6ff4-df73-4c19-7b7f6c2fbbae.png)<br>上記のアイコンが表示されない場合や、クリックしても何も設定されない場合は、該当の端末の「コンピューター名&yen;ユーザー名」を入力します。<br>「コンピューター名&yen;ユーザー名」と言われてもなんだかわからない方は、このあと手順を解説していますので、そちらをご覧ください。|
| ② | デバイスのパスワード| 任意 | 開発端末や、Community Editionを利用する際には設定不要です。<br>設定が必要となるのは、該当の端末をRunnerとして使用する際に、ログオフした状態からリモート起動する必要がある場合だけです。 <br>設定する内容は、該当の端末のログインパスワード（＝PC自体にログインする際のパスワード）です。|

#端末の「コンピューター名&yen;ユーザー名」の調べ方

ユーザー名の欄に設定する「コンピューター名&yen;ユーザー名」は、以下の手順で調べることができます。

## 手順１：コマンドプロンプトを起動する

Windowsのメニュー検索に「cmd」と入力し、コマンドプロンプトを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/662fd431-6d16-e2d4-7e95-9421d9fe2ca5.png)

## 手順２：whoamiと入力してEnter

出てきた画面に「whoami」と入力してEnterキーを押下します。　
（whoami = Who am I ? のことです。入力する際はスペースも?もなしで、ただ whoami と入力してください。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/9450a22a-640f-24f7-4e90-7fbc48f794bd.png)

## 手順３：表示された文字列をコピー

上記の結果、表示される文字列が「コンピューター名&yen;ユーザー名」です。
これをコピーし、Automation360のユーザー名の入力欄に貼り付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/bc5670b7-9e21-c994-6861-b917ef3c5f28.png)

なお、コンピューター名とユーザー名の間の区切りは、コマンドプロンプト上は「&yen;（円マーク）」で表示されていると思いますが、Automation360にコピペすると「\（バックスラッシュ）」に変わっているかもしれません。

これは、コマンドプロンプトとブラウザのフォントの違いにより起こるものなので、問題ありません。

設定の手順は以上です。

#デバイスの資格情報は何のために聞かれるのか？

Automation AnywhereのRPAはサーバー型であり、開発端末や実行端末で行われたすべての操作は、中央の管理サーバーであるControl Room によって監視・記録されます。

Control Roomに接続されていない状態（＝Control Room が動きを監視できない状態）では、Botを作ることも、Botが動くことも許されません。

上記のようなサーバーと端末の接続関係を管理するために、デバイスの情報をControl Room に登録しておく必要があります。

PCのログインパスワードは、端末をログオフした状態からBotを無人実行する際に必要になります。

Community Editionでは、上記のような無人実行を行うことはできないため、パスワードの入力も不要になっています。

#最後に

この記事は、「はじめてのAA」シリーズからリンクされています。

Automation Anywhere を初めて使う方は、ぜひ以下のリンクもチェックしてみてください。

https://qiita.com/IQ_Bocchi/items/8d28f12256037b5f9058
ラズパイ初心者がペットの監視カメラを作ってみた①～セットアップ編～

## 概要
ラズパイ4を使って監視カメラを作成、動体検知を行い、動くものがあった場合、LINEに通知するようにする。今回は初回で、ラズパイのセットアップ編です。

### 用意したもの
・[LABISTS Raspberry Pi 4 4B-64GB スターターキット](https://www.amazon.co.jp/gp/product/B082VVBKRP/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
　（Raspberry Pi本体、SDカード64G、ケース、3A Type-C スイッチ付電源、MicroHDMI-to-HDMIケーブルライン、ヒートシンク、冷却ファン）
・[カメラモジュール](https://www.amazon.co.jp/dp/B07W6NK7TW/ref=cm_sw_r_tw_dp_GCTHVQ1RWW18N53017QK)
・ディスプレイ
・USB キーボード
・USB マウス

#### 1. ラズパイセットアップ

①ケースがあれば、ケースに本体を固定する。
（少し硬い場合があるため、カチっと音がなるまで押し込む）
②冷却ファン、ヒートシンクを取り付ける。
③USBポートに、キーボードとマウスを接続する。
![ラズパイ4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004263/142e9931-987f-4ea1-5432-bd4e9301997b.jpeg)
④裏側のSDカードの入り口にSDカードをセットする。
![ラズパイ４裏.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004263/d871bbf9-5e2a-13d3-3c6a-2271227e9aab.jpeg)

⑤Micro HDMIにケーブルを接続して、ディスプレイと接続。
⑥カメラモジュールを取り付ける。
　黒い部分を少し持ち上げて、カメラモジュールの青いテープの部分を取り付けたあと、
　黒い部分を下に押し下げて固定する。
![camera.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004263/b9353686-c5b4-d4db-17a8-47859b555257.jpeg)
ケースの上の部分にカメラを固定する。
![camera_case.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004263/d11cbea6-c762-3caf-3bc4-5446e2c9f392.jpeg)
カメラのレンズがのぞくように、ケースを閉める。
![IMG_0157.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004263/33b79f45-a1d9-0ac1-0b53-ce70b91adfcd.jpeg)


#### 2. OSのインストール
ラズベリーパイにはOSをインストールする必要があり、SDカードにラズベリーパイ専用のOSとして、ラズベリーパイ財団が提供しているRaspbianをインストールします。
最新のRaspbianは、[公式ページ](https://www.raspberrypi.org/software/)からダウンロードできます。以前はNOOBSというファイルからインストールするのが一般的でしたが、2020年3月に「Raspberry Pi Imager」がリリースされ、こちらからダウンロードするのが一般的なようです。
今回はこちらのファイルがプレインストールされたSDカードを使用しました。


RaspberryPiを起動して、ディスプレイを起動し、以下のような画面から、一番上のRaspberry Pi OSを選び、セットアップします。（少し時間がかかりました）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004263/0e6d93b1-1190-3beb-5519-b61aa7c1e899.png)

セットアップが終わると、使用する言語、Wifiの設定やデフォルトユーザ(pi)パスワードの設定などを行う画面が表示されるため、入力します。（piのデフォルトパスワードは「raspberry」です。）

すべてのセットアップが終わると、以下のようなディスクトップ画面が表示さされば終わりです。
![2021-02-02-185319_1024x768_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004263/19fc9f6e-b519-f64a-6b85-a6ff73c7e4bd.png)

次は、Raspberry Piでの開発にあたりVNCでのデスクトップ、SSHでのリモート接続やVisual Studio Codeのインストールなどを行い、さらに開発環境を整えていきたいと思います。
Pythonの組み込みモジュールの効果的な使い方（2）【Effective Python】

# はじめに

Twitterで一時期流行していた 100 Days Of Code なるものを先日知りました。本記事は、初学者である私が100日の学習を通してどの程度成長できるか記録を残すこと、アウトプットすることを目的とします。誤っている点、読みにくい点多々あると思います。ご指摘いただけると幸いです！

# 今回学習する教材

- [Effective Python](https://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%94%B9%E8%89%AF%E3%81%99%E3%82%8B59%E9%A0%85%E7%9B%AE-Brett-Slatkin/dp/4873117569/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Effective+python&qid=1609408832&sr=8-3)

    - 8章構成
    - 本章216ページ

- 第6章：組み込みモジュール

## ローカルクロックにはtimeではなくdatetimeを使う

Pythonは、組み込みモジュールのtimeとdatetimeという2種類の方法で、タイムゾーンの変換を行うことができます。
しかし、timeを使う方法ではひどいエラーが起きる危険性があります。
具体的には、timeで複数のローカルタイムを見ようとすると、プログラムが動作しません。
そのため、基本的にはdatetimeを使うべきで、どうしてもtimeを使わなければならない場合は、UTCとホストコンピュータのローカル時間との間の変換にのみ使うべきなようです。
また、datetimeでUTCの他のタイムゾーンを見たい場合は、pytzモジュールを使うことで解決できるようです。

## 組み込みアルゴリズムとデータ構造を使う

対象課題に最適なアルゴリズムとデータ構造を使うことで、高速化しましょうというお話です。
Python標準ライブラリには多くのアルゴリズムとデータ構造が組み込まれているので、その一部を見ていきます。

### 両端キュー (Double-ended Queue)

collectionsモジュールのdequeクラスは、両端キューです。
先頭または、末尾への要素追加を定数時間で実行するため、先入れ先だし（FIFO）キューに理想的です。
listで同様の実装する場合、リストの終端に要素を追加したり削除するのは定数時間ですが、先頭に要素を追加したり削除するのは線形時間（要素数が多くなるほど時間がかかる）です。
そのため、listよりcollectionsモジュールのdequeの方が高速です。

```python
from collections import deque

fifo = deque()
fifo.append(1)
print('Before:', fifo)
# Before: deque([1])
x = fifo.popleft()
print('After:', fifo)
# After: deque([])
```

### 順序つき辞書 (Ordered Dictionary)

標準辞書は、順序の保証をしていません。つまり、同じキーと値とがdictで順に調べていくと異なる順番で出てくることがあるということです。
CollectionsモジュールのOrderedDictクラスは、キーの挿入順を記録する辞書です。
OrderedDictのキーについて順に反復処理をするときには、振る舞いを予想できるため、テストとデバッグを大幅に単純化することができるようです。

### デフォルト辞書 (Default Dictionary)

標準の辞書では、キーの出現回数を数えるという単純な作業でも、面倒な処理を書く必要があります。

```python
stats = {}
keys = [
    'a',
    'a',
    'b',
    'c',
    'a'
]
print(keys)
for key in keys:
    if key not in stats:
        stats[key] = 0
    stats[key] += 1
print(stats)
# {'a': 3, 'b': 1, 'c': 1}
```

collectionsモジュールのdefaultdictクラスは、キーが存在しないときにデフォルト値を自動的に格納することによって、この処理を単純化します。

```python
from collections import defaultdict

stats = defaultdict(int)
for key in keys:
    stats[key] += 1
print(stats)
# defaultdict(<class 'int'>, {'a': 3, 'b': 1, 'c': 1})
```

### ヒープキュー (Heap Queue)

ヒープは、優先度つきキューを保持するのに役立つデータ構造です。
heapqモジュールは、heappush, heappop, nsmallestのような関数で、標準list型にヒープを作成します。

要素は常に最小数から削除されます。

```python
from heapq import heappush, heappop, nsmallest

a = []
heappush(a, 15)
heappush(a, 3)
heappush(a, 3)
heappush(a, 4)
print('最小値：',a[0])      # ヒープの0番目の要素は常に最小値
print(heappop(a), heappop(a), heappop(a), heappop(a))
```

実行結果

```result
最小値： 3
3 3 4 15     # 要素の小さいものからpopされる
```

### 二分法 (Bisection)

listの要素を探すために、indexメソッドを呼び出すと、リストの長さに比例して時間がかかります。
これに対して、bisectモジュールのbisect_leftのような関数は、ソートされた要素のシーケンスに対して、効率的な二分探索をします。

```python
from bisect import bisect_left
from time import time

start = time()
x = list(range(10**7))
i = x.index(9999999)
end = time()
print('listの実行時間:', end - start)

start = time()
i = bisect_left(x, 9999999)
end = time()
print('bisect_leftの実行時間', end - start)
```

実行結果

```result
listの実行時間: 0.4592776298522949
bisect_leftの実行時間 0.0
```
npmを使って、バージョン指定してパッケージをインストールする方法

## 本記事の対象者
「npmを使ってパッケージなどをインストールする際に、バージョンを指定したい」

そんな方に向けてこの記事を書いています。

## 結論
インストールしたいパッケージ名の後ろに「＠」をつけた後に、バージョンを記載することで、バージョンを指定できます。
以下は例です。

```
$ npm i --save-dev jest@26.6.0      
```
STM32G031J6M6のボードの作り方(STM32G031)


シリーズはSTM32G031でパッケージはSTM32G031J6で8P

部品(全て秋月で購入)
STM32G031J6M6->I-15688
基板->P-08242
[P1,P2]1列ソケット2個->C-10298
[C1]コンデンサー0.1uF->P-07935
[R1,R2,R3,R4,R5]カーボン抵抗0Ω->R-16000
[R6]カーボン抵抗470Ω->R-16471

作り方
1.STM32L010F4P6を基板に半田付けする。
導通チェックとショートのチェックをテスターで行う。
2.0Ωの抵抗R1を取り付ける。
3.470Ωの抵抗R2を取り付ける。
4.電源用パスコンC1を取り付ける。
5.1列ソケットP1を位置4aに取り付ける
6.1列ソケットP2を位置4lに取り付ける

![stm32_oled_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/64a31452-7e46-700e-f620-927a071eb64a.jpeg)

![stm32_oled_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/13a6b4ae-55c4-4055-130f-0c85df022918.jpeg)

![7seg_b_g031_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/9def7e28-840e-d879-2b84-5a3910cfa726.jpeg)

7セグメントを挿して遊べるよ
[M-12642]　赤色７セグメントＬＥＤシリアルドライバモジュール　完成品

STM32G031と7セグで3分タイマー(STM32G031J6M6)
https://qiita.com/caa45040/items/b923ae7e9f54126123a6
Pandasでカラム名がTupleになってしまうというバグ？を踏み抜いた件

pandas使っていて奇妙な挙動を踏み抜いたので、その備忘録。
この状況になると、カラム名がstringではなくなぜかTupleになってしまいます。
pandas力が低いのでバグなのか、仕方ない挙動なのかは不明です。

## 今回踏み抜いた挙動

空のDataFrameに対してpivotをかけて、その結果のDataFrameにインデクサーアクセスで新しいカラムを追加するとColumnがTupleとして追加される


## 通常の挙動

```python
import pandas as pd

empty_df = pd.DataFrame()
print("Plain1:", empty_df)
"""
ただの空のDataFrame
Plain1: Empty DataFrame
Columns: []
Index: []
"""
empty_df["new_column"] = 1
print("Plain2:",empty_df)
"""
# Printed
Plain2: Empty DataFrame
Columns: [new_column] # <- ちゃんとstring
Index: []
"""
```

## 今回踏み抜いたバグ？挙動

```python
import pandas as pd

empty_df = pd.DataFrame(columns=["id","key"])
empty_df["value"] = 1 # ただのemptyなdfだと、pivotする時に例外が発生。これをすると何故かpivotが可能に
print("Pivot1:", empty_df)
"""
Pivot1: Empty DataFrame
Columns: [id, key, value]
Index: []
"""

pivot = pd.pivot_table(empty_df, index="id", columns="key", values="value")
print("Pivot1:", pivot)
"""
# ただの空のDataFrame
Pivot2: Empty DataFrame
Columns: []
Index: []
"""

pivot["new_column"] = 1
print("Pivot3:",pivot)
"""
# Printed
Pivot3: Empty DataFrame
Columns: [(new_column, )] # <- カラム名がなぜかTuple
Index: []
"""
```
ビジュアルエディタで文頭のスペースが消える現象を回避

WordPress旧エディタのテキストエディタとビジュアルエディタを行き来していると、文頭の全角スペースが自動整形処理により除去される。

これを回避する方法を調べると、プラグイン[TinyMCE Advanced](https://ja.wordpress.org/plugins/tinymce-advanced/)を使う（≒wpautopを無効化する）方法がよく出てくるが、この場合、自動整形全体が無効化されるため、例えば、テキストエディタに本来は表示されないpタグやbrタグが表示されることになる。

文頭にインデントを付けるだけであればCSSで対処すべきだが、どうしても自動整形処理で対応したい場合の方法を紹介する。

#解決法

以下、WordPressのバージョン4.9.16でのみ動作確認している。

```php:functions.php
<?php
function editor_keep_space() {
	wp_enqueue_script('editor_keep_space_script', get_template_directory_uri() . '/js/editor_keep_space.js');
}
add_action('admin_head-post-new.php', 'editor_keep_space');
add_action('admin_head-post.php', 'editor_keep_space');
```

functions.phpでは、記事編集時にeditor_keep_space.jsが読み込まれるよう設定する。

```js:editor_keep_space.js
(function($){
    if($) {
        $('body').on('beforePreWpautop', function(_, obj) {
            if(!obj || !obj.data) {
                return;
            }
            var html = obj.data;

            // 属性等無しのpタグ直後の空白を保持
            html = html.replace( /<p>(\s+)/gi, '<p><pre#>$1</pre#>' );

            obj.data = html;
        })

        $('body').on('afterPreWpautop', function(_, obj) {
            if(!obj || !obj.data) {
                return;
            }
            var html = obj.data;

            // beforePreWpautopで保持した空白保護用のタグを除去
            html = html.replace( /<pre#>(\s+)<\/pre#>/gi, '$1' );

            obj.data = html;
        })
    }
})(window.jQuery);
```

editor_keep_space.jsは、wp-admin/js/editor.jsで定義される関数wp.editor.removepにおいてタグ除去の前後にトリガーされるイベントを使い、文頭のスペースが除去対象とならないよう退避させるものである。

#あとがき
文頭のスペースに限らず、テキストエディタとビジュアルエディタを行き来する際の整形を部分的に無効化したい場合は、同様の手段が有効と思われる。
Ruby on Rails　CSSファイル連携

#Ruby on Rails　CSSファイル連携方法は？

結論、特別何かを書き足さなければ行けないということはありません。
なぜかというと、Ruby on Railsでアプリを作成した際に自動で連携するための記述もされているからです！

##該当箇所

```app/views/layouts/application.html
<html>
  <head>
    <title>Pictweet</title>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>

   <!--↑ここの記述 -->

    <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
   
  </head>

```

上記で、app/assets/stylesheets/application.cssファイルを読み込むような記述があります。


では、application.cssファイルの中を見に行きましょう。

```app/assets/stylesheets/application.css
/*省略*/

 *= require_tree .
 *= require_self
 */


```

この部分の記述で、app/assets/stylesheets以下にあるファイルを、application.cssファイルが読み込んでまとめて反映させてくれるような設定になっています。


上記のような理由から、特にこちらで連携させるための記述をしなくても、
app/assets/stylesheets配下にcssファイルを作成することで反映させることができます！
Understand im2col

# What is im2col
im2col is an important function used in CNN, Convolutional Neural Networks, which transforms 4 dimensional images data to 2 dimensional numpy array. An image has a height, width and channel dimension (usually 3 channels for RGB colors). The last dimension is the number of images that is fed into CNN model. So usually you have input data that has a shape of (N,C,H,W), where N is number of images in the batch, C is number of channels (such as R,G,B), H is the height of the image in pixels, W is the width of the image.
im2col transforms this data to 2 dimensional format. Specifically it will convert it to (N*OH*OW,C*FH*FW) shape, where OH and OW are the resulting Output Height and Output Width after applying filter to the image, FH and FW are filter Height and Width respectively.

# im2col code

We provide im2col code in below. Essentially this function takes all (C,FH,FW) cubes to which the filter is applied and transforms them into horizontal vector. Below figure helps visualizing this process
![im2col_figure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401639/399ad37f-772c-f985-d770-442dde085f59.png)

```python
def im2col(input_data,fh,fw,stride=1,pad=0):
    # first we apply padding to the input data
    img=np.pad(input_data,[(0,0),(0,0),(pad,pad),(pad,pad)],'constant')
    N,C,H,W=img.shape
    OH = (H+2*pad-fh)//stride+1
    OW = (W+2*pad-fw)//stride+1
    col = np.zeros((N,C,fh,fw,OH,OW))
    for y in range(fh):
        y_max = y + OH * stride
        for x in range(fw):
            x_max = x + OW * stride
            col[:,:,y,x,:,:] = img[:,:,y:y_max:stride,x:x_max:stride]
    col = col.transpose(0,4,5,1,2,3).reshape(N*OH*OW,-1)
    return col
```

The only part that took me long time to understand was why were we jumping per stride. And after conducting below kind of experiment as shown in the figure, I finally understood that the trick was with transpose.
![convolution_transpose_explanation.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401639/e0f42e95-5c3a-6be7-15ab-490517e10f49.jpeg)
Apache 2.4.37でバーチャルホストがSSLで繋がらなかった話

### 何も役に立たない自己紹介
初めまして、ウェブ開発頑張りたいけどどうせやらない系デベロッパー（笑）のReisan03です。
#何があったのよあーた
バーチャルホストを設定しても何故か繋がりませんでした。解決したので備忘録を。

#結局何が原因だったのよあーた
443ポートのVirtualHostを設定してなかったのが原因でした。
```<VirtualHost *:443>```って入れたらちゃんと動きました。
#何を使ってるのよあーた
<dl>
<dt>Apache</dt>
<dd>2.4.37 CentOS</dd>
CentOS 8 Streamかなにか使ってます....(もう思い出したくない)
#詳しく聞かせなさいよあーた
DocumentRootは`/var/www/html`
何故か繋がらなかった`hoge.marumaru.dev`は`/var/www/html/hoge/`に配置していると仮定します。

もともと、`/etc/httpd/conf.d/hoge.conf`には以下の内容が書いてありました。

```
<VirtualHost *:80>
DocumentRoot "/var/www/html/hoge"
ServerName hoge.marumaru.dev

<Directory "/var/www/html/hoge">
Require all granted
AllowOverride all
Options SymLinksIfOwnerMatch FollowSymLinks MultiViews
</Directory>
</VirtualHost>
```

よく考えたら一発で何が原因かはわかりますよね。
`<VirtualHost *:443>`が居ないんですよね...
これだとhttpsに強制移動する私の`hoge.marumaru.dev`にはアクセスできません...(悲しい)

ということで以下の内容を追加してみました。

```
<VirtualHost *:443>
DocumentRoot "/var/www/html/hoge"
ServerName hoge.marumaru.dev
<Directory "/var/www/html/hoge">
Require all granted
AllowOverride all
Options SymLinksIfOwnerMatch FollowSymLinks MultiViews
</Directory>
SSLEngine On
SSLProtocol all -SSLv2

SSLCertificateFile [Key Location]
SSLCertificateKeyFile [Key Location]
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
```

追記して保存して
`systemctl restart httpd.service`
で完成です。やったね。終わり。
DialogFragmentを角丸にした部分に背景色が残ってしまうときの対処法

毎回これにハマります。。

角丸にする一般的な方法としては

```corner_radius.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid
                    android:color="@color/colorBackground"
                    />
            <corners
                    android:radius="16dp"
                    />
        </shape>
    </item>
</selector>
```

このdrawableをbackgroundに指定すると角丸になる、というのは定石かと思います。
しかし、DialogFragmentに限ってこれがうまくいかず色が残ってしまう


↓問題となったコードです。

```kotlin
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        super.onCreateDialog(savedInstanceState)


        val dialog = AlertDialog.Builder(requireContext()).also {
            it.setView(R.layout.fragment_some_dialog)
        }
        return dialog.create()
    }
```

ちなみにこれは純粋に背景色を透過させれば直るのですが、xml側で指定してもうまくいかないんですよね。
AlertDialogを使うのをやめてDialogを使って、背景色を透明に指定したらうまくいきました。

```kotlin
   override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        super.onCreateDialog(savedInstanceState)

        return Dialog(requireContext()).also {
            it.setContentView(R.layout.fragment_test_call_dialog)
            it.window?.setBackgroundDrawableResource(R.color.zs_color_transparent)
        }
    }
```



# 参考:
https://www.it-swarm.jp.net/ja/android/android%E3%83%80%E3%82%A4%E3%82%A2%E3%83%AD%E3%82%B0%E8%A7%92%E3%81%AE%E4%B8%B8%E3%81%BF%E3%81%A8%E9%80%8F%E6%98%8E%E5%BA%A6/1073609326/
Cloud Storageにアップされたファイルを検知してCloud Functionsを実行

# AWSのメッセージキューをGCPで
Google Cloud Storageにアップロードされたファイルを検知して作業する案件が舞い込んできました。
AWSで言うところのメッセージキューのような仕組みをGCPでやるようなイメージですね。

# 調査に次ぐ調査
調べると、トピックがどうのサブスクリプションがどうの、コマンドを叩いて、権限が必要で、と渋川剛気であれば眼前に火の海でも見えそうな状況。

しかし、さらに調べてみると、Cloud FunctionsのトリガーでCloud Storageを選べば、コンソール上で比較的簡単に設定できたので、ここに記します。

# やり方
まずはメニューのCloud Functionsから「関数の作成」を選択します。
関数名とリージョンは任意で、トリガーのタイプに「Cloud Storage」を指定します。

![2021-02-02_17h45_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140574/e89bf7ae-e58e-ba4d-4685-a4d739b86230.png)

Event typeに「ファイナライズ/作成」を選び、バケットを指定して保存後、「次へ」を押すと、Cloud Functionsが作成されます。
後は、ランタイムで言語を選んで、実際の関数を作成するだけです。

![2021-02-02_17h54_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140574/b42a624f-bd20-2211-e310-9142612f172c.png)

スタン値の高いGO言語(今日もpanic!)使いの私は「Go 1.13」を選択して、実装に励んでいきます。

簡単そうに見えますが、内部ではトピックでプールして、サブスクリプションに回してみたいなことはやっているみたいです。

現場からは以上です。
CloudBuildで特定のディレクトリをcacheして高速化する

GCPのCI/CDサービスであるCloudBuildで、特定のディレクトリをCacheして高速化する方法です。

node_modulesのcacheを例として説明しますが、他の言語でも何でもいけるはずです。

[Cloud Build: サーバーレス CI / CD プラットフォーム  \|  Google Cloud](https://cloud.google.com/cloud-build?hl=ja)


# CloudBuildでの高速化方法

公式ドキュメントでいくつか紹介されています。

[ビルドを高速化する際のおすすめの方法  \|  Cloud Build のドキュメント  \|  Google Cloud](https://cloud.google.com/cloud-build/docs/speeding-up-builds?hl=ja)

今回は、「Google Cloud Storage でのディレクトリのキャッシュ」についての説明です。


# 対象のプロジェクト

javascriptでの静的ページなプロジェクトを想定して説明します。
reactやvueでのSPAなイメージです。


```yml:特にcahcheしない素のcloudbuild.yaml
steps:
  - name: node
    entrypoint: npm
    args: ['install']
    dir: app

  - id: 'generate'
    name: 'node'
    args: ['npm', 'run', 'generate']
    dir: app

  # deploy（省略）

```
使用しているライブラリが多いと、`npm install`（あるいは`yarn install`）にかなり時間がかかる場合があります。
そこで、`node_modules` ディレクトリをcacheして高速化します。

appディレクトリ配下に`node_modules`が作成されるものとします。


# cacheの設定

## 事前準備

cacheファイルを保存しておくCloud Storageのbucketを作成しておきます。
ここでは`cloud-build-cache` という名前で作った事にします。


## cloudbuild.yamlの例


```yml:node_modulesのcahcheをしたcloudbuild.yaml

steps:
  # cacheファイルを取得
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://cloud-build-cache/cache.tar.gz', 'app/cache.tar.gz']
  # cacheファイルを解凍
  - name: bash
    args: ['tar', 'xzf', 'app/cache.tar.gz']

  - name: node
    entrypoint: npm
    args: ['install']
    dir: app

  - id: 'generate'
    name: 'node'
    args: ['npm', 'run', 'generate']
    dir: app

  # deploy（省略）

  # zip化
  - name: bash
    id: 'archive node_modules'
    args: ['tar', 'czf', 'cache.tar.gz', 'app/node_modules']
    waitFor: [ 'generate' ]
  # upload
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'cache.tar.gz', 'gs://cloud-build-cache/cache.tar.gz',]
    waitFor: [ 'archive node_modules' ]

```


## 解説

まず、CloudStorageを保存するファイルは、対象ディレクトリをzip化したファイルにしています。

他の選択肢としては、

- zip化せずにcpコマンドでディレクトリ毎コピー
- rsyncで差分コピー

が考えられますが、node_modulesはファイル数がかなり多くなりがちで、1ファイルずつの対応はかなり時間がかかる可能性があります。（私の手元の環境では5万ファイルが対象で、いつまでたってもアップロードが終わりませんでした）


### cacheファイルを取得とupload

```yaml
  # cacheファイルを取得
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://cloud-build-cache/cache.tar.gz', 'app/cache.tar.gz']

  # upload
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'cache.tar.gz', 'gs://cloud-build-cache/cache.tar.gz',]
    waitFor: [ 'archive node_modules' ]
```

CloudBuildでは、gsutilというCloudStorageを扱うコマンドが簡単に使えるようになっています。

今回使っているのは`cp`コマンドで、`ローカル（今回だとCloudBuild上のディレクトリ） ⇔ CloudStorage` のファイルのやり取りをする事ができます。

[cp \- Copy files and objects  \|  Cloud Storage  \|  Google Cloud](https://cloud.google.com/storage/docs/gsutil/commands/cp)

### 圧縮と解凍

```yaml
  # cacheファイルを解凍
  - name: bash
    args: ['tar', 'xzf', 'app/cache.tar.gz']

  # zip化
  - name: bash
    id: 'archive node_modules'
    args: ['tar', 'czf', 'cache.tar.gz', 'app/node_modules']
    waitFor: [ 'generate' ]
```
 
普通のlinuxコマンドです。

[tarコマンド、gzipコマンドの使い方 \- Qiita](https://qiita.com/sympe/items/13819ebe57a46090f064)



# 結果

プロジェクトの構成によって大きく変わると思いますが、私の環境だと

- 対応前 -> 10分ほど
- 対応後（cacheが効いている場合） -> 6分ほど

に高速化する事ができました。たかが4分、されど4分。

ライブラリのインストールに時間がかかっている場合は、検討する価値はありそうです。
プロフィール画面の作成【プログラミング日記~ポートフォリオ⑤~】#6

#自己紹介画面を作ろう
今回はワイヤーフレームの2枚目に当たる自己紹介の部分を作っていきます:v:![スライド2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043307/1e294809-c417-1828-7cbe-201f98a82891.jpeg)

```html:index.html
<div class="main">
      <div class="container first">  
         <h2 id="profile" class="section-title">自己紹介</h2>
        <div class="profile">
            <img src="image/profile.jpg" height="250px" width="250px">
            <ul>
              <li>名前:ぱぱぱぺ</li>
              <li>出身:埼玉県***市</li>
              <li>趣味:大相撲観戦</li>
              <li class="message">ひとこと:<br>プログラミング歴は浅いですが、<br>コミュニケーションを大切に迅速丁寧な仕事を心がけます！</li>
            </ul>
            </div>
</div>
```

```css:style.css
/* 共通 */
.container{
  height: 100vh;
  padding: 80px 50px 0 50px;
  text-align: center;
}
.section-title{
  padding-top: 130px;
  font-size: 3rem;
}
/* 自己紹介 */
.first{
  background-color:rgb(239, 243, 239, 0.959);
}
.profile{
  width: 80%;
  padding: 0 300px;
}
.profile img{
  border: 5px solid black;
  border-radius: 50%;
  float: left;
}
.profile ul{
  float: left;
}
.profile li{
 line-height: 60px; 
 text-align: left;
}
.profile .message{
  line-height: 36px;
}

```


###工夫したこと、苦労したこと
#####html
①共通の部分にcontainerとsection-titleを追加したことでコンテンツ同士の統一感が出るはず、、、

#####css
①ヘッダーのlistから飛んできたときにいい感じの位置になるように調整した
②一言だけ別にclass付けして行間を詰めて読みやすくした

#そして完成したものがこちら！
![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043307/1a6347ef-e22d-b8d3-8150-2267d390def8.png)
うーーーん、これまたシンプル(笑)
まぁポートフォリオとしての健康で最低限の役割を果たしているので生存権違反にはならないはず。。。

#おわりに
今回は自己紹介ページ作りました～
趣味の欄にも書きましたが大相撲めっちゃ好きなんです、小学生の時から見続けているので相撲に関するサイトでも作りたいなぁ
Xサーバーでの「max_input_vars」の設定方法

# max_input_varsとはなんぞ
PHP5.3以降、 ```max_input_vars```という物が追加されて、一度にpostできるフォームの項目が設定されている。
デフォルトでは ```max_input_vars = 1000```となっているらしい。
EC-cube3系を触っていく中で、大量の規格を登録する際になのエラーも出ずに編集ができないことがある。
規格系の登録はEC-cubeの仕様上、一度に大量の項目をPOSTするので、規格数が100個とかになると弾かれる。

# php.iniで設定変更
こういう系はもちろんphp.iniで変更できるのですが、該当のサイトはXサーバーで動いており、レンタルサーバーでのphp.iniの変更方法を備忘録として。
Xサーバーは管理画面から独自にphp.iniの変更ができるのでそこで修正する。簡単。
ただ、```max_input_vars```という項目はXサーバー上に用意されていないので、
「直接編集」から```max_input_vars = 数字```とすると、設定が無事変更されます！！

以上！！！
Pythonはどうやって文のブロックをインデントで実現しているのか？

##動機

CPythonのソースを読もうと思った動機のひとつに、文のブロックをどうやってインデントで実現しているのか、インタプリタのメカニズムはどうなっているかを解明したいというものがあった。やっと解明できたので、メモを書いておく。

リポジトリはここ：　https://github.com/python/cpython

##字句解析(トーカナイザ）のひみつ

秘密は字句解析器にあった。Pythonのソースコードからトークンの切り出しをおこなう処理の、コアの部分は `tok_get()` という関数が行っている。ソースコードではこの部分。

[tok_get() : githubへのリンク](https://github.com/python/cpython/blob/9eb11a139fac5514d8456626806a68b3e3b7eafb/Parser/tokenizer.c#L1194)

字句解析は状態を持つステートフルな処理になっていて、状態を保持する重要な構造体 `tok_state` がある。この中にどのようなデータが保持されているか理解すると、字句解析の動きが理解できるようになる。

[struct tok_state : githubへのリンク](https://github.com/python/cpython/blob/9eb11a139fac5514d8456626806a68b3e3b7eafb/Parser/tokenizer.h#L22)

インデント処理のための最も重要なデータは、この構造体`tok_state` のメンバである `indstack` というスタックである。このスタックには、処理するソースコードの最初の部分から、現在処理している部分までのインデントされたカラムの位置が積まれている。インデントが深くなるたびに、カラムの位置がpushされ、インデントが（正しく）浅くなると値がpopされる。

ちなみに、このスタックの上限はもちろん決まっていて、デフォルトは100である。よって101段以上のインデントをつけたソースコードは、エラーになる（はず）。またこの処理は巧妙に作られていて、ある部分のインデントはスペース4個、ある部分のインデントは空白2個といった、かなり変態的なソースコードでも処理でも正しく処理できる。（インデントを浅くなるとき、それまでのインデントと整合性がとれている必要がある）。次のようなソースでもエラーにはならない。

```
$ cat test_indent.py
def foo():

  def bar(): # indent 2 spaces
        pass # indent 8 spaces

def baz():
            pass # indent 12 spaces

$ ./python.exe test_indent.py
$
```

字句解析器は、インデントが変化（深くなったり、浅くなったり）したときに、ソースコード上には存在しない仮想的トークン、`INDENT` や `DEDENT` というトークンを構文解析器に渡す。これにより、構文解析器の立場からからみたPythonの文法は、伝統的な言語のようなブロックを表すためのシンボル( `{` `}` `begin` `end` などなど)を持つ言語となんら変わらないものとなる。ソースコードは以下の部分。

[仮想的トークン INDENT, DEDENT を返す処理 : githubへのリンク](https://github.com/python/cpython/blob/9eb11a139fac5514d8456626806a68b3e3b7eafb/Parser/tokenizer.c#L1290)

参考までに、PEG (Parsing Expression Grammar) による `block` の具象構文の定義はこのようになっている。

```
block[asdl_seq*] (memo):
    | NEWLINE INDENT a=statements DEDENT { a }
    | simple_stmt
    | invalid_block

```

[この部分](https://github.com/python/cpython/blob/1ba08a121a25fcf7c947d8d37e72e46dae59168c/Grammar/python.gram#L311)

なんとなく、NEWLINE(改行)の次にINDENTがきて、文が並び DEDENT が来ることがわかる。PEG は python 3.9 で採用された文法記述で詳細は [PEP 617](https://www.python.org/dev/peps/pep-0617/) を参照のこと。