python: Silence yapf import triggered log messages
Importing yapf in any Python file was triggering these log messages
during bootstrap and activate on Linux and Mac:
Generating grammar tables from
./.environment/cipd/packages/python/lib/python3.9/lib2to3/Grammar.txt
Writing grammar tables to
./.environment/cipd/packages/python/lib/python3.9/lib2to3/Grammar3.9.5.final.0.pickle
Writing failed: [Errno 13] Permission denied:
'./.environment/cipd/packages/python/lib/python3.9/lib2to3/Grammar3.9.5.final.0.pickle'
Generating grammar tables from
./.environment/cipd/packages/python/lib/python3.9/lib2to3/PatternGrammar.txt
Writing grammar tables to
./.environment/cipd/packages/python/lib/python3.9/lib2to3/PatternGrammar3.9.5.final.0.pickle
Writing failed: [Errno 13] Permission denied:
'./.environment/cipd/packages/python/lib/python3.9/lib2to3/PatternGrammar3.9.5.final.0.pickle'
This CL modifies pw_env_setup to chmoding those pickle files to be
writeable. All CIPD packages are put in place as read only.
Additionally those log messages are suppressed when importing yapf
in python_protos.py.
Bug: b/236166970
Change-Id: I41ca5ca6dd435a9fb534983d9aa967a31314ff62
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/98520
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Anthony DiGirolamo <tonymd@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
index b8841b9..73c751f 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
@@ -24,6 +24,7 @@
import shutil
import subprocess
import sys
+import stat
import tempfile
# Grabbing datetime string once so it will always be the same for all GnTarget
@@ -130,6 +131,24 @@
shutil.rmtree(venv_path)
+def _check_python_install_permissions(python):
+ # These pickle files are not included on windows.
+ # The path on windows is environment/cipd/packages/python/bin/Lib/lib2to3/
+ if platform.system().lower() == 'windows':
+ return
+
+ # Make any existing lib2to3 pickle files read+write. This is needed for
+ # importing yapf.
+ lib2to3_path = os.path.join(os.path.dirname(os.path.dirname(python)),
+ 'lib', 'python3.9', 'lib2to3')
+ pickle_file_paths = list(file_path
+ for file_path in os.listdir(lib2to3_path)
+ if '.pickle' in file_path)
+ for pickle_file in pickle_file_paths:
+ pickle_full_path = os.path.join(lib2to3_path, pickle_file)
+ os.chmod(pickle_full_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
+
+
def install( # pylint: disable=too-many-arguments
project_root,
venv_path,
@@ -175,6 +194,7 @@
pyvenv_cfg = os.path.join(venv_path, 'pyvenv.cfg')
+ _check_python_install_permissions(python)
_check_venv(python, version, venv_path, pyvenv_cfg)
if full_envsetup or not os.path.exists(pyvenv_cfg):
diff --git a/pw_protobuf_compiler/py/pw_protobuf_compiler/python_protos.py b/pw_protobuf_compiler/py/pw_protobuf_compiler/python_protos.py
index 5030051..c8f080d 100644
--- a/pw_protobuf_compiler/py/pw_protobuf_compiler/python_protos.py
+++ b/pw_protobuf_compiler/py/pw_protobuf_compiler/python_protos.py
@@ -25,7 +25,26 @@
from typing import (Dict, Generic, Iterable, Iterator, List, NamedTuple, Set,
Tuple, TypeVar, Union)
-from yapf.yapflib import yapf_api # type: ignore[import]
+# Temporarily set the root logger level to critical while importing yapf.
+# This silences INFO level messages from
+# .environment/cipd/packages/python/lib/python3.9/lib2to3/driver.py
+# when it writes Grammar3.*.pickle and PatternGrammar3.*.pickle files.
+_original_level = 0
+for handler in logging.getLogger().handlers:
+ if type(handler) == logging.StreamHandler: # pylint: disable=unidiomatic-typecheck
+ if handler.level > _original_level:
+ _original_level = handler.level
+ handler.level = logging.CRITICAL
+
+from yapf.yapflib import yapf_api # type: ignore[import] # pylint: disable=wrong-import-position
+
+# Restore the original stderr/out log handler level.
+for handler in logging.getLogger().handlers:
+ # Must use type() check here since isinstance returns True for FileHandlers
+ # and StreamHandler: isinstance(logging.FileHandler, logging.StreamHandler)
+ if type(handler) == logging.StreamHandler: # pylint: disable=unidiomatic-typecheck
+ handler.level = _original_level
+del _original_level
_LOG = logging.getLogger(__name__)