環境
$ python --version
Python 3.11.2
$ ruff --version
ruff 0.0.264
バージョン: 1.77.3
コミット: 704ed70d4fd1c6bd6342c436f1ede30d1cff4710
日付: 2023-04-12T09:16:52.732Z
Electron: 19.1.11
Chromium: 102.0.5005.196
Node.js: 16.14.2
V8: 10.2.154.26-electron.0
OS: Linux x64 5.15.0-70-generic
Sandboxed: No
# confusables.txt
# Date: 2022-08-26, 16:49:08 GMT
# © 2022 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Security Mechanisms for UTS #39
# Version: 15.0.0
#
# For documentation and usage, see https://www.unicode.org/reports/tr39
起きたこと
以下のPythonコードを静的解析ツールRuffでチェックすると、以下のエラーが発生しました。
"""
annotation
アノテーション
"""
$ ruff check sample.py --select RUF
sample.py:2:1: RUF002 [*] Docstring contains ambiguous unicode character `a` (did you mean `a`?)
sample.py:3:2: RUF002 [*] Docstring contains ambiguous unicode character `ノ` (did you mean `/`?)Found 2 errors.
[*] 2 potentially fixable with the --fix option.
全角文字a
を半角文字a
に変えるのは納得できるのですが、カタカナのノ
をスラッシュ/
に変えるとは、どういうことなのでしょうか?
ambiguous unicode characterとは何か?
よく分かりませんでした。
"ambiguous unicode character"の判定はどこで実装されているのか?
以下の関数で、confusableな文字かどうかを判定しています。
定数CONFUSABLES
には、警告対象の"ambiguous unicode character"と、それに対する提案対象の文字が定義されています。
/// See: https://github.com/microsoft/vscode/blob/095ddabc52b82498ee7f718a34f9dd11d59099a8/src/vs/base/common/strings.ts#L1195
static CONFUSABLES: Lazy<BTreeMap<u32, u32>> = Lazy::new(|| {
BTreeMap::from([
(8232, 32),
コメントには、https://github.com/microsoft/vscode/blob/095ddabc52b82498ee7f718a34f9dd11d59099a8/src/vs/base/common/strings.ts#L1195 を参照と書いてあります。
つまりVSCodeのコードを移植したようです。
Unicode Confusables
Unicodeには視覚的に似ている"confusable"な文字が定義されています。
The data in [confusables] provide a mechanism for determining when two strings are visually confusable. The data in these files may be refined and extended over time. For information on handling modifications over time, see Section 2.10.1, Backward Compatibility in Unicode Technical Report #36, "Unicode Security Considerations" [UTR36] and the Migration section of this document.
RuffやVSCodeは、"Unicode confusables"を参照しているようです。
上記のページには、以下の様に記載されていました。"ノ"以外にもスラッシュ/
に似ている文字はたくさんありました。
1735 ; 002F ; MA #* ( ᜵ → / ) PHILIPPINE SINGLE PUNCTUATION → SOLIDUS #
2041 ; 002F ; MA #* ( ⁁ → / ) CARET INSERTION POINT → SOLIDUS #
2215 ; 002F ; MA #* ( ∕ → / ) DIVISION SLASH → SOLIDUS #
2044 ; 002F ; MA #* ( ⁄ → / ) FRACTION SLASH → SOLIDUS #
2571 ; 002F ; MA #* ( ╱ → / ) BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT → SOLIDUS #
27CB ; 002F ; MA #* ( ⟋ → / ) MATHEMATICAL RISING DIAGONAL → SOLIDUS #
29F8 ; 002F ; MA #* ( ⧸ → / ) BIG SOLIDUS → SOLIDUS #
1D23A ; 002F ; MA #* ( 𝈺 → / ) GREEK INSTRUMENTAL NOTATION SYMBOL-47 → SOLIDUS #
31D3 ; 002F ; MA #* ( ㇓ → / ) CJK STROKE SP → SOLIDUS # →⼃→
3033 ; 002F ; MA # ( 〳 → / ) VERTICAL KANA REPEAT MARK UPPER HALF → SOLIDUS #
2CC6 ; 002F ; MA # ( Ⳇ → / ) COPTIC CAPITAL LETTER OLD COPTIC ESH → SOLIDUS #
30CE ; 002F ; MA # ( ノ → / ) KATAKANA LETTER NO → SOLIDUS # →⼃→
4E3F ; 002F ; MA # ( 丿 → / ) CJK UNIFIED IDEOGRAPH-4E3F → SOLIDUS # →⼃→
2F03 ; 002F ; MA #* ( ⼃ → / ) KANGXI RADICAL SLASH → SOLIDUS #
ただし、VSCodeは"Unicode confusables"をすべて取り込んでいる訳ではないようです。
"Unicode confusables"には、カタカナのカ
や平仮名のく
も定義されています。
30AB ; 529B ; MA # ( カ → 力 ) KATAKANA LETTER KA → CJK UNIFIED IDEOGRAPH-529B # →⼒→
...
304F ; 276C ; MA # ( く → ❬ ) HIRAGANA LETTER KU → MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT # →㇛→→⟨→→〈→
しかしRuffは片仮名のノ
だけを警告します。
"""
あいうえお
かきくけこ
さしすせそ
たちつてと
なにぬねの
はひふへほ
まみむめも
やゆよ
らりるれろ
わゐゑを
ん
アイウエオ
カキクケコ
サシスセソ
タチツテト
ナニヌネノ
ハヒフヘホ
マミムメモ
ヤユヨ
ラリルレロ
ワヰヱヲ
ン
"""
$ ruff check sample2.py --select RUF
sample2.py:17:5: RUF002 [*] Docstring contains ambiguous unicode character `ノ` (did you mean `/`?)
Found 1 error.
[*] 1 potentially fixable with the --fix option.
補足
RuffにIssueを作りました。
参考サイト