Skip to content

Commit 46713bf

Browse files
Lint rule to check for incorrect logging in Python modules (project-chip#41112)
* Lint rule to check for incorrect logging in Python modules * Fix logging in Python controller * Fix logging in testing infrastructure * Fix logging in scripts modules * Migrate away from deprecated 'logging.warn' method * Restyled by isort * Fix lint issues * Change case according to copilot suggestion --------- Co-authored-by: Restyled.io <[email protected]>
1 parent ec8f50e commit 46713bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+479
-418
lines changed

.github/workflows/lint.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,18 @@ jobs:
426426
# Ignore uses of `System::Clock::Literals`, because that's the only way to have things using _ms32 or whatnot
427427
# in a header file.
428428
git grep -I -n -e '^using namespace' --and --not -e 'System::Clock::Literals' -- './**/*.h' ':(exclude)src/platform/*/BLEManager*.h' ':(exclude)./examples' ':(exclude)./third_party' && exit 1 || exit 0
429+
430+
# git grep exits with 0 if it finds a match, but we want
431+
# to fail (exit nonzero) on match.
432+
- name:
433+
Check for a direct use of the "logging" module for logging.
434+
Instead one should use a local logger with a name based on
435+
the module name.
436+
if: always()
437+
run: |
438+
git grep -I -n -E -e 'logging[.](log|debug|info|warn|warning|error|critical|exception)[(]' -- \
439+
'scripts/py_matter_idl' \
440+
'scripts/py_matter_yamltests' \
441+
'src/controller/python' \
442+
'src/python_testing/matter_testing_infrastructure' \
443+
&& exit 1 || exit 0

scripts/build/build/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def Build(self):
7676

7777
def CleanOutputDirectories(self):
7878
for builder in self.builders:
79-
logging.warn('Cleaning %s', builder.output_dir)
79+
logging.warning('Cleaning %s', builder.output_dir)
8080
if os.path.exists(builder.output_dir):
8181
shutil.rmtree(builder.output_dir)
8282

scripts/py_matter_idl/matter/idl/backwards_compatibility.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
from matter.idl.matter_idl_parser import CreateParser
2525
from matter.idl.matter_idl_types import ApiMaturity, Attribute, Bitmap, Cluster, Command, Enum, Event, Field, Idl, Struct
2626

27+
LOGGER = logging.getLogger(__name__)
28+
2729

2830
class Compatibility(enum.Enum):
2931
UNKNOWN = enum.auto()
@@ -70,10 +72,9 @@ def __init__(self, original: Idl, updated: Idl):
7072
self._updated_idl = updated
7173
self.compatible = Compatibility.UNKNOWN
7274
self.errors: List[str] = []
73-
self.logger = logging.getLogger(__name__)
7475

7576
def _mark_incompatible(self, reason: str):
76-
self.logger.error(reason)
77+
LOGGER.error(reason)
7778
self.errors.append(reason)
7879
self.compatible = Compatibility.INCOMPATIBLE
7980

@@ -157,7 +158,7 @@ def _check_event_compatible(self, cluster_name: str, event: Event, updated_event
157158
f"Event {cluster_name}::{event.name}", event.fields, updated_event.fields)
158159

159160
def _check_command_compatible(self, cluster_name: str, command: Command, updated_command: Optional[Command]):
160-
self.logger.debug(f" Checking command {cluster_name}::{command.name}")
161+
LOGGER.debug(f" Checking command {cluster_name}::{command.name}")
161162
if not updated_command:
162163
self._mark_incompatible(
163164
f"Command {cluster_name}::{command.name} was removed")
@@ -180,7 +181,7 @@ def _check_command_compatible(self, cluster_name: str, command: Command, updated
180181
f"Command {cluster_name}::{command.name} qualities changed from {command.qualities} to {updated_command.qualities}")
181182

182183
def _check_struct_compatible(self, cluster_name: str, original: Struct, updated: Optional[Struct]):
183-
self.logger.debug(f" Checking struct {original.name}")
184+
LOGGER.debug(f" Checking struct {original.name}")
184185
if not updated:
185186
self._mark_incompatible(
186187
f"Struct {cluster_name}::{original.name} has been deleted.")
@@ -202,7 +203,7 @@ def _check_struct_compatible(self, cluster_name: str, original: Struct, updated:
202203
f"Struct {cluster_name}::{original.name} has modified qualities")
203204

204205
def _check_attribute_compatible(self, cluster_name: str, original: Attribute, updated: Optional[Attribute]):
205-
self.logger.debug(
206+
LOGGER.debug(
206207
f" Checking attribute {cluster_name}::{original.definition.name}")
207208
if not updated:
208209
self._mark_incompatible(
@@ -293,7 +294,7 @@ def _check_cluster_list_compatible(self, original: List[Cluster], updated: List[
293294
self._check_cluster_compatible(original_cluster, updated_cluster)
294295

295296
def _check_cluster_compatible(self, original_cluster: Cluster, updated_cluster: Optional[Cluster]):
296-
self.logger.debug(
297+
LOGGER.debug(
297298
f"Checking cluster {original_cluster.name}")
298299
if not updated_cluster:
299300
self._mark_incompatible(
@@ -377,10 +378,10 @@ def main(log_level, old_idl, new_idl):
377378
fmt='%(asctime)s %(levelname)-7s %(message)s',
378379
)
379380

380-
logging.info("Parsing OLD idl from %s" % old_idl)
381+
LOGGER.info("Parsing OLD idl from %s" % old_idl)
381382
old_tree = CreateParser().parse(open(old_idl, "rt").read())
382383

383-
logging.info("Parsing NEW idl from %s" % new_idl)
384+
LOGGER.info("Parsing NEW idl from %s" % new_idl)
384385
new_tree = CreateParser().parse(open(new_idl, "rt").read())
385386

386387
if not is_backwards_compatible(original=old_tree, updated=new_tree):

scripts/py_matter_idl/matter/idl/data_model_xml/__init__.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
from matter.idl.matter_idl_parser import CreateParser
2828
from matter.idl.matter_idl_types import Idl
2929

30+
LOGGER = logging.getLogger(__name__)
31+
3032

3133
class ParseHandler(xml.sax.handler.ContentHandler):
3234
"""A parser for data model XML data definitions.
@@ -73,13 +75,13 @@ def endDocument(self):
7375
raise Exception("Unexpected nesting!")
7476

7577
def startElement(self, name: str, attrs):
76-
logging.debug("ELEMENT START: %r / %r" % (name, attrs))
78+
LOGGER.debug("ELEMENT START: %r / %r" % (name, attrs))
7779
self._context.path.push(name)
7880
self._processing_stack.append(
7981
self._processing_stack[-1].GetNextProcessor(name, attrs))
8082

8183
def endElement(self, name: str):
82-
logging.debug("ELEMENT END: %r" % name)
84+
LOGGER.debug("ELEMENT END: %r" % name)
8385

8486
last = self._processing_stack.pop()
8587
last.EndProcessing()
@@ -119,16 +121,16 @@ def ParseXmls(sources: List[ParseSource], include_meta_data=True) -> Idl:
119121
handler = ParseHandler(include_meta_data=include_meta_data)
120122

121123
for source in sources:
122-
logging.info('Parsing %s...' % source.source_file_name)
124+
LOGGER.info('Parsing %s...' % source.source_file_name)
123125
handler.PrepareParsing(source.source_file_name)
124126

125127
parser = xml.sax.make_parser()
126128
parser.setContentHandler(handler)
127129
try:
128130
parser.parse(source.source)
129131
except AssertionError as e:
130-
logging.error("AssertionError %s at %r", e,
131-
handler._context.GetCurrentLocationMeta())
132+
LOGGER.error("AssertionError %s at %r", e,
133+
handler._context.GetCurrentLocationMeta())
132134
raise
133135

134136
return handler.Finish()
@@ -223,15 +225,15 @@ def main(log_level, no_print, output, compare, compare_output, filenames):
223225
)
224226

225227
if (compare is None) != (compare_output is None):
226-
logging.error(
228+
LOGGER.error(
227229
"Either both or none of --compare AND --compare-output must be set")
228230
sys.exit(1)
229231

230-
logging.info("Starting to parse ...")
232+
LOGGER.info("Starting to parse ...")
231233

232234
sources = [ParseSource(source=name) for name in filenames]
233235
data = ParseXmls(sources)
234-
logging.info("Parse completed")
236+
LOGGER.info("Parse completed")
235237

236238
if compare:
237239
other_idl = CreateParser(skip_meta=True).parse(

scripts/py_matter_idl/matter/idl/data_model_xml/handlers/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from .handlers import ClusterHandler
2323
from .parsing import NormalizeName
2424

25-
LOGGER = logging.getLogger('data-model-xml-data-parsing')
25+
LOGGER = logging.getLogger(__name__)
2626

2727

2828
def contains_valid_cluster_id(attrs: AttributesImpl) -> bool:

scripts/py_matter_idl/matter/idl/data_model_xml/handlers/context.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
from matter.idl.matter_idl_types import Cluster, Idl, ParseMetaData
2020

21+
LOGGER = logging.getLogger(__name__)
22+
2123

2224
class IdlPostProcessor:
2325
"""Defines a callback that will apply after an entire parsing
@@ -119,7 +121,7 @@ def MarkTagNotHandled(self):
119121
if where:
120122
msg = msg + " at " + where
121123

122-
logging.warning(msg)
124+
LOGGER.warning(msg)
123125
self._not_handled.add(path)
124126

125127
def AddIdlPostProcessor(self, processor: IdlPostProcessor, has_priority: bool = False):

scripts/py_matter_idl/matter/idl/data_model_xml/handlers/derivation.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16+
1617
import dataclasses
1718
import logging
1819
from typing import Iterable, Optional, Protocol, TypeVar
@@ -22,7 +23,7 @@
2223
from .context import Context, IdlPostProcessor
2324
from .parsing import NormalizeName
2425

25-
LOGGER = logging.getLogger('data-model-xml-data-parsing')
26+
LOGGER = logging.getLogger(__name__)
2627

2728
T = TypeVar("T")
2829

scripts/py_matter_idl/matter/idl/data_model_xml/handlers/handlers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from .parsing import (ApplyConstraint, AttributesToAttribute, AttributesToBitFieldConstantEntry, AttributesToCommand,
2727
AttributesToEvent, AttributesToField, NormalizeDataType, NormalizeName, ParseInt, StringToAccessPrivilege)
2828

29-
LOGGER = logging.getLogger('data-model-xml-parser')
29+
LOGGER = logging.getLogger(__name__)
3030

3131

3232
def is_unused_name(attrs: AttributesImpl):
@@ -267,8 +267,8 @@ def GetNextProcessor(self, name: str, attrs: AttributesImpl):
267267
elif name == "item":
268268
for key in ["name", "value"]:
269269
if key not in attrs:
270-
logging.error("Enumeration %s entry is missing a '%s' entry (at %r)",
271-
self._enum.name, key, self.context.GetCurrentLocationMeta())
270+
LOGGER.error("Enumeration %s entry is missing a '%s' entry (at %r)",
271+
self._enum.name, key, self.context.GetCurrentLocationMeta())
272272
# bad entry, nothing I can do about it.
273273
return BaseHandler(self.context, handled=HandledDepth.ENTIRE_TREE)
274274

scripts/py_matter_idl/matter/idl/data_model_xml/handlers/parsing.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from matter.idl.generators.type_definitions import GetDataTypeSizeInBits, IsSignedDataType
2222
from matter.idl.matter_idl_types import AccessPrivilege, Attribute, Command, ConstantEntry, DataType, Event, EventPriority, Field
2323

24-
LOGGER = logging.getLogger('data-model-xml-data-parsing')
24+
LOGGER = logging.getLogger(__name__)
2525

2626

2727
@dataclass
@@ -170,7 +170,7 @@ def NormalizeName(name: str) -> str:
170170

171171
while '_' in name:
172172
idx = name.find('_')
173-
name = name[:idx] + name[idx+1].upper() + name[idx+2:]
173+
name = name[:idx] + name[idx + 1].upper() + name[idx + 2:]
174174

175175
return name
176176

@@ -271,8 +271,8 @@ def AttributesToEvent(attrs: AttributesImpl) -> Event:
271271
elif attrs["priority"] == "debug":
272272
priority = EventPriority.DEBUG
273273
elif attrs["priority"] == "desc":
274-
LOGGER.warn("Found an event with 'desc' priority: %s" %
275-
[item for item in attrs.items()])
274+
LOGGER.warning("Found an event with 'desc' priority: %s" %
275+
[item for item in attrs.items()])
276276
priority = EventPriority.CRITICAL
277277
else:
278278
raise Exception("UNKNOWN event priority: %r" % attrs["priority"])
@@ -302,7 +302,7 @@ def AttributesToCommand(attrs: AttributesImpl) -> Command:
302302
assert "name" in attrs
303303

304304
if "response" not in attrs:
305-
LOGGER.warn(f"Command {attrs['name']} has no response set.")
305+
LOGGER.warning(f"Command {attrs['name']} has no response set.")
306306
# Matter IDL has no concept of "no response sent"
307307
# Example is DoorLock::"Operating Event Notification"
308308
#
@@ -362,4 +362,4 @@ def ApplyConstraint(attrs, field: Field):
362362
field.data_type.min_length = ParseOptionalInt(attrs["from"])
363363
field.data_type.max_length = ParseOptionalInt(attrs["to"])
364364
else:
365-
logging.error(f"UNKNOWN constraint type {constraint_type}")
365+
LOGGER.error(f"UNKNOWN constraint type {constraint_type}")

scripts/py_matter_idl/matter/idl/generators/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
from .filters import RegisterCommonFilters
2424
from .storage import GeneratorStorage
2525

26+
LOGGER = logging.getLogger(__name__)
27+
2628

2729
class CodeGenerator:
2830
"""
@@ -99,11 +101,11 @@ def internal_render_one_output(self, template_path: str, output_file_name: str,
99101
output_file_name - File name that the template is to be generated to.
100102
vars - variables used for template generation
101103
"""
102-
logging.info("File to be generated: %s" % output_file_name)
104+
LOGGER.info("File to be generated: %s" % output_file_name)
103105
if self.dry_run:
104106
return
105107

106-
logging.info(f"Template path: {template_path}, CWD: {os.getcwd()}")
108+
LOGGER.info(f"Template path: {template_path}, CWD: {os.getcwd()}")
107109
rendered = self.jinja_env.get_template(template_path).render(vars)
108110

109111
# Report regardless if it has changed or not. This is because even if
@@ -112,6 +114,6 @@ def internal_render_one_output(self, template_path: str, output_file_name: str,
112114
self.storage.report_output_file(output_file_name)
113115

114116
if rendered == self.storage.get_existing_data(output_file_name):
115-
logging.info("File content not changed")
117+
LOGGER.info("File content not changed")
116118
else:
117119
self.storage.write_new_data(output_file_name, rendered)

0 commit comments

Comments
 (0)