Python3.12環境で出るSyntaxWarning対応¶
- Ubuntu24.04, Python3.12環境へ、OpenRTM-Python 2.0.2版をインストールし、サンプルRTCを実行した時に確認した
$ python3 ConsoleIn.py /usr/lib/python3/dist-packages/OpenRTM_aist/PortBase.py:2464: SyntaxWarning: invalid escape sequence '\p' """ /usr/lib/python3/dist-packages/OpenRTM_aist/PortBase.py:2470: SyntaxWarning: invalid escape sequence '\p' """
- 指摘されたPortBase.pyのコード部分
2463 def __init__(self, id_): 2464 """ 2465 \param id_(string) 2466 """ 2467 self._id = id_
- これはDoxygen用に \param と記述している部分で、
- Python の文字列 → \p を無効なエスケープと解釈する
- Doxygen の構文 → \param を必要としている
- OpenRTM-aist-Pythonソース全体を置換するシェルスクリプトをChatGPTに教えてもらう
- Doxygen向けのキーワードは param 以外もあるそうなので、それらも含めて一括置換する
複数のDoxygenキーワードを一括置換するスクリプト¶
- \param等の Doxygen キーワードを 一括で「単一バックスラッシュ → 二重バックスラッシュ」に変換し、
既に \\keyword になっている箇所はスキップするスクリプト
(Perl の負の後読みを使って安全に置換します)
- 対象キーワードは初期設定で以下です(必要に応じて編集する):
param, return, brief, retval, note, warning, deprecated, tparam, sa
- fix_doxygen_escapes.sh
- bash 以外で起動されたら自動で bash で再実行するガード付き版
(Ubuntu 24.04 で動作、mapfile 非依存にし、xargs -0 で安全に全 .py を処理)#!/usr/bin/env bash # Convert selected Doxygen commands like \param -> \\param in Python files, # preserving already-escaped tokens (\\param etc). # Usage: # ./fix_doxygen_escapes.sh [clone_dir] # # Default repo: OpenRTM/OpenRTM-aist-Python # --- Re-exec with bash if not already bash --- if [ -z "${BASH_VERSION:-}" ]; then exec bash "$0" "$@" fi set -euo pipefail REPO_URL="https://github.com/OpenRTM/OpenRTM-aist-Python.git" CLONE_DIR="${1:-OpenRTM-aist-Python}" # --- Customize target keywords here (no leading backslashes) --- KEYWORDS=( param return brief retval note warning deprecated tparam sa ) # -------------------------------------------------------------- command -v git >/dev/null 2>&1 || { echo "ERROR: git not found."; exit 1; } command -v perl >/dev/null 2>&1 || { echo "ERROR: perl not found."; exit 1; } command -v grep >/dev/null 2>&1 || { echo "ERROR: grep not found."; exit 1; } command -v find >/dev/null 2>&1 || { echo "ERROR: find not found."; exit 1; } command -v xargs >/dev/null 2>&1 || { echo "ERROR: xargs not found."; exit 1; } echo "Cloning repo..." git clone --depth 1 "$REPO_URL" "$CLONE_DIR" cd "$CLONE_DIR" BRANCH="fix/docstring-escape-doxygen" echo "Creating branch $BRANCH ..." git checkout -b "$BRANCH" echo "Building keyword regex..." KEYWORD_RE="$(printf '%s|' "${KEYWORDS[@]}")" KEYWORD_RE="${KEYWORD_RE%|}" echo "Finding Python files and applying replacements for: ${KEYWORDS[*]}" # Replace only single-backslash tokens: (?<!\\)\(backslash)(param|...)\b -> \\$1 # (negative lookbehind ensures already-escaped \\keyword are skipped) find . -type d -name .git -prune -o \ -type d -name venv -prune -o \ -type f -name "*.py" -print0 | xargs -0 -r perl -0777 -i -pe "s/(?<!\\\\)\\\\(${KEYWORD_RE})\\b/\\\\\\\\\\1/g" echo "Replacement done." echo echo "Summary of changes:" git status --porcelain | awk '$1 ~ /M/ {print $2}' echo git diff --stat || true echo echo "Quick scan (candidates with single backslash, for review):" # If your grep supports PCRE (-P), this precisely lists remaining single-backslash tokens. if grep -R --line-number -P "(?<!\\\\)\\\\(${KEYWORD_RE})\\b" --include="*.py" . >/dev/null 2>&1; then grep -R --line-number -P "(?<!\\\\)\\\\(${KEYWORD_RE})\\b" --include="*.py" . || true else # Fallback: broader hint (may include already-escaped ones) grep -R --line-number --include="*.py" -E "\\\\(${KEYWORD_RE})\\b" . || true fi echo echo "Already-escaped double-backslash occurrences (for reference):" grep -R --line-number --include="*.py" -E "\\\\\\\\(${KEYWORD_RE})\\b" . || true echo read -r -p "Commit changes? [y/N] " ans if [[ "${ans:-N}" =~ ^[Yy]$ ]]; then git add -A git commit -m "docs: escape Doxygen \\keyword as \\\\keyword in Python docstrings (${KEYWORDS[*]})" echo "Committed. You can now push the branch:" echo " git push -u origin $BRANCH" else echo "Changes are left unstaged. Review with 'git diff' if needed." fi
- bash 以外で起動されたら自動で bash で再実行するガード付き版
一括置換結果¶
$ ./fix_doxygen_escapes.sh Cloning repo... Cloning into 'OpenRTM-aist-Python'... remote: Enumerating objects: 516, done. remote: Counting objects: 100% (516/516), done. remote: Compressing objects: 100% (352/352), done. remote: Total 516 (delta 194), reused 373 (delta 151), pack-reused 0 (from 0) Receiving objects: 100% (516/516), 766.54 KiB | 907.00 KiB/s, done. Resolving deltas: 100% (194/194), done. Creating branch fix/docstring-escape-doxygen ... Switched to a new branch 'fix/docstring-escape-doxygen' Building keyword regex... Finding Python files and applying replacements for: param return brief retval note warning deprecated tparam sa Replacement done. Summary of changes: OpenRTM_aist/CorbaNaming.py OpenRTM_aist/CorbaPort.py OpenRTM_aist/DataFlowComponentBase.py OpenRTM_aist/DefaultConfiguration.py OpenRTM_aist/ECFactory.py OpenRTM_aist/PortBase.py OpenRTM_aist/Process.py OpenRTM_aist/examples/AutoTest/AutoTestIn.py OpenRTM_aist/examples/AutoTest/AutoTestOut.py OpenRTM_aist/examples/TkJoyStick/TkJoyStickComp.py OpenRTM_aist/ext/ssl/test/test_SSLTransport.py OpenRTM_aist/CorbaNaming.py | 2 +- OpenRTM_aist/CorbaPort.py | 2 +- OpenRTM_aist/DataFlowComponentBase.py | 2 +- OpenRTM_aist/DefaultConfiguration.py | 2 +- OpenRTM_aist/ECFactory.py | 2 +- OpenRTM_aist/PortBase.py | 30 +++++++++++++++--------------- OpenRTM_aist/Process.py | 2 +- OpenRTM_aist/examples/AutoTest/AutoTestIn.py | 6 +++--- OpenRTM_aist/examples/AutoTest/AutoTestOut.py | 4 ++-- OpenRTM_aist/examples/TkJoyStick/TkJoyStickComp.py | 2 +- OpenRTM_aist/ext/ssl/test/test_SSLTransport.py | 2 +- 11 files changed, 28 insertions(+), 28 deletions(-) Quick scan (candidates with single backslash, for review): ./OpenRTM_aist/CorbaPort.py:6:# \\brief CorbaPort class ./OpenRTM_aist/ECFactory.py:25:# \\param ec 破棄対象ExecutionContextのインスタンス ./OpenRTM_aist/DefaultConfiguration.py:6:# \\brief RTC manager default configuration ./OpenRTM_aist/CorbaNaming.py:7:# \\brief CORBA naming service helper class ./OpenRTM_aist/examples/TkJoyStick/TkJoyStickComp.py:78: \\brief Converting from canvas data to MobileRobotCanvas data ./OpenRTM_aist/examples/AutoTest/AutoTestIn.py:86: \\brief ModuleDescription ./OpenRTM_aist/examples/AutoTest/AutoTestIn.py:92: \\brief constructor ./OpenRTM_aist/examples/AutoTest/AutoTestIn.py:93: \\param manager Maneger Object ./OpenRTM_aist/examples/AutoTest/AutoTestOut.py:7: \\brief ModuleDescription ./OpenRTM_aist/examples/AutoTest/AutoTestOut.py:58: \\brief ModuleDescription ./OpenRTM_aist/DataFlowComponentBase.py:6:# \\brief DataFlowParticipant RT-Component base class ./OpenRTM_aist/ext/ssl/test/test_SSLTransport.py:6:# \\brief ./OpenRTM_aist/Process.py:7:# \\brief Process handling functions ./OpenRTM_aist/PortBase.py:2465: \\param id_(string) ./OpenRTM_aist/PortBase.py:2471: \\param cprof(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2485: \\param port_ref(RTC.PortService) ./OpenRTM_aist/PortBase.py:2491: \\param port_ref(RTC.PortService) ./OpenRTM_aist/PortBase.py:2505: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2506: \\param prof(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2514: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2531: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2532: \\param prof(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2540: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2557: \\param p(OpenRTM_aist.PortBase) ./OpenRTM_aist/PortBase.py:2564: \\param p(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2580: \\param name(string) ./OpenRTM_aist/PortBase.py:2581: \\param pol(RTC.PortInterfacePolarity) ./OpenRTM_aist/PortBase.py:2588: \\param prof(RTC.PortInterfaceProfile) Already-escaped double-backslash occurrences (for reference): ./OpenRTM_aist/CorbaPort.py:6:# \\brief CorbaPort class ./OpenRTM_aist/ECFactory.py:25:# \\param ec 破棄対象ExecutionContextのインスタンス ./OpenRTM_aist/DefaultConfiguration.py:6:# \\brief RTC manager default configuration ./OpenRTM_aist/CorbaNaming.py:7:# \\brief CORBA naming service helper class ./OpenRTM_aist/examples/TkJoyStick/TkJoyStickComp.py:78: \\brief Converting from canvas data to MobileRobotCanvas data ./OpenRTM_aist/examples/AutoTest/AutoTestIn.py:86: \\brief ModuleDescription ./OpenRTM_aist/examples/AutoTest/AutoTestIn.py:92: \\brief constructor ./OpenRTM_aist/examples/AutoTest/AutoTestIn.py:93: \\param manager Maneger Object ./OpenRTM_aist/examples/AutoTest/AutoTestOut.py:7: \\brief ModuleDescription ./OpenRTM_aist/examples/AutoTest/AutoTestOut.py:58: \\brief ModuleDescription ./OpenRTM_aist/DataFlowComponentBase.py:6:# \\brief DataFlowParticipant RT-Component base class ./OpenRTM_aist/ext/ssl/test/test_SSLTransport.py:6:# \\brief ./OpenRTM_aist/Process.py:7:# \\brief Process handling functions ./OpenRTM_aist/PortBase.py:2465: \\param id_(string) ./OpenRTM_aist/PortBase.py:2471: \\param cprof(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2485: \\param port_ref(RTC.PortService) ./OpenRTM_aist/PortBase.py:2491: \\param port_ref(RTC.PortService) ./OpenRTM_aist/PortBase.py:2505: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2506: \\param prof(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2514: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2531: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2532: \\param prof(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2540: \\param p(RTC.PortService) ./OpenRTM_aist/PortBase.py:2557: \\param p(OpenRTM_aist.PortBase) ./OpenRTM_aist/PortBase.py:2564: \\param p(RTC.ConnectorProfile) ./OpenRTM_aist/PortBase.py:2580: \\param name(string) ./OpenRTM_aist/PortBase.py:2581: \\param pol(RTC.PortInterfacePolarity) ./OpenRTM_aist/PortBase.py:2588: \\param prof(RTC.PortInterfaceProfile) Commit changes? [y/N] Changes are left unstaged. Review with 'git diff' if needed.